前言

CanvasRenderingContext2D 没有提供绘制多边形的函数,所以只能由我们自己来实现绘制多边形的函数。以六边形为基础,需要用到三角函数:sin 和 cos。

点 A 坐标

(一)连接必要的辅助线:①连接点 A 和点 O;②从点 A 往下作一条垂直线;③连接点 A1 和点 O。(二)已知的量:①AO 实际就是圆 O 的半径。点 A 坐标的求解步骤:

  1. 求 ∠AOB;
  2. 求 OB 的长;
  3. 求 AB 的长;
  4. X 轴上的坐标:O 的 X 轴 + OB 的长度;
  5. Y 轴上的坐标:O 的 Y 轴 - AB 的长度;

求 A 点的坐标就必须要知道 OB 和 AB。

求 OB 的长

领边比斜边用 COS 函数,那么 OB 的长就是:

\[cos∠AOB = \frac{OB}{AO}
\]

求 AB 的长

对边比斜边用 SIN 函数,那么 AB 的长就是:

\[sin∠AOB = \frac{AB}{AO}
\]

求 ∠AOB

求 OB 和 AB 就必须要知道 ∠AOB。观察可知,∠AOB 的度数是360° / 6 = 60°

代码实现

let circX = 100, circY = 100, // 圆心坐标
let sides = 6, angleAOB = (Math.PI * 2) / sides; // ∠AOB let sideOB = Math.cos(angleAOB) * radius, sideAB = Math.sin(angleAOB) * radius; let aX = circX + sideOB, // 点 A 的 x 坐标
let aY = circY - sideAB; // 点 A 的 y 坐标

所以最终求得点 A 的坐标:(140, 30.717967697244916)

点 F 坐标

点 F 不能直接构成一个三角形,所以度数是 0°。sin0° = 0cos0°= 1

let circX = 100, circY = 100, // 圆心坐标
let sides = 6, angle = 0; let adjacentSide = Math.cos(angle) * radius, beveledSide = Math.sin(angle) * radius; let aX = circX + adjacentSide, // 点 F 的 x 坐标
let aY = circY - beveledSide; // 点 F 的 y 坐标

所以最终求得点 F 的坐标:(180, 100)

求所有点坐标

通过上面两个坐标的求解过程可知,只有三角形的度数在增加,从点 F 顺时针开始,每一个角是自身的角度再加 60°。

let radius = 80, sides = 6, circX = 100, circY = 100;
let angle = (Math.PI * 2) / sides, accumulator = 0; for ( let i = 0; i < sides; i++ ) {
let adjacentSide = Math.cos(accumulator) * radius;
let beveledSide = Math.sin(accumulator) * radius;
let aX = circX + adjacentSide;
let aY = circY - beveledSide;
ctx.lineTo(aX, aY);
accumulator += angle;
}

6 个点坐标的结果依次是:

封装成函数

只需提供多边形有多少面、多边形的圆心半径:

function drawPolygonPath(sides, radius, circX, circY, ctx) {
let angle = (Math.PI * 2) / sides, accumulator = 0; ctx.beginPath();
for ( let i = 0; i < sides; i++ ) {
let adjacentSide = Math.cos(accumulator) * radius;
let beveledSide = Math.sin(accumulator) * radius;
let aX = circX + adjacentSide;
let aY = circY - beveledSide;
ctx.lineTo(aX, aY);
accumulator += angle;
}
ctx.closePath();
ctx.stroke();
}

ctx.lineTo(aX, aY) 确定多边形所有的点,在循环结束之后关闭路径,再调用ctx.stroke() 函数,完成多边形的绘制。

let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d"); drawPolygonPath(6, 80, 100, 100, ctx);

