HTML 画布绘制线垂直于另一条线

2023-12-30

我使用 HTML canvas 绘制线条,如下图所示,但是该线条的两侧都有边缘。

如图所示,两个边缘不是垂直到主线。
我尝试了以下解决方案,但没有成功:
* 旋转边缘线,但旋转会使它们从原始位置发生变化
* 求出该点的角度主线然后相对于线画线,但是这个解决方案并不容易实现(很可能是我错误地实现了它)。

这是我的代码,但它总是会绘制垂直边缘:

<!DOCTYPE html>
<html>
<body>

<canvas id="myCanvas" width="200" height="200" style="border:1px solid #d3d3d3;">

<script>

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

var x1 = 100;
var x2 = 150;
var y1 = 50;
var y2 = 120;

ctx.beginPath();
ctx.strokeStyle = "purple";  // Purple path
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);            
ctx.stroke();  // Draw it

ctx.beginPath();
ctx.moveTo(x1,y1);
ctx.lineTo(x1,y1+10);
ctx.stroke();


ctx.restore();
ctx.beginPath();
ctx.moveTo(x1,y1);
ctx.lineTo(x1,(y1-10));
ctx.stroke();


ctx.beginPath();
ctx.moveTo(x2,y2);
ctx.lineTo(x2,y2+10);
ctx.stroke();


ctx.restore();
ctx.beginPath();
ctx.moveTo(x2,y2);
ctx.lineTo(x2,(y2-10));
ctx.stroke();


</script>
</body>
</html>

谁能帮我旋转两条边缘线,使其垂直于主线。 谢谢。


将任何 2D 矢量旋转 90 度

如果您还记得 2D 向量的旋转 90 度规则,则垂直线很容易计算。

一个向量{x,y}可顺时针旋转90度{-y,x}或逆时针{y,-x}。交换 x 和 y 并对顺时针方向的 y 求反或对逆时针方向的 x 求反

所以对于一条线段x1,y1 to x2,y2转换为向量,对该向量进行归一化并旋转 90 度,如下所示

function getPerpOfLine(x1,y1,x2,y2){ // the two points can not be the same
    var nx = x2 - x1;  // as vector
    var ny = y2 - y1;
    const len = Math.sqrt(nx * nx + ny * ny);  // length of line
    nx /= len;  // make one unit long
    ny /= len;  // which we call normalising a vector
    return [-ny, nx]; // return the normal  rotated 90 deg
}

然后假设你想在线段的末端绘制一条10像素的线

const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
document.body.append(canvas);
ctx.strokeStyle = "black";
ctx.lineJoin = ctx.lineCap = "round";
ctx.lineWidth = 3;

// the line segment
const x1 = 40, y1 = 40, x2 = 260, y2 = 110;
const endLen = 10; // length of end lines

var px = y1 - y2; // as vector at 90 deg to the line
var py = x2 - x1;
const len = endLen / Math.hypot(px, py);
px *= len;  // make leng 10 pixels
py *= len; 

// draw line the start cap and end cap.
ctx.beginPath();

ctx.lineTo(x1, y1);   // the line start
ctx.lineTo(x2, y2);
ctx.moveTo(x1 + px, y1 + py); // the start perp line
ctx.lineTo(x1 - px, y1 - py);
ctx.moveTo(x2 + px, y2 + py); // the end perp line
ctx.lineTo(x2 - px, y2 - py);
ctx.stroke();

Update

沿线渲染内容的简单解决方案,使用相同的 90 度规则。

还有一种使用相同向量旋转进行渲染的替代方法,但不是通过向量乘法设置垂直轴,而是将变换的 y 轴设置为与沿线的 x 轴成 90 度。将原点设置为线条的开头,然后您只需相对于线条进行渲染即可。

setTransformToLine(x1, y1, x2, y2)

以下函数将设置画布变换为沿线

// Set 2D context  current transform along the line x1,y1,x2,y2 and origin to
// start of line. y Axis is rotated clockwise 90 from the line.
// Returns the line length as that is most frequently required when
// using the method saving some time.
function setTransformToLine(x1, y1, x2, y2) {
  const vx = x2 - x1;   // get the line as vector
  const vy = y2 - y1;
  const len = Math.hypot(vx, vy); // For <= IE11 use Math.sqrt(vx * vx + vy * vy)
  const nx = vx / len; // Normalise the line vector. Making it one
  const ny = vy / len; // pixel long. This sets the scale

  // The transform is the normalised line vector for x axis, y at 90 deg 
  // and origin at line start
  ctx.setTransform(nx, ny, -ny, nx, x1, y1); // set transform

  return len;
}

如何使用

此示例展示了如何使用转换来执行相同的行,但还添加带注释的长度。

const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
document.body.append(canvas);
ctx.strokeStyle = "black";
ctx.lineJoin = ctx.lineCap = "round";
ctx.lineWidth = 3;
ctx.font = "16px arial";
ctx.textBaseline = "middle";
ctx.textAlign = "center";

const x1 = 40, y1 = 40, x2 = 260, y2 = 110;
const endLen = 10; 


function setTransformToLine(x1, y1, x2, y2) {
  const vx = x2 - x1; 
  const vy = y2 - y1;
  const len = Math.hypot(vx, vy); 
  const nx = vx / len; 
  const ny = vy / len;
  ctx.setTransform(nx, ny, -ny, nx, x1, y1);
  return len;
}

// Set the transform along the line. Keep the line length
// line len is need to get the x coord of the end of the line
const lineLen = setTransformToLine(x1, y1, x2, y2);

const lineLenStr = Math.round(lineLen) + "px";
const textWidth = ctx.measureText(lineLenStr).width;

const rlen = lineLen - textWidth - 16; // find the remaining line len after removing space for text

// Rendering is done in line local coordinates
// line is from (0,0) to (lineLen,0)

// Now draw the line the ends first and then along the line leaving gap for text
ctx.beginPath();
ctx.lineTo(0, -endLen);             // start perp line
ctx.lineTo(0,  endLen); 

ctx.moveTo(lineLen, -endLen);       // end of line is at lineLen
ctx.lineTo(lineLen,  endLen); 

ctx.moveTo(0,0);                    // line start segment
ctx.lineTo(rlen / 2, 0);

ctx.moveTo(lineLen - rlen / 2,0);   // line end segment
ctx.lineTo(lineLen, 0);

ctx.stroke(); // render it.

// now add text at the line center
ctx.fillText(lineLenStr, lineLen / 2, 0);

// To restore the transform to its default use identity matrix
ctx.setTransform(1, 0, 0, 1, 0, 0);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HTML 画布绘制线垂直于另一条线 的相关文章

  • 为什么我的数据没有存储到我的 Firebase 实时数据库中?

    我正在尝试为网络应用程序制作一个注册页面 这会将数据发送到 firebase 数据库 我已阅读官方 firebase 文档并按照说明写入数据 但什么也不会写 在我的数据库控制台中 它显示的所有内容都是空 而不是我的数据 我没有收到控制台错误
  • 如何使用 JQuery 创建新的 img 标签,并使用 JavaScript 对象中的 src 和 id?

    我从基本意义上了解 JQuery 但对它绝对是新手 并且怀疑这很容易 我在 JSON 响应中获得了图像 src 和 id 转换为对象 因此在 responseObject imgurl 和 responseObject imgid 中获得了
  • 如何从索引文件迭代多个导入的模块

    我有一个名为Polygons我在那里创建了一个index jsfile 以导出目录中的所有文件 它看起来像这样 export default as europe from europe export default as northAmer
  • 如何使用 jQuery 解析 JavaScript 对象

    jQuery JavaScript 中用于解析 JSON 对象并返回键 值对的 foreach 等效项是什么 JSON 对象 是什么意思 JSON 是一种用于序列化对象的文本格式 如果要循环访问通过反序列化 JSON 字符串获得的对象中的属
  • CSS 链接图像带有下划线(“a”显示设置为阻止)

    我有一个菜单 我希望每个单独的项目中文本周围的所有空间都能将用户带到指定的页面 我在网上查了一下 发现最好的解决方案是将 a 显示设置为阻止 如下 a display block height 100 text decoration und
  • starsGeometry[0].setAttribute 不是函数

    尝试复制此站点上存在的 Three js 地球仪 https trijs org examples misc controls fly html https threejs org examples misc controls fly ht
  • 样式表与 标记上的 TITLE 属性中断? [复制]

    这个问题在这里已经有答案了 我正在帮助升级一个非常旧的公司内部网 我们的用户使用的是 IE8 和 IE9 我们的大多数网站都是为 IE5 IE9 编写的 我们即将将所有人升级到 IE11 但试点人员发现了大量兼容性问题 未来几个月将会有大量
  • setImmediate 与 nextTick

    Node js 0 10 版本今天发布并推出setImmediate The API变更 https github com nodejs node wiki API changes between v0 8 and v0 10文档建议在进行
  • 带有蓝图 css 的 HTML5 样板

    我正在考虑将这两种技术结合起来用于一个新项目 这是坏主意吗 有没有推荐的替代网格系统与 html5 样板一起使用 实际上 我将它们混合在一起并且它们一起工作得很好 http shikiryu com html5 我所要做的就是修改 div
  • DOM Range 克隆不能免受 DOM 更改的影响

    我正在使用 cloneRange 函数克隆 DOM Range 如果我然后像这样修改原始范围对象 range setStart range startContainer 1 克隆保留了旧的startOffset正如预期的那样 但是 如果我修
  • Typescript:如何在构造函数之外初始化类属性

    我有一个场景 我需要在构造函数之外初始化类属性 考虑以下示例 class A public prop MyPropType public id string public constructor id string this id id p
  • 可访问性和所有这些 JavaScript 框架

    我研究一些 JavaScript 框架 例如 Backbone js 和 Batman js 已经有一段时间了 虽然我真的很喜欢它们 但我一直在关注一件棘手的事情 这个问题就是可访问性 作为一名网络开发人员 我一直试图让我的网站和应用程序考
  • 基于nextjs中的user-agent重写

    我在 NextJs 中有一个多域网站 我想根据域和设备类型获取数据 现在我可以识别该域 但我希望在重写规则中使用用户代理并在 getStaticProps 函数中使用它 这是我在 next config js 文件中的规则 async re
  • 如何在 VS Code 中禁用烦人的突出显示

    正如标题所说 我只是想知道如何在 VS Code 中禁用这个烦人的突出显示 当我在括号内输入内容时 我想立即得到建议 但首先我得到一个恼人的突出显示 除非我按 ESC 键 否则它不会消失 正如您在图像中看到的 首先 console log
  • 在javascript中使用正则表达式从字符串中提取子字符串

    我是 javascript 新手 如何提取与 javascript 字符串中的正则表达式匹配的子字符串 例如在Python中 version regex re compile r d d d line 2021 05 29 Version
  • NextJS 在生产构建中 CSS 顺序错误

    我从本地文件和节点模块导入 CSS 文件 gt Global Styling Local import styles globals scss Icons import fortawesome fontawesome free css al
  • 当虚拟键盘出现时,三星 Android 上的 Html 输入失去焦点

    我在使用 html5 Web 应用程序的 Samsung Galaxy Tab A Android 7 0 上遇到输入元素失去焦点的问题 这似乎是android中的一个问题 就像在windows 10或iOS上一样 尽管弹出虚拟键盘时也会触
  • 是否可以更改 Google Chatbot 的“卡片”“宽度”?

    我环顾四周想要改变card width由 Google Chatbot 创建 但据我所知 Chatbot API 中没有任何配置 是否可以以某种方式设置属性 我现在的Card class class Card constructor tit
  • Tampermonkey 用户脚本可以访问 Chrome API 吗?

    我正在开发一个需要的用户脚本chrome对象 但我无法访问它 如何访问chrometampermonkey 用户脚本中的对象 也许 清单中的一些权限或者什么 参考Chrome 扩展代码 vs 内容脚本 vs 注入脚本 https stack
  • AngularJS动画卡片翻转

    我正在尝试使用新的 AngularJS 方式在页面转换之间制作动画 并希望合并卡片翻转 例如http jsfiddle net nicooprat GDdtS http jsfiddle net nicooprat GDdtS body b

随机推荐