557ay(绘制虚线.html)

本文介绍了一种使用HTML5 Canvas API绘制虚线的方法。通过设置线段样式和偏移量,可以创建出美观的虚线效果。文章提供了具体的代码示例,包括如何设置线段的长度和间距。

《2019年4月14日》【连续 557天】

标题:绘制虚线.html;
内容:
 

 var myCanvas = document.querySelector('canvas');
    var ctx = myCanvas.getContext('2d');

    /*画线*/
    ctx.moveTo(100,100.5);
    ctx.lineTo(300,100.5);
    /*[5,10] 数组是用来描述你的排列方式的*/
    ctx.setLineDash([20]);
    /*获取虚线的排列方式 获取的是不重复的那一段的排列方式*/
    console.log(ctx.getLineDash());

    /*如果是正的值 往后偏移*/
    /*如果是负的值 往前偏移*/
    ctx.lineDashOffset = -20;

    ctx.stroke();

 

#include <Windows.h> #include <string> #include <vector> #include <sstream> // 定义控件ID #define ID_EDIT_AX 101 #define ID_EDIT_AY 102 #define ID_EDIT_BX 103 #define ID_EDIT_BY 104 #define ID_BUTTON_DRAW 105 #define ID_BUTTON_CLEAR 106 // 存储点坐标的结构体 struct Point { float x = 0.0f; float y = 0.0f; bool valid = false; }; // 全局变量存储点A和B Point g_pointA; Point g_pointB; // 窗口过程函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); // 获取客户区尺寸 RECT rect; GetClientRect(hWnd, &rect); int width = rect.right - rect.left; int height = rect.bottom - rect.top; // 设置坐标系原点在左下角 int originX = 50; // 左边距 int originY = height - 50; // 下边距 // 创建白色笔用于坐标轴 HPEN hAxisPen = CreatePen(PS_SOLID, 2, RGB(255, 255, 255)); HPEN hOldPen = (HPEN)SelectObject(hdc, hAxisPen); // 绘制X轴(带箭头) MoveToEx(hdc, originX, originY, NULL); LineTo(hdc, width - 20, originY); // X轴主线段 // X轴箭头 LineTo(hdc, width - 30, originY - 5); MoveToEx(hdc, width - 20, originY, NULL); LineTo(hdc, width - 30, originY + 5); // 绘制Y轴(带箭头) MoveToEx(hdc, originX, originY, NULL); LineTo(hdc, originX, 20); // Y轴主线段 // Y轴箭头 LineTo(hdc, originX - 5, 30); MoveToEx(hdc, originX, 20, NULL); LineTo(hdc, originX + 5, 30); // 创建虚线笔用于网格线 HPEN hGridPen = CreatePen(PS_DOT, 1, RGB(100, 100, 100)); SelectObject(hdc, hGridPen); // 绘制网格线(每50像素一条) for (int x = originX + 50; x < width - 20; x += 50) { MoveToEx(hdc, x, originY, NULL); LineTo(hdc, x, 20); } for (int y = originY - 50; y > 20; y -= 50) { MoveToEx(hdc, originX, y, NULL); LineTo(hdc, width - 20, y); } // 恢复原始笔 SelectObject(hdc, hOldPen); DeleteObject(hAxisPen); DeleteObject(hGridPen); // 设置文本颜色为白色 SetTextColor(hdc, RGB(255, 255, 255)); SetBkColor(hdc, RGB(0, 0, 0)); // 黑色背景 // 绘制刻度标记 for (int i = 1; i <= 10; i++) { int xPos = originX + i * 50; int yPos = originY - i * 50; // X轴刻度 MoveToEx(hdc, xPos, originY - 5, NULL); LineTo(hdc, xPos, originY + 5); // Y轴刻度 MoveToEx(hdc, originX - 5, yPos, NULL); LineTo(hdc, originX + 5, yPos); // 绘制刻度值 std::wstring label = std::to_wstring(i); TextOut(hdc, xPos - 5, originY + 10, label.c_str(), label.length()); TextOut(hdc, originX - 25, yPos - 8, label.c_str(), label.length()); } // 绘制坐标轴标签 TextOut(hdc, width - 15, originY - 15, L"X", 1); TextOut(hdc, originX - 15, 15, L"Y", 1); TextOut(hdc, originX - 10, originY + 10, L"0", 1); // 如果点A和点B有效,绘制它们并连接 if (g_pointA.valid && g_pointB.valid) { // 转换为屏幕坐标 int screenAx = originX + static_cast<int>(g_pointA.x * 50); int screenAy = originY - static_cast<int>(g_pointA.y * 50); int screenBx = originX + static_cast<int>(g_pointB.x * 50); int screenBy = originY - static_cast<int>(g_pointB.y * 50); // 创建红色笔用于直线 HPEN hLinePen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0)); SelectObject(hdc, hLinePen); // 绘制直线 MoveToEx(hdc, screenAx, screenAy, NULL); LineTo(hdc, screenBx, screenBy); // 创建红色实心笔用于点 HBRUSH hRedBrush = CreateSolidBrush(RGB(255, 0, 0)); HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hRedBrush); // 绘制点A Ellipse(hdc, screenAx - 5, screenAy - 5, screenAx + 5, screenAy + 5); TextOut(hdc, screenAx + 10, screenAy - 10, L"A", 1); // 绘制点B Ellipse(hdc, screenBx - 5, screenBy - 5, screenBx + 5, screenBy + 5); TextOut(hdc, screenBx + 10, screenBy - 10, L"B", 1); // 计算并显示距离 float distance = sqrtf(powf(g_pointB.x - g_pointA.x, 2) + powf(g_pointB.y - g_pointA.y, 2)); std::wstring distText = L"距离: " + std::to_wstring(distance).substr(0, 4); TextOut(hdc, width - 150, 30, distText.c_str(), distText.length()); // 恢复并删除对象 SelectObject(hdc, hOldBrush); DeleteObject(hLinePen); DeleteObject(hRedBrush); } EndPaint(hWnd, &ps); break; } case WM_CREATE: { // 创建输入框和标签 CreateWindow(L"STATIC", L"A点 X:", WS_CHILD | WS_VISIBLE | SS_CENTER, 10, 10, 50, 20, hWnd, NULL, NULL, NULL); CreateWindow(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER, 65, 10, 50, 20, hWnd, (HMENU)ID_EDIT_AX, NULL, NULL); CreateWindow(L"STATIC", L"Y:", WS_CHILD | WS_VISIBLE | SS_CENTER, 120, 10, 20, 20, hWnd, NULL, NULL, NULL); CreateWindow(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER, 145, 10, 50, 20, hWnd, (HMENU)ID_EDIT_AY, NULL, NULL); CreateWindow(L"STATIC", L"B点 X:", WS_CHILD | WS_VISIBLE | SS_CENTER, 10, 40, 50, 20, hWnd, NULL, NULL, NULL); CreateWindow(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER, 65, 40, 50, 20, hWnd, (HMENU)ID_EDIT_BX, NULL, NULL); CreateWindow(L"STATIC", L"Y:", WS_CHILD | WS_VISIBLE | SS_CENTER, 120, 40, 20, 20, hWnd, NULL, NULL, NULL); CreateWindow(L"EDIT", L"", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER, 145, 40, 50, 20, hWnd, (HMENU)ID_EDIT_BY, NULL, NULL); // 创建按钮 CreateWindow(L"BUTTON", L"绘制", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 210, 10, 80, 25, hWnd, (HMENU)ID_BUTTON_DRAW, NULL, NULL); CreateWindow(L"BUTTON", L"清除", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 210, 40, 80, 25, hWnd, (HMENU)ID_BUTTON_CLEAR, NULL, NULL); // 设置默认值 SetDlgItemText(hWnd, ID_EDIT_AX, L"2"); SetDlgItemText(hWnd, ID_EDIT_AY, L"3"); SetDlgItemText(hWnd, ID_EDIT_BX, L"7"); SetDlgItemText(hWnd, ID_EDIT_BY, L"8"); break; } case WM_COMMAND: { int wmId = LOWORD(wParam); if (wmId == ID_BUTTON_DRAW) { // 获取输入的坐标值 wchar_t text[32]; GetDlgItemText(hWnd, ID_EDIT_AX, text, 32); g_pointA.x = _wtof(text); GetDlgItemText(hWnd, ID_EDIT_AY, text, 32); g_pointA.y = _wtof(text); GetDlgItemText(hWnd, ID_EDIT_BX, text, 32); g_pointB.x = _wtof(text); GetDlgItemText(hWnd, ID_EDIT_BY, text, 32); g_pointB.y = _wtof(text); // 验证坐标是否在有效范围内(0-10) g_pointA.valid = (g_pointA.x >= 0 && g_pointA.x <= 10 && g_pointA.y >= 0 && g_pointA.y <= 10); g_pointB.valid = (g_pointB.x >= 0 && g_pointB.x <= 10 && g_pointB.y >= 0 && g_pointB.y <= 10); // 重绘窗口 InvalidateRect(hWnd, NULL, TRUE); } else if (wmId == ID_BUTTON_CLEAR) { // 清除点 g_pointA.valid = false; g_pointB.valid = false; // 重绘窗口 InvalidateRect(hWnd, NULL, TRUE); } break; } case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // 应用程序入口点 int WINAPI wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { // 1. 注册窗口类 const wchar_t CLASS_NAME[] = L"CartesianWindowClass"; WNDCLASSEXW wcex = { sizeof(WNDCLASSEX) }; wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // 黑色背景 wcex.lpszClassName = CLASS_NAME; if (!RegisterClassExW(&wcex)) { MessageBox(NULL, L"窗口类注册失败!", L"错误", MB_ICONERROR); return 1; } // 2. 计算窗口尺寸(包含边框和标题栏) int clientWidth = 600; int clientHeight = 600; RECT rect = { 0, 0, clientWidth, clientHeight }; AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); int windowWidth = rect.right - rect.left; int windowHeight = rect.bottom - rect.top; // 3. 计算居中位置 int screenWidth = GetSystemMetrics(SM_CXSCREEN); int screenHeight = GetSystemMetrics(SM_CYSCREEN); int posX = (screenWidth - windowWidth) / 2; int posY = (screenHeight - windowHeight) / 2; // 4. 创建窗口 HWND hWnd = CreateWindowExW( 0, // 无扩展样式 CLASS_NAME, L"笛卡尔坐标系 - 绘制点A和点B", WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX, // 禁用调整大小和最大化 posX, posY, // 位置 windowWidth, // 宽度 windowHeight, // 高度 nullptr, nullptr, hInstance, nullptr); if (!hWnd) { MessageBox(NULL, L"窗口创建失败!", L"错误", MB_ICONERROR); return 1; } // 5. 显示窗口 ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); // 6. 消息循环 MSG msg; while (GetMessage(&msg, nullptr, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } 将以上代码接入我发的代码中,并给我全部无删减的完整代码
最新发布
07-22
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值