html5 现在是时下较火的编程语言之一, 但是对于怎么学习很多朋友都是不了解的, 不知道从何处下手, 针对以上内容小猿圈 web 前端讲师每天会分享一个 Web 前端知识, 希望对你的前端学习有一定的帮助, 今天分享的是 canvas 绘制线段方法.
学习 canvas, 首先得知道如何去绘制线段, 然后才能通过很多简单的线段去实现比较复杂的图形, 比如常见的图表, 柱状图, 折线图等都是通过一段一段的线段实现的.
基础知识
canvas 的基础知识不算多, 主要掌握如何绘制线段, 图形, 图片, 文本等. canvas 可以在浏览器中绘制, 也可以借助 node-canvas 在 node 服务端绘制简单的图片. 本文只记录在浏览器中绘制, 至于在 node 端如何绘制, 自己可以去查看相关资料.
在浏览器中绘制, 就先在 HTML 中定义 canvas 元素, 默认宽高是 300*150, 可以通过 width 和 height 设置. 注意 canvas 元素样式宽高和 canvas 绘图画布宽高不是一个东西, 这块将在以后说的.
- <canvasid="canvas">
- <p>
- 当前浏览器不支持 canvas, 请升级浏览器
- </p>
- </canvas>
在绘制之前, 我们要先获取当前 canvas 的 2d 绘制上下文 context, 后续总是通过操作 context 来进行绘制.
- letcanvas=document.querySelector('#canvas');
- if(!canvas){
- thrownewError('cannotfindcanvaselement');
- }
- // 注意 2d. 参数必须是小写的;
- // 通过设置参数为 webgl, 可以获取 3d 绘制上下文
- letctx=canvas.getContext('2d');
注: 后续示例中会忽略上面的代码片段, 直接使用 ctx 变量表示 canvas 的 2d 绘制上下文.
线段
在绘制一条简单的线段时, 一般会先设置线段的样式, 比如, 颜色, 线条宽度, 线条端点样式等, 我们通过设置 strokeStyle 来设置 ctx 的全局绘制样式, 可以是 rgba 或合法的 16 进制颜色值, 或者渐变对象等. 如下代码简单的绘制了一条从 (10,10) 到(50,60)的, 宽度为 10 的, 红色的线段.
- ctx.strokeStyle='red';
- ctx.lineWidth=10;
- ctx.moveTo(10,10);
- ctx.lineTo(50,60);
- ctx.stroke();
绘制线段相关的方法以及属性:
相关属性:
lineCap, 该值告诉浏览器如何绘制线段的端点, 可选值为以下三个之一: butt,round,square. 默认为 butt.
lineWidth, 该值决定了线段的像素宽度. 必须为非负, 非无穷, 默认为 1.0.
lineJoin, 决定了两条线段相交时如何绘制焦点, 只有当两条线段方向不同时, 才会生效. 可取值: bevel,round,miter. 默认值是 miter.
miterLimit, 告诉浏览器如何绘制 miter 形式的线段焦点, 只有当 lineJoin='miter'有效, 默认为 10.0.
lineDashOffset, 设置虚线偏移量, 默认为 0.0.
相关方法:
beginPath, 将当前路径之中的所有子路径都要清除掉, 以此来重置当前路径. 一般在绘制闭合图形时要先调用.
closePath, 显示的封闭某段路径. 该方法用于封闭圆弧路径以及由曲线或线段所创建的开放路径.
moveTo, 移动当前绘制点到指定的坐标.
lineTo, 从上一个点绘制一条到指定坐标点的线段.
setLineDash, 用来设置虚线的方法, 参数是一个数组, 表明绘制实线的长度, 以及实线之间的间隙的长度.
试试用设置不同的 lineCap 值来绘制同样的线段
- ctx.lineWidth=10;
- ctx.textAlign='center';
- letcolors=['red','green','blue'];
- letlineCaps=['butt','round','square'];
- for(let[index,lc]oflineCaps.entries()){
- ctx.strokeStyle=colors[index];// 设置线段的颜色
- ctx.lineCap=lc;// 设置 lineCap
- ctx.beginPath();// 清空当前路径
- ctx.moveTo(10,20+20*index);
- ctx.lineTo(50,20+20*index);
- ctx.stroke();
- ctx.fillText(lc,80,25+20*index);
- }
再来试试用不同的 lineJoin 值来绘制两个线段焦点处的样式
- ctx.lineWidth=20;
- ctx.textAlign='center';
- ctx.lineCap='butt';
- letcolors=['red','green','blue'];
- letlineJoins=['bevel','round','miter'];
- for(let[index,lj]oflineJoins.entries()){
- ctx.strokeStyle=colors[index];// 设置线段的颜色
- ctx.lineJoin=lj;// 设置 lineJoin
- ctx.beginPath();// 清空当前路径
- ctx.moveTo(10+80*index,20);
- ctx.lineTo(50+80*index,20);
- ctx.lineTo(50+80*index,60);
- ctx.stroke();
- ctx.fillText(lj,40+80*index,80);
- }
canvas 不仅可以绘制实线, 还可以绘制虚线. 绘制虚线, 通过设置 lineDashOffset 属性和调用 setLineDash()方式.
- ctx.lineWidth=10;
- ctx.textAlign='center';
- ctx.setLineDash([8,8]);// 表示实线部分 8 个像素, 间隙部分 8 个像素
- letcolors=['red','green','blue'];
- letlineDashOffsets=[1,2,4];
- for(let[index,ldOffset]oflineDashOffsets.entries()){
- ctx.strokeStyle=colors[index];// 线段颜色
- ctx.lineDashOffset=ldOffset;// 设置了偏移量
- ctx.beginPath();
- ctx.moveTo(10,20+20*index);
- ctx.lineTo(100,20+20*index);
- ctx.stroke();
- ctx.fillText(`lineDashOffset:${ldOffset}`,160,25+20*index);
- }
通过上述我们可以知道 lineDashOffset 就是设置的开始绘制虚线的偏移量. setLineDash()方法, 接受一个数组参数, 如果数组个数是奇数, 则会默认把当前数组元素复制一份, 使之变成偶数. 从第 0 个元素, 表示实线部分长度, 第 1 个元素, 表示间隙部分长度, 第 2 个元素, 表示实线部分长度, 第 3 个元素, 表示间隙部分长度, 如果到数组最后一个元素了, 又会从头开始, 以此类推.
- ctx.lineWidth=10;
- ctx.textAlign='center';
- letcolors=['red','green','blue','gray'];
- letlineDashes=[[20,20],[40,40],[20,40],[20,40,20]];
- for(let[index,ld]oflineDashes.entries()){
- ctx.strokeStyle=colors[index];// 设置颜色
- ctx.setLineDash(ld);// 设置 lineDash
- ctx.beginPath();
- ctx.moveTo(10,20+20*index);
- ctx.lineTo(171,20+20*index);
- ctx.stroke();
- ctx.fillText(`lineDashes:[${ld}]`,240,25+20*index);
- }
- letlineDashOffset=0;// 初始 lineDashOffset
- ctx.strokeStyle='green';
- functionanimate(){
- if(lineDashOffset>25){
- lineDashOffset=0;
- }
- ctx.clearRect(0,0,width,height);// 清空当前 canvas
- ctx.lineDashOffset=-lineDashOffset;// 设置 lineDashOffset
- ctx.setLineDash([4,4]);// 设置实线长度和间隙长度
- ctx.rect(20,20,100,100);// 绘制一个矩形
- ctx.stroke();// 对 canvas 当前路径描边
- lineDashOffset+=1;//lineDashOffset 偏移加 1
- Windows.requestAnimationFrame(animate);// 用浏览器帧速率来反复执行 animate 函数
- }
- animate();
小猿圈 Web 前端讲师认为: 授之以鱼更授之以渔, 想要了解更多关于 Web 前端开发方面的小伙伴, 可以关注小猿圈每天的动态 Web 前端自学2群: 738735873, 会不定期更新互联网编程知识, 希望对你的学习有一定的帮助.
来源: http://www.jianshu.com/p/c19cb2d924fc