Canvas:绘制多边形的更多相关文章

  1. canvas绘制多边形

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 浅谈使用canvas绘制多边形

    本文主要使用坐标轴的使用来绘制多边形,点位则都是在y轴上寻找,这种方法能够更好的理解图形与修改. //id为html里canvas标签的属性id: //x,y为坐标轴的起始位置,因为canvas默认坐 ...

  3. JavaScript+canvas 绘制多边形

    效果图: <body> <canvas id="square" width="500"></canvas> <canv ...

  4. (三)canvas绘制样式

    beginPath() 对画线点的一个开始限制 moveTo() 画线的起点,只在开头使用 参数两个x轴,y轴 lineTo() 后续连线 两个参数x轴,y轴 stroke() 连线无填充 fill( ...

  5. 学习笔记:HTML5 Canvas绘制简单图形

    HTML5 Canvas绘制简单图形 1.添加Canvas标签,添加id供js操作. <canvas id="mycanvas" height="700" ...

  6. [WebGL入门]十四,绘制多边形

    注意:文章翻译http://wgld.org/.原作者杉本雅広(doxas),文章中假设有我的额外说明,我会加上[lufy:].另外,鄙人webgl研究还不够深入.一些专业词语,假设翻译有误,欢迎大家 ...

  7. Canvas绘制不规则图形,实现可拖动,编辑--V1.0第一篇

    目前的工作在做在线的标注工具,接触canvas一年了,各种绘制,基本上图像的交互canvas都可以完成,也写了几篇关于canvas的文章,遇到的问题也写博客上了,对于canvas有问题的朋友可以去看看 ...

  8. Canvas学习:封装Canvas绘制基本图形API

    Canvas学习:封装Canvas绘制基本图形API Canvas Canvas学习   从前面的文章中我们了解到,通过Canvas中的CanvasRenderingContext2D对象中的属性和方 ...

  9. JS实现鼠标点击爱心&绘制多边形&每日一言功能

    本篇文章主要介绍我的个人博客 程序猿刘川枫 中页面使用的美化功能(基于JS实现): 1.鼠标点击出现不同颜色爱心特效 2.页面浮动多边形跟随鼠标移动 3.每日一言功能 1.鼠标点击出现爱心特效 经常在 ...

  10. HTML5学习总结——canvas绘制象棋(canvas绘图)

    一.HTML5学习总结——canvas绘制象棋 1.第一次:canvas绘制象棋(笨方法)示例代码: <!DOCTYPE html> <html> <head> & ...

随机推荐

  1. 【Java SE进阶】Day11 网络编程、TCP应用程序

    一.网络编程入门 1.软件架构 C/S:QQ.迅雷 B/S 共同点:都离不开网络的支持 网络编程:在一定的协议下,实现两台计算机通信 2.网络通信协议 通信协议:需遵守的规则,只有遵守才能通信 主要包 ...

  2. Nmap扫描参数

    执行Nmap/nmap --help查看帮助文档,将显示Namp的用法及其功能Nmap的相关参数的含义与用法:扫描目标时用到的参数:-iL:从文件中导入目标主机或目标网段-iR:随意选择目标主机--e ...

  3. 第一百一十七篇: JavaScript 工厂模式和原型模式

    好家伙,本篇为<JS高级程序设计>第八章"对象.类与面向对象编程"学习笔记   1.工厂模式 工厂模式是另外一种关注对象创建概念的创建模式. 它的领域中同其它模式的不同 ...

  4. 一、对称加密(DES加密)

    一.DES简介DES是一种对称加密(Data Encryption Standard)算法.于1977年得到美国政府的正式许可,是一种用56位密钥来加密64位数据的方法.一般密码长度为8个字节,其中5 ...

  5. [编程基础] C++多线程入门1-创建线程的三种不同方式

    原始C++标准仅支持单线程编程.新的C++标准(称为C++11或C++0x)于2011年发布.在C++11中,引入了新的线程库.因此运行本文程序需要C++至少符合C++11标准. 1 创建线程的三种不 ...

  6. [OpenCV实战]36 使用OpenCV在视频中实现简单背景估计

    目录 1 时间中值滤波 2 使用中值进行背景估计 3 帧差分 4 总结和代码 5 参考 许多计算机视觉应用中,硬件配置往往较低.在这种情况下,我们必须使用简单而有效的技术.在这篇文章中,我们将介绍一种 ...

  7. Serilog日志同步到redis中和自定义Enricher来增加额外的记录信息

    Serilog 日志同步到redis队列中 后续可以通过队列同步到数据库.腾讯阿里等日志组件中,这里redis库用的新生命团队的NewLife.Redis组件 可以实现轻量级消息队列(轻量级消息队列R ...

  8. [C#]C++/CLI中interior_ptr和pin_ptr的区别

    interior_ptr 当垃圾回收器移动对象时,Interior pointer能随之移动,并始终指向该对象. 但是如果把这个指针返回给外部函数,那么当垃圾回收时(垃圾回收期间会压缩对象,),对象地 ...

  9. elasticsearch之search template

    一.search template简介 elasticsearch提供了search template功能,其会在实际执行查询之前,对search template进行预处理并将参数填充到templa ...

  10. Flutter 3.7 正式发布

    新的 Flutter 稳定版加入了 Material 3 更新.iOS 平台优化及其他内容 新年伊始,由 Flutter 3.7 正式版来「打头阵」!我们与整个 Flutter 社区成员们继续在 Fl ...