前幾天有不少人問到了如何繪製高德地圖那樣的導航箭頭線效果,當時想了想並不難就先用canvas 作了,而後集成到mapbox 上,遷移到其餘map lib 也只須要應用相應的地理轉屏幕座標函數。git
在canvas 的應用中咱們常常會遇到各類線樣式的繪製,好比虛線,漸變線,帶pattern 線(箭頭,鐵軌圖標等),或者虛線與pattern 的動畫效果。以下圖所示,總結下實現方法。github
好比 ctx.setLineDash([10, 5]),就能夠畫出上圖的虛線效果。發揮想象能夠作出更多奇特效果。好比讓虛線動起來,有走馬燈的感受。。canvas
經過 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 角度同樣的。bash
最後這個算是綜合的應用,我寫了些canvas functions 放到了以前的canvasOverlay 裏面去用,能夠方便的集成到各類支持canvas 的lib 裏面用。 基本思路就是:(懶得畫圖了,思路比較簡單)ide
每個有向線段根據startPnt, endPnt 座標反算 atan 弧度角函數
設定一個stepSize,在線段上生成繪製圖標的座標,把ctx.原點平移到這個點,而且旋轉弧度角去繪製 圖標的偏向(熟悉canvas 的應該都明白,經過操做canvas 座標軸去繪製旋轉要素)post
須要注意的是,atan弧度角的計算在第二三象限,會跟第一四象限混淆。好比向左下角的有向線的向量是兩個負值,可是tan 值是正的,跟第一象限同樣,因此反算的時候也會算出來小於90度的角,其實是大於180 的角度了,須要 + Math.PI優化
大概的繪製過程,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;
}
複製代碼
最近還有個問題提到比較多,關於canvas 上的圖標如何貼合地圖的傾斜,這也是個視覺上的問題。大抵上能夠經過CSS3d 或者 canvas 的透視去作,前者應該更簡單些。有空再實踐下。
由於以前也寫過一些canvas 的文章,好比繪製風向圖,但願造成一個系列,因此此次就叫第二篇,下一篇應該是icon與傾斜角的貼合實踐
最近Update (2019-10):