canvas系列教程02——圆、弧线、圆角矩形、曲线(气泡、心形、N叶草)、扇形

简介: canvas系列教程02——圆、弧线、圆角矩形、曲线(气泡、心形、N叶草)、扇形

此系列教程层层递进,建议按顺序阅读

  • canvas系列教程01——直线、三角形、多边形、矩形、调色板
    https://blog.csdn.net/weixin_41192489/article/details/124333306

圆 arc()

cxt.beginPath();
cxt.arc(x,y,半径,开始角度,结束角度, anticlockwise);
cxt.closePath();

  • (x,y)为圆心坐标
  • 开始和结束角度的单位为弧度,推荐写法如下:
120*Math.PI/180   //120°
150*Math.PI/180   //150°


  • anticlockwise表示绘制方向,布尔值
    —— true 逆时针
    —— false 顺时针(默认值)
             //半圆
             cxt.beginPath();
             cxt.arc(80, 80, 50, 0, 180*Math.PI/180, true);
             cxt.closePath();
             //描边
             cxt.strokeStyle = "HotPink";
             cxt.stroke();
             //整圆
             cxt.beginPath();
             cxt.arc(120, 80, 50, 0, 360*Math.PI/180, true);
             cxt.closePath();
             //描边
             cxt.strokeStyle = "HotPink";
             cxt.stroke();

             cxt.beginPath();
             cxt.arc(70, 70, 50, 0, -90 * Math.PI / 180, true);
             cxt.closePath();
             cxt.strokeStyle = "HotPink";
             cxt.stroke();

cxt.arc(70, 70, 50, 0, -90 * Math.PI / 180, false);

             //半圆
             cxt.beginPath();
             cxt.arc(80, 80, 50, 0, 180 * Math.PI / 180, true);
             cxt.closePath();
             //填充
             cxt.fillStyle = "HotPink";
             cxt.fill();
             //整圆
             cxt.beginPath();
             cxt.arc(120, 80, 50, 0, 360 * Math.PI / 180, true);
             cxt.closePath();
             //填充
             cxt.fillStyle = "#9966FF";
             cxt.fill();

弧线

方法一 arc() 绘制

//状态描述
cxt.beginPath();
cxt.arc(x,y,半径,开始角度,结束角度, anticlockwise);
//描边
cxt.strokeStyle = "颜色值";
cxt.stroke();

和圆一样,使用arc(),但不需要关闭路径! (即没有 cxt.closePath())

             cxt.beginPath();
             cxt.arc(70, 70, 50, 0, -90 * Math.PI / 180, true);
             cxt.stroke();

stroke()和fill()这两个方法只能绘制当前路径,不能同时绘制几个路径。

             //绘制一条直线
             cxt.moveTo(20,20);
             cxt.lineTo(70,20);
             cxt.stroke();

             //绘制圆弧+直线
             cxt.beginPath();
             cxt.arc(70,70,50,0,-90*Math.PI/180,true);
             cxt.moveTo(120,70);
             cxt.lineTo(120,120);
             cxt.stroke(); 

             //绘制一条直线
             cxt.moveTo(20,20);
             cxt.lineTo(70,20);
             // cxt.stroke();  注释掉之后,此直线不会绘制

             //绘制圆弧+直线
             cxt.beginPath();
             cxt.arc(70,70,50,0,-90*Math.PI/180,true);
             cxt.moveTo(120,70);
             cxt.lineTo(120,120);
             cxt.stroke(); 

方法二 arcTo() 绘制

cxt.arcTo(cx,cy,x2,y2,radius);

一般由moveTo()或lineTo()提供开始点

  • cx,cy 为控制点坐标
  • x2,y2 为结束点坐标
  • radius 是圆弧半径
  • arcTo()方法绘制的弧线是两个切点之间长度最短的那个圆弧。此外,如果开始点不是弧线起点,arcTo()方法还将添加一条当前端点到弧线起点的直线线段。也就是说,开始点坐标并不一定是弧线起点坐标。
             cxt.moveTo(20,20);
             cxt.lineTo(70,20);
             cxt.arcTo(120,20,120,70,50);
             cxt.lineTo(120,120);
             cxt.stroke();

             cxt.moveTo(20,20);
             // cxt.lineTo(70,20);  注释掉后,仍会画直线!
             cxt.arcTo(120,20,120,70,50);
             cxt.lineTo(120,120);
             cxt.stroke();

圆角矩形

方法一 直线和弧线拼接

             cxt.moveTo(40,20);
             cxt.lineTo(160,20);
             cxt.arcTo(180,20,180,40,20);
             cxt.moveTo(180,40);
             cxt.lineTo(180,110);
             cxt.arcTo(180,130,160,130,20);
             cxt.moveTo(160,130);
             cxt.lineTo(40,130);
             cxt.arcTo(20,130,20,110,20);
             cxt.moveTo(20,110);
             cxt.lineTo(20,40);
             cxt.arcTo(20,20,40,20,20);
             cxt.stroke();

方法二 封装一个专门绘制圆角矩形的函数

        /*
         * createRoundedRect()用于绘制圆角矩形
         * width、height:分别表示长和宽
         * r:表示圆角半径
         * offsetX、offsetY:分别表示左上角顶点坐标
         */
        function createRoundedRect(cxt, width, height, r, offsetX, offsetY) {
             cxt.beginPath();
             cxt.moveTo(offsetX + r, offsetY);
             cxt.lineTo(offsetX + width - r, offsetY);
             cxt.arcTo(offsetX + width, offsetY, offsetY + width, offsetY + r, r);
             cxt.lineTo(offsetX + width, offsetY + height - r);
             cxt.arcTo(offsetX + width, offsetY + height, offsetX + width - r, offsetY + height, r);
             cxt.lineTo(offsetX + r, offsetY + height);
             cxt.arcTo(offsetX, offsetY + height, offsetX, offsetY + height - r, r);
             cxt.lineTo(offsetX, offsetY + r);
             cxt.arcTo(offsetX, offsetY, offsetX + r, offsetY, r);
             cxt.closePath();
        }
             createRoundedRect(cxt, 100, 100, 20, 20, 20);
             cxt.fillStyle = "HotPink";
             cxt.fill();

曲线

从理论上来说,任何复杂的图形都可以用贝塞尔曲线绘制出来

二次贝塞尔曲线

二次贝塞尔曲线有一个控制点,只能向一个方向弯曲

cxt.quadraticCurveTo(cx , cy , x2,y2);

一般由moveTo()或lineTo()提供开始点

  • cx,cy 为控制点坐标
  • x2,y2 为结束点坐标

    绘制原理可以参考下图:
             cxt.moveTo(30, 120);
             cxt.quadraticCurveTo(100, 20, 160, 120);
             cxt.stroke();

实战范例:气泡

             cxt.moveTo(75, 25);
             cxt.quadraticCurveTo(25, 25, 25, 62);
             cxt.quadraticCurveTo(25, 100, 50, 100);
             cxt.quadraticCurveTo(50, 120, 30, 125);
             cxt.quadraticCurveTo(60, 120, 65, 100);
             cxt.quadraticCurveTo(125, 100, 125, 62);
             cxt.quadraticCurveTo(125, 25, 75, 25);
             cxt.stroke();

三次贝塞尔曲线

三次贝塞尔曲线有两个控制点,可以绘制出波浪线

cxt.bezierCurveTo(cx1 , cy1 , cx2 , cy2 , x , y);

一般由moveTo()或lineTo()提供开始点

  • cx1,cy1 为控制点1的坐标
  • cx2,cy2 为控制点2的坐标
  • x,y 为结束点坐标

    绘制原理可参考下图:
             //绘制三次贝塞尔曲线
             cxt.moveTo(20, 80);
             var cx1 = 20;
             var cy1 = 20;
             var cx2 = 120;
             var cy2 = 120;
             var endX = 120;
             var endY = 60;
             cxt.bezierCurveTo(cx1, cy1, cx2, cy2, endX, endY);
             cxt.stroke();

实战范例:心形

             cxt.moveTo(75, 40);
             cxt.bezierCurveTo(75, 37, 70, 25, 50, 25);
             cxt.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5);
             cxt.bezierCurveTo(20, 80, 40, 102, 75, 120);
             cxt.bezierCurveTo(110, 102, 130, 80, 130, 62.5);
             cxt.bezierCurveTo(130, 62.5, 130, 25, 100, 25);
             cxt.bezierCurveTo(85, 25, 75, 37, 75, 40);
             cxt.stroke();

