Canvas
介绍SVG是构建XML树的方式来达到绘制图形的,canvas是通过调用相关的方法来绘制图形的。
绘制圆<!DOCTYPE html> <html lang="zh_CN" xmlns="http://www.w3.org/1999/html"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div>第一个园</br> <canvas id="square" width="10" height="100"> </canvas> </div> <div> 第二个园 <canvas id="circle" width="10" height="10"> </canvas> </div> <script src="./js/index.js" charset="UTF-8"></script> </body> </html> // 获取画布元素 let canvas = document.getElementById("square"); // 获取绘制2D元素上下文 let context = canvas.getContext("2d"); // 设置填充颜色为红色 context.fillStyle = "#f00"; // 填充一个正方形 context.fillRect(10,10,10); 绘制线段,填充多边形// 获取画布元素 let canvas = document.getElementById("square"); // 获取绘制2D元素上下文 let context = canvas.getContext("2d"); // 开始一条路径 context.beginPath(); // 从100,100 开始定义一条新的子路径 context.moveTo(100,100); // 从100 100 到 200 200 绘制一条线段 context.lineTo(200,200); // 从200 200 到 100 200 绘制一条线段 context.lineTo(100,200); // 从100 200 到 100 100 绘制一条路径 context.lineTo(100,100); // 绘制边 context.stroke(); // 进行填充 context.fill(); 绘制多边形以五边形为例子, var canvas = document.getElementById("square"); var context = canvas.getContext("2d"); // 绘制一个以100,100为中心,半径为20的柜子N变形,每个定点均匀分布在圆角上,第一个定点放置在最上下 // 偏转角度为0 // 开始定义一条子路径 context.moveTo(100 + 20 * Math.sin(0),100 - 20 * Math.cos(0)); // 计算两个顶点之间夹角 // 其中2π为一个园,除以边数,得到需要旋转的角度 var delta = 2 * Math.PI/5; console.log(delta); // 循环剩余每个顶点 var angle = 0; for(var i = 1; i < 5; i++){ // 角度累加 angle += delta; // 通过旋转绘制下一个顶点,不断的旋转绘制 context.lineTo(100 + 20 * Math.sin(angle),100 - 20*Math.cos(angle)); } // 最后一个顶点和起点进行连接 context.closePath(); // 从新开始一条新路径 context.stroke(); context.fill(); 同理,画圆var canvas = document.getElementById("square"); var context = canvas.getContext("2d"); // 绘制一个以100,100 - 20 * Math.cos(0)); // 计算两个顶点之间夹角 // 其中2π为一个园,除以边数,得到需要旋转的角度 var delta = 2 * Math.PI/500000; console.log(delta); // 循环剩余每个顶点 var angle = 0; for(var i = 1; i < 500000; i++){ // 角度累加 angle += delta; // 通过旋转绘制下一个顶点,不断的旋转绘制 context.lineTo(100 + 20 * Math.sin(angle),100 - 20*Math.cos(angle)); } // 最后一个顶点和起点进行连接 context.closePath(); // 从新开始一条新路径 context.stroke(); context.fill(); 非零绕数原则要检测一个点p是否在路径内部,使用非零绕数原则,即,一条从点p出发沿着任意方向无限延伸,或者一直延伸到路径所在的区域外某点的射线,现在从0开始初始化一个计数器,对穿过这条射线的路径进行枚举,每当一条路径顺时针方向穿过射线的时候,计数器加1,逆时针减1,最后,枚举完所有路径以后,如果计时器的值不是0,那么就认为p在路径内,反过来,计数器的值为0,p在路径外。 js根据非零绕数原则确定那个在路径内,那个在路径外,用于进行填充。 图形属性可以通过设置画布上下文的fillStyle等属性,设置图形的属性,例如对画布上下文的fillStyle的属性进行设置,即,可以设置出填充时的颜色,渐变,图案等样式。 对于canvas来说,每次获取上下文对象的时候,都会返回同一个上下文对象,即,上下文对象为单例的。 还可以使用save方法,把当前的状态,压入已经保存的栈中,调用restore方法,把状态进行恢复,即弹栈。 画布尺寸坐标画布的默认的坐标系为左上角的坐标原点(0,0),右边数值大,下数值大,使用浮点数指定坐标,但不会自动转换为整数,会用反锯齿的方式,模拟填充部分元素。 画布尺寸不能随意改变,对任意属性进行操作,都会清空整个画布。 坐标系变换每一个点的坐标都会映射到css像素上,css像素会映射到一个或多个设备像素。 坐标变换当调用c.translate(dx,dy)方法的时候,会进行如下变换
x‘ = x + dy; y‘ = y + dy; 缩放 x‘ = sx * x; y‘ = sy * y; 进行旋转操作,进行的是如下变换 x‘ = x * cos(a) - y * sin(a); y‘ = y * cos(a) - x * sin(a); 如果要先变换再伸缩,进行如下变换 x‘‘ = sx*x + dx; y‘‘ = sy*y + dy; 如果变换顺序相反进行如下变换 x‘‘ = sx*(x + dx); y‘‘ = sy*(y + dy); 这种变换称为仿射变换,并且仿射变换会修改点的距离和线段间的夹角。对于平行线来说,仿射变换也会保持平行。仿射变换用6个参数描述成为如下表述 x‘ = ax + cy + e; y‘ = bx + dy + f; 通过传入参数实现仿射变换
var canvas = document.getElementById("square"); var context = canvas.getContext("2d"); // 通过坐标变换实现科赫雪花 // 开始一条路径 context.beginPath(); // 开始绘制子路径 context.moveTo(100,100); // 继续绘制 context.lineTo(200,200); // 继续绘制 context.lineTo(200,200); // 进行绘制边 context.stroke(); context.translate(200,200); // 开始一条路径 context.beginPath(); // 开始绘制子路径 context.moveTo(100,200); // 进行绘制边 context.stroke(); 已经绘制的图形不会进行改变,改变的是已经绘制的图形 科赫雪花var canvas = document.getElementById("square"); var context = canvas.getContext("2d"); // 通过坐标变换实现科赫雪花 // 当前状态入栈 function leg(n) { // 保存状态 context.save(); // 递归画 if(n == 0){ context.lineTo(50,0); }else{ // 定义为v字型 context.scale(1/2,1/2); // 递归第一条 context.rotate(60 * (Math.PI / 180)); leg(n - 1); context.rotate(-120 * (Math.PI / 180)); leg(n - 1); } // 坐标恢复变换 context.restore(); // 恢复下一个坐标为0,0 context.translate(50,0); } context.save(); context.moveTo(50,50); // 绘制第一条 leg(1); context.stroke(); 绘制填充曲线绘制一些常见的图形 var canvas = document.getElementById("square"); var context = canvas.getContext("2d"); // 工具函数,角度转弧度 function rads(x) { return Math.PI * x / 180; } // 绘制园 context.beginPath(); context.arc(100,100,40,rads(360),false); context.stroke(); context.fill(); 同理绘制贝塞尔曲线也是同理。 颜色,透明度,渐变,图案绘制一个渐变 线段绘制封顶对于线段,有三种封顶方式,即,butt,square,round 文本和css类似,基线问题。 裁剪直接调动clip即可,当前路径也会被裁剪进入,路径外的统统不会显示。 阴影设置shadow属性即可 图片画布API支持位图图片,同时也支持canvas导出成为图片。 // 创建一个img元素 let img = document.createElement("img"); // 设置src属性 img.src = canvas.toDataURL(); // 追加到文档后面 document.body.appendChild(img); 合成一些api不在阐述 像素操作调用getImageDate方法返回ImageDate对象 // row为行数 for(var row = 0; row < height; row++){ // 获得每行第二个元素的偏移量,其中width为行的色素块。 var i = row * width * 4; // 每4个的色素值进行处理 for(var col = 1; col < width; col++,i+=4){ // 对红色分量处理 data[i] = (data[i] + data[i - 4] * m) / n; // 对绿色分量处理 data[i + 1] = (data[i + 1] + data[i + 1 - 4] * m) / n; // 对蓝色分量处理 data[i + 2] = (data[i + 2] + data[i + 2 - 4] * m) / n; // 对透明度分量处理 data[i + 3] = (data[i + 3] + data[i + 3 - 4] * m) / n; } } 然后把其色素块进行复制回去即可。 命中检测isPointInPath方法用来确定一个点是否落在当前路径中。
但是坐标需要进行转换。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |