canvas 绘制双线技能

楔子

近来一个项目,须要绘制双线的效果,双线效果示意的是轨道(相似铁轨之类的),以下图所示:

担任这块功用开辟的小伙,权且称之为L吧,最最先是经由历程数学盘算的体式格局来完成这类双线,也就是在本来的途径的基础上,盘算出两条途径。然则这个历程的盘算算挺庞杂,而是终究完成的效果很耗机能,机能消耗预计重要在于途径的盘算上。

优化技能

厥后他找到我来看这个题目,我在剖析了项目背景的状况下,赋予了一个简朴的绘制技能,就是先用较粗的线条绘制途径,然后再用较细的线条绘制途径,较细线条的色彩恰好是背景色彩。
之所以能够运用这个技能,是因为该项目的绘制背景是纯色的,而不是渐变色或许图片。
示例代码以下:

               ctx.beginPath();
               ctx.fillStyle = 'blue';
               ctx.rect(10,10,1000,1000);
               ctx.fill();

              ctx.save();
              ctx.strokeStyle = 'red';
              ctx.lineWidth = 10;
              ctx.lineCap = "round";
              ctx.beginPath();
              ctx.moveTo(200,100);  //起始点
              ctx.lineTo(400,100);
              ctx.quadraticCurveTo(500,100,500,200);   
              ctx.lineTo(500,400);
              ctx.quadraticCurveTo(500,500,400,500);   
              ctx.lineTo(200,500);
              ctx.quadraticCurveTo(100,500,100,400);   
              ctx.lineTo(100,200);
              ctx.quadraticCurveTo(100,100,200,100);   
              ctx.stroke();

              ctx.strokeStyle= 'blue'
              ctx.lineWidth = 4;
              ctx.stroke();
              ctx.restore();
              

代码的思绪是,起首运用纯色blue绘制了一个背景,然后运用线条色彩red绘制一条线,然后运用较小的线宽,并把线条色彩改成背景色彩blue,绘制别的一个条线段。终究的绘制效果以下:

《canvas 绘制双线技能》

到此,项目的这个手艺难点题目,算是被处理了。这类处理要领,不仅算法简朴,不必构想数学要领来构造双线,而且轻量,不会有机能累赘。

背景不是纯色状况

前面说到:之所以能够运用这个技能,是因为该项目的绘制背景是纯色的,而不是渐变色或许图片。
那假如背景是图片或许渐变色彩状况下,用这类技能,一定就是失效的了。

之所以会思索这个题目,是得益于公司的手艺分享会。我会请求员工按期构造分享会,分享一些履历。在此打个小广告,能够看出我们公司的手艺气氛是很好的,所以有兴致的小伙伴能够抓紧时间投简历。怎样投简历呢,关注微信号ITman彪叔。

历程当中,当时小伙伴L也分享了前面提到这类思绪。在分享的历程当中,我提出了进一步的题目,假如背景不是纯色,而是渐变色或许图片怎样办?而且灵感乍现,想到了一个处理要领,就是运用ctx.globalCompositeOperation。

有关globalCompositeOperation的申明,能够参考以下链接的申明:
https://developer.mozilla.org…
http://www.w3school.com.cn/ta…

globalCompositeOperation的定义和用法

globalCompositeOperation 属性设置或返回如何将一个源(新的)图象绘制到目的(已有)的图象上。个中:

  • 源图象 = 您盘算安排到画布上的画图。
  • 目的图象 = 您已安排在画布上的画图

下图显现了globalCompositeOperation的差别的值的诠释:
《canvas 绘制双线技能》

要完成双线的绘制,就请求用一样的途径,差别的线宽绘制两条线路
(我们称之为目的线路和源线路)。并要到达一条线路抠出别的一条线路的效果。
连系上图,我们能够看出destination-out,source-out,xor能够到达效果。下面以destination-out举例申明。

destination-out绘制道理申明