实战范例:N叶草

        /*
         * createLeaf()用于绘制N叶草
         * n:n片
         * dx、dy:叶子中心位置的坐标
         * size:控制叶子的大小
         * length:控制叶子长度
         */
        function createLeaf(cxt, n, dx, dy, size, length) {
             cxt.beginPath();
             cxt.moveTo(dx, dy + size);
             var degree = 2 * Math.PI / n;
             for (var i = 1; i < n + 1; i++) {
                  //计算控制点的坐标
                  var cx1 = Math.sin((i - 1) * degree) * length + dx;
                  var cy1 = Math.cos((i - 1) * degree) * length + dy;
                  var cx2 = Math.sin(i * degree) * length + dx;
                  var cy2 = Math.cos(i * degree) * length + dy;
                  //计算结束点的坐标
                  var x = Math.sin(i * degree) * size + dx;
                  var y = Math.cos(i * degree) * size + dy;
                  cxt.bezierCurveTo(cx1, cy1, cx2, cy2, x, y);
             }
             cxt.closePath();
        }
             createLeaf(cxt, 4, cnv.width/2, cnv.height/2, 20, 80);
             //定义填充颜色为浅绿色
             cxt.fillStyle = "#00FF99";
             cxt.fill();

扇形

封装绘制扇形的函数 createSector

        function createSector(cxt, x, y, r, angle1, angle2) {
             cxt.beginPath();
             cxt.moveTo(x, y);
             cxt.arc(x, y, r, angle1 * Math.PI / 180, angle2 * Math.PI / 180, false);
             cxt.closePath();
        }
             createSector(cxt, cnv.width / 2, cnv.height / 2, 50, 30, 120);
             cxt.fillStyle = "HotPink";
             cxt.fill();
目录
相关文章
|
8月前
|
缓存 安全 Java
Java反射机制:动态操作类与对象
Java反射机制是运行时动态操作类与对象的强大工具,支持获取类信息、动态创建实例、调用方法、访问字段等。它在框架开发、依赖注入、动态代理等方面有广泛应用,但也存在性能开销和安全风险。本文详解反射核心API、实战案例及性能优化策略,助你掌握Java动态编程精髓。
|
7月前
|
存储 算法 API
唯品会智能分仓API技术解析:基于收货地址自动匹配最近仓库
唯品会智能分仓API通过地理编码与Haversine距离算法,自动将订单匹配至最近仓库,提升配送效率、降低成本。本文详解其技术原理、实现步骤与应用优势,助力开发者构建高效物流系统。(239字)
461 0
|
前端开发 JavaScript
canvas系列教程01——直线、三角形、多边形、矩形、调色板
canvas系列教程01——直线、三角形、多边形、矩形、调色板
533 0
|
设计模式 数据安全/隐私保护
Next.js 实战 (七):浅谈 Layout 布局的嵌套设计模式
这篇文章介绍了在Next.js框架下,如何处理中后台管理系统中特殊页面(如登录页)不包裹根布局(RootLayout)的问题。作者指出Next.js的设计理念是通过布局的嵌套来创建复杂的页面结构,这虽然保持了代码的整洁和可维护性,但对于特殊页面来说,却造成了不必要的布局包裹。文章提出了一个解决方案,即通过判断页面的skipGlobalLayout属性来决定是否包含RootLayout,从而实现特殊页面不包裹根布局的目标。
512 0
Next.js 实战 (七):浅谈 Layout 布局的嵌套设计模式
Vue3进度条(Progress)
这是一个基于 Vue2 的进度条组件,支持线性 (`line`) 和圆形 (`circle`) 两种模式。可通过多种属性自定义进度条的样式和行为,包括宽度、进度百分比、颜色、线宽、线帽样式等。此外,还支持显示进度文本或图标,并允许通过插槽自定义内容。该组件提供了丰富的配置选项,适用于多种应用场景。
1902 5
Vue3进度条(Progress)
|
网络协议 jenkins 持续交付
Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker
Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker
5688 0
Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker
|
XML JavaScript 前端开发
vue实战——图标,请使用SVG!(含插件vue-svg-icon的使用)
vue实战——图标,请使用SVG!(含插件vue-svg-icon的使用)
1327 1
|
Web App开发 前端开发
canvas系列教程04 —— 渐变、阴影、路径、状态、Canvas对象、图形重叠模式
canvas系列教程04 —— 渐变、阴影、路径、状态、Canvas对象、图形重叠模式
1171 0
|
Windows
NPM——通过commitlint来规范commit的提交信息
NPM——通过commitlint来规范commit的提交信息
364 0
|
存储 前端开发 JavaScript
canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)(一)
canvas系列教程03 —— 线的样式、绘制文本、操作图片(图片的渲染、缩放、裁剪、切割、平铺、特效)、变换元素(平移、缩放、旋转)(一)
1784 0

热门文章

最新文章