阅读 145

canvas进阶之特殊形状绘制(在canvas中绘制图像,用哪种方式可以绘制图像的轮廓?)

前言

在阅读完 canvas - 基础了解 中后,想必大家对 canvas 有了一定的认知,那么接下来,咱们就玩点稍微有点意思的东西....

创建弧/曲线

  • 创建介于两个切线之间的弧/曲线

image.png

var c = document.getElementById('canvas'); var ctx = c.getContext('2d'); ctx.strokeStyle = 'red'; ctx.moveTo(20, 20); // 创建开始点 ctx.arcTo(40, 20, 40, 50, 20); // 创建弧 ctx.stroke(); // 进行绘制 复制代码

API

  • 三次贝塞尔曲线:有两个控制点

    • bezierCurveTo(控制点1x,控制点1y,控制点2x,控制点2y,结束点x, 结束点y)

image.png

  • 二次贝塞尔曲线:它仅有有一个控制点

image.png

  • 二次贝塞尔曲线:它仅有有一个控制点

image.png

bezierCurveTo - demo

image.png

//控制点 function draw(id) {   var canvas = document.getElementById(id);   var ctx = canvas.getContext('2d');      ctx.fillStyle = '#eeeeef';   ctx.fillRect(0, 0, 300, 400);      var dx = 150;   var dy = 150;   var s = 100;   ctx.beginPath();   ctx.fillStyle = 'rgb(100,255,100)';   var x = Math.sin(0);   var y = Math.cos(0);   var dig = (Math.PI / 15) * 11;   ctx.moveTo(dx, dy);   for (var i = 0; i < 30; i++) {     x = Math.sin(i * dig);     y = Math.cos(i * dig);     ctx.bezierCurveTo(dx + x * s, dy + y * s - 100, dx + x * s + 100, dy + y * s, dx + x * s, dy + y * s);   }   ctx.closePath();   ctx.fill();   ctx.stroke(); } 复制代码

bezierCurveTo + quadraticCurveTo - demo

image.png

var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); // 画天空 var g = context.createRadialGradient(   canvas.width / 2,   canvas.height / 2,   0,   canvas.width / 2,   canvas.height,   canvas.height ); g.addColorStop(0.0, '#035'); g.addColorStop(1.0, 'black'); context.fillStyle = g; context.fillRect(0, 0, canvas.width, canvas.height); /****** 画星星 ******/ for (var i = 0; i < 100; i++) {   var R = parseInt(Math.random() * 10);   var x = parseInt(Math.random() * canvas.width) + 5;   var y = parseInt(Math.random() * canvas.height * 0.6) + 5;   var rot = parseInt(Math.random() * 50);   drawStar(context, R, x, y, rot, '#fb3'); } //半径小,半径大,x,y,线宽,角度,颜色,类型 function drawStar(ctx, R, x, y, rot, color) {   ctx.save();   ctx.translate(x, y);   ctx.scale(R, R);   ctx.rotate((rot / 180) * Math.PI);   starPath(ctx, color);   ctx.restore(); } function starPath(ctx, color) {   ctx.beginPath();   for (var i = 0; i <= 5; i++) {     ctx.lineTo(Math.cos(((18 + i * 72) / 180) * Math.PI), -Math.sin(((18 + i * 72) / 180) * Math.PI));     ctx.lineTo(Math.cos(((54 + i * 72) / 180) * Math.PI) * 0.5, -Math.sin(((54 + i * 72) / 180) * Math.PI) * 0.5);     ctx.fillStyle = color;     ctx.fill();   } } /****** 画月亮 *******/ drawMoon(context, 100, 100, 50); function drawMoon(ctx, x, y, r) {   ctx.beginPath();   ctx.save();   ctx.translate(x, y);   ctx.scale(r, r);   drawMoonPath(ctx, r);   ctx.restore(); } function drawMoonPath(ctx) {   // 画半圆   ctx.arc(0, 0, 1, 0.5 * Math.PI, 1.5 * Math.PI, true);   ctx.moveTo(0, -1);   ctx.quadraticCurveTo(1, 0, 0, 1);   ctx.closePath();   ctx.fillStyle = '#fb3';   ctx.fill(); } /****** 画陆地 *******/ drawLand(context); function drawLand(ctx) {   ctx.beginPath();   ctx.moveTo(0, canvas.height * 0.8);   ctx.bezierCurveTo(300, canvas.height * 0.6, 600, canvas.height * 0.9, canvas.width, canvas.height * 0.8);   ctx.lineTo(canvas.width, canvas.height);   // ctx.lineTo(0, canvas.height);   var g = ctx.createLinearGradient(0, canvas.height, 0, canvas.height * 0.7);   g.addColorStop(0.0, '#030');   g.addColorStop(1.0, '#580');   ctx.fillStyle = g;   ctx.fill(); } 复制代码

非零环绕规则

路径一正一反,则求和为0

  • canvas在进行填充的时候是否要进行填充的判断依据.用来判断内侧和外侧的方式

  • 在判断填充的区域拉一条线出来,拉到图形的外面,这条拉出来的线就是辅助线。

  • 判断绘制的线是否是从辅助线的左边穿过到辅助线的右边,此时这种穿过的方式记录为+1

  • 如果是从辅助线的右边穿到辅助线的左边,就记做-1.

  • 最后将所有记录的数字进行求和,如果求和的结果为0,代表这块区域不要填充,否则,必须填充

image.png

剪纸效果

  • 本例中,两个圆的路径一顺时针一逆时针,求和为0,不填充

image.png

var canvas = document.getElementById('canvas'); canvas.width = 400; canvas.height = 400; var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.arc(200, 200, 100, 0, Math.PI * 2); ctx.arc(200, 200, 50, 0, Math.PI * 2, true); // ctx.closePath(); ctx.fillStyle = '#058'; ctx.shadowColor = 'gray'; ctx.shadowOffsetX = 10; ctx.shadowOffsetY = 10; ctx.shadowBlur = 10; ctx.fill();


作者:xfz
链接:https://juejin.cn/post/7031586008282234888


文章分类
代码人生
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