比方起首经由历程 css 设置背景图,并去掉绘制背景色彩,代码以下:

 <body onload="init()" style="background: url(../test/images/diffuse.png);">

然后绘制代码以下:

  ctx.save();
              ctx.strokeStyle = 'red';
              ctx.lineWidth = 10;
              ctx.lineCap = "round";
              ctx.beginPath();
              ctx.moveTo(200,100);  //起始点
              ctx.lineTo(400,100);
              ctx.quadraticCurveTo(500,100,500,200);   
              ctx.lineTo(500,400);
              ctx.quadraticCurveTo(500,500,400,500);   
              ctx.lineTo(200,500);
              ctx.quadraticCurveTo(100,500,100,400);   
              ctx.lineTo(100,200);
              ctx.quadraticCurveTo(100,100,200,100);   
              ctx.stroke();

              
              ctx.globalCompositeOperation = 'destination-out';
              ctx.lineWidth = 4;
              ctx.stroke();
              ctx.restore();

起首设置途径,然后设置线宽为10,挪用stroke要领绘制一条线宽为10的线路A。
以后设置globalCompositeOperation为 ‘destination-out’,调解线宽为4,挪用stroke要领绘制一条线宽为4的线路B。
看下destination-out的诠释:

在源图象外显现目的图象。只有源图象外的目的图象部份会被显现,源图象是通明的。

绘制了线路A的canvas图象是目的图象,线路B是源图象。依据上面诠释,只有源图象以外的目的图象能够被显现。终究绘制的效果以下:
《canvas 绘制双线技能》

xor 和 source-out

把上面的代码的globalCompositeOperation修改成xor,发明效果也是能够的,xor的诠释以下:

运用异或操刁难源图象与目的图象举行组合。 英文诠释以下:

Shapes are made transparent where both overlap and drawn normal everywhere else.

意思源和目的的像素堆叠(overlap)的部份会被变成通明像素,其他部份一般绘制。 所以上面示例中,线条A和线条B堆叠的部份会被变成通明。绘制的效果也是线条A的被挖空。

关于source-out,其效果恰好和destination-out的效果相反:

在目的图象以外显现源图象。只会显现目的图象以外源图象部份,目的图象是通明的。

应此只须要取反操纵即可,先用宽度4绘制线条A,然后用宽度10绘制线条B,其效果也是一样的。

背景不是纯色状况2

前面的背景是经由历程css的体式格局设置上去的,假如是经由历程canvas的drawImage直接绘制上去,效果就不一样了。还是以destination-out为例申明,起首绘制了image,然后绘制线路A,此时的目的图象不在是线路A构成的图形,而是image和线路A组合成的图形,此时用destination-out的体式格局绘制线路B,不仅会挖空线路A,背景也会被挖空,以下图所示:

《canvas 绘制双线技能》

应此要想到达真正的双线效果,要么背景只能是用css设置,要么用两个canvas叠加,一个绘制背景图片,一个绘制途径。
固然另有一种体式格局,就是绘制双线总是在一个暂时的canvas上面举行,然后把这个暂时的canvas绘制效果再次绘制到事情canvas上面,相干实践留给读者本身举行。

跋文

在收集上面搜刮canvas double line,搜刮到stackoverflow上的一条效果以下:
https://stackoverflow.com/que…
个中的答案也是采用了globalCompositeOperation设置为destination-out的体式格局。

迎接关注民众号“ITman彪叔”。彪叔,具有10多年开辟履历,现任公司体系架构师、手艺总监、手艺培训师、职业规划师。熟习Java、JavaScript、Python言语,熟习数据库。熟习java、nodejs运用体系架构,大数据高并发、高可用、分布式架构。在盘算机图形学、WebGL、前端可视化方面有深入研究。对程序员思维能力练习和培训、程序员职业规划有浓厚兴致。
《canvas 绘制双线技能》

    原文作者:netcy
    原文地址: https://segmentfault.com/a/1190000017459301
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