未加星标

canvas 奇巧淫技(二)绘制箭头路径效果

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二03 | 时间 2018 | 作者 红领巾 ] 0人收藏点击收藏

前几天有很多人问到了如何绘制高德地图那样的 导航箭头线 效果,当时想了想并不难就先用canvas 做了,然后集成到mapbox 上,迁移到其他map lib 也只需要应用相应的 地理转屏幕坐标 函数。

线的绘制样式

在canvas 的应用中我们经常会遇到各种线样式的绘制,比如虚线,渐变线,带pattern 线(箭头,铁轨图标等),或者虚线与pattern 的动画效果。如下图所示,总结下实现方法。


canvas 奇巧淫技(二)绘制箭头路径效果
虚线样式 利用 CanvasRenderingContext2D.setLineDash 的方法设置虚线样式, 接受一个数组类型的参数([solid: number, empty:number]) ,表示实线虚线的像素比例. 比如 ctx.setLineDash([10, 5]),就可以画出上图的虚线效果。发挥想象可以做出更多奇特效果。比如让虚线动起来,有走马灯的感觉。。 渐变线样式

通过 createLinearGradient 函数创建渐变,然后设定其渐变色段, 赋值给strokeStyle,渐变效果如开头图所示

// 创建一个从左到右的渐变,从绿色渐变到几乎透明, var gradient = ctx.createLinearGradient(0, 0, 600, 0); gradient.addColorStop(0, "rgba(0,255,100,0.9)"); gradient.addColorStop(1, "rgba(255,255,255,0.1)"); ctx.strokeStyle = gradient; 复制代码

有个问题就是如果需要 渐变方向符合线条走向 ,这是常见需求,只需要提前算下每条线的范围和方向,创建对应的LinearGradient 即可,其实类似于下面的箭头绘制,需要 反算 atan 角度 一样的。

icon pattern 的线样式

最后这个算是综合的应用,我写了些canvas functions 放到了之前的canvasOverlay 里面去用,可以方便的集成到各种支持canvas 的lib 里面用。 基本思路就是:(懒得画图了,思路比较简单)

每一个 有向线段 根据startPnt, endPnt 坐标反算 atan 弧度角

设定一个stepSize,在线段上生成绘制图标的坐标,把ctx.原点平移到这个点,并且旋转弧度角去绘制 图标的偏向(熟悉canvas 的应该都明白,通过操作canvas 坐标轴去绘制旋转要素)

需要注意的是,atan弧度角的计算在第二三象限,会跟第一四象限混淆。比如向左下角的 有向线的向量 是两个负值,但是tan 值是正的,跟第一象限一样,所以反算的时候也会算出来小于90度的角,实际上是大于180 的角度了,需要 + Math.PI


canvas 奇巧淫技(二)绘制箭头路径效果

大概的绘制过程,code as follow:

function generatePoints(startP, endP, stepSize = 30, ctx, aniOffset = 0.5, img) { let radA = Math.atan((endP[1] - startP[1]) / (endP[0] - startP[0])); if ((endP[0] - startP[0]) < 0) { radA += Math.PI; } const dist = calcDist(startP, endP); let points = []; const steps = dist / stepSize; const drawImg = (pX, pY) => { if (img && ctx) { ctx.save(); ctx.translate(pX , pY); // consider img position and imgWidth/Height. ctx.rotate(radA); ctx.drawImage(img, -img.width / 2, -img.width/2); ctx.restore(); } } // gen points by stepSize.. if enable corner arrow, start s with (0~1) float number. for (let s = aniOffset; s <= steps; s += 1) { const pX = Math.round(startP[0] + s * stepSize * Math.cos(radA)); const pY = Math.round(startP[1] + s * stepSize * Math.sin(radA)); points.push([pX, pY]); drawImg(pX, pY); } // console.warn(`icon Number: ${points.length}`); return points; } 复制代码

就简单写到这里,集成mapbox 的DEMO

最近还有个问题提到比较多,关于canvas 上的图标如何贴合地图的倾斜,这也是个视觉上的问题。大抵上可以通过CSS3d 或者 canvas 的透视去做,前者应该更简单些。有空再实践下

因为之前也写过一些canvas 的文章,比如绘制风向图,希望形成一个系列,所以这次就叫第二篇,下一篇应该是icon与倾斜角的贴合实践

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

tags: ctx,canvas,startP,Math,stepSize,img,绘制,虚线,radA,const,pY,points,pX,endP,渐变
分页:12
转载请注明
本文标题:canvas 奇巧淫技(二)绘制箭头路径效果
本站链接:https://www.codesec.net/view/586978.html


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(102)