? ? ? ? ?之前做android原生開發(fā)带膜,現(xiàn)在公司又讓搞搞h5吩谦,所有就開始學(xué)習(xí)js的相關(guān)知識(shí),canvas是h5的一個(gè)重要元素(當(dāng)然原生的Canvas要好用的多)膝藕。都是繪制圖形來制作控件式廷。當(dāng)然了,畫圖的思想沒太大變化芭挽,主要是API的不同以及語言區(qū)別懒棉,需要排坑。希望幫到才入坑的萌新览绿。廢話不多說策严,效果圖:
? ? ? ? 現(xiàn)在的流程是:畫圓、畫波浪饿敲、畫文字妻导、然后就是進(jìn)度的設(shè)置和獲取。以及各樣式的設(shè)置和獲取怀各。最后就是封裝在一個(gè)js文件中倔韭。
1 畫圓
畫圖形的條件是上下文要存在
var myCanvas = document.getElementById(id);
var ctx = myCanvas.getContext("2d");
if(ctx) {
//畫圖
}
畫圓API
arc(x, y, radius, startAngle, endAngle, anticlockwise)
畫一個(gè)以(x,y)為圓心的以radius為半徑的圓弧(圓)瓢对,從startAngle開始到endAngle(弧度寿酌,弧度=(Math.PI/180)*角度)結(jié)束,按照anticlockwise給定的方向(默認(rèn)為順時(shí)針)來生成硕蛹。關(guān)鍵代碼
c.beginPath();
c.arc(X, Y, radius, 0, Math.PI * 2, true);
c.closePath();
c.stroke();
c.clip();
stroke()就是繪制空心的形狀醇疼,clip就是裁剪畫布硕并,當(dāng)前是什么形狀,之后繪制的圖形都只能現(xiàn)在在裁剪的畫布上秧荆,這里裁剪掉圓之外的圖形倔毙,
2 畫波浪
波浪就是曲線,所以畫曲線可以使用貝塞爾曲線就很方便了乙濒。
quadraticCurveTo(cp1x, cp1y, x, y)
繪制二次貝塞爾曲線陕赃,cp1x,cp1y為一個(gè)控制點(diǎn),x,y為結(jié)束點(diǎn)颁股。
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
繪制三次貝塞爾曲線么库,cp1x,cp1y為控制點(diǎn)一,cp2x,cp2y為控制點(diǎn)二甘有,x,y為結(jié)束點(diǎn)廊散。
詳細(xì)請(qǐng)移步貝塞爾曲線。?
靜態(tài)的曲線有了之后再在x軸上不斷的移動(dòng)就形成了大波浪的樣子梧疲。移動(dòng)一次要重新繪制一次。
至于一個(gè)圓形內(nèi)顯示幾個(gè)波运准,改變下波長即可
關(guān)鍵代碼
c.moveTo(mWaveDx - 2 * mWaveLength, mWaveDy);
for(var j = -2; j <= 4; j++)
{
if(j % 2 == 0)
{ y = mWaveDy + mWaveheight;
}
else {
y = mWaveDy - mWaveheight;
}
c.quadraticCurveTo(mWaveDx + mWaveLength * (2 * j - 1) / 2, y, mWaveDx + mWaveLength * j, mWaveDy);
}
c.lineTo(w, h);
c.lineTo(0, h);
c.closePath();
c.fill();
mWaveDx 就是用來讓波浪飛幌氮,mWaveDy就是進(jìn)度的控制。fill()就是填充
3 畫文字
關(guān)鍵代碼
c.fillStyle = obj.mTextColor;
c.font = "bold " + obj.mTextSize + "px Microsoft Yahei";
c.textBaseline = "middle";
var info = obj.mProgress + "%";
c.fillText(info, X - c.measureText(info).width / 2, Y, 100);
繪制文字的方法就是fillText()胁澳,參數(shù) (文字 x坐標(biāo) y坐標(biāo),可選的最大寬度)该互。
這里需要注意的是要把文字繪制在圓心(好看點(diǎn),你非要寫在其他地方也可以)韭畸。c.measureText(info).width這個(gè)方法是測(cè)量所繪制文字的寬度的宇智,這樣確定x的坐標(biāo),y坐標(biāo)直接這只基線居中即可c.textBaseline = "middle";基線就是文字以那條線作為基準(zhǔn)定位胰丁∷骈伲可選的值包括:top,?hanging,?middle,?alphabetic,?ideographic,?bottom。默認(rèn)值是?alphabetic锦庸。圖示(圖片侵權(quán)的話聯(lián)系我)
這樣的話基本的圖形就繪制號(hào)了机蔗,現(xiàn)在就可以添加動(dòng)畫了。
4 添加波浪動(dòng)畫甘萧。
if(window.requestAnimationFrame)
{ if(obj.anim)
{ ?cancelAnimationFrame(obj.anim);
}
var id = window.requestAnimationFrame(function() {
//波浪移動(dòng) mWaveDx += mWaveSpeed;
if(mWaveDx >= 2 * mWaveLength)
{ mWaveDx = 0;
}
c.clearRect(0, 0, w, h);
draw(obj);
});
obj.anim = id;
}
else { if(obj.anim)
{ ?clearTimeout(obj.anim);
}
var id = window.setTimeout(function()
{ //波浪移動(dòng) mWaveDx += mWaveSpeed;
if(mWaveDx >= 2 * mWaveLength) { mWaveDx = 0;
}
c.clearRect(0, 0, w, h); draw(obj);
}, 20);
obj.anim = id;
}
沒什么難度萝嘁,就是改變x坐標(biāo)的值然后重繪,方法clearRect就是清除一個(gè)矩形區(qū)域的圖形扬卷,requestAnimationFrame方法是專門用來繪制圖形的牙言,這個(gè)方法要實(shí)現(xiàn)循環(huán)的話需要像setTimeout那樣在函數(shù)內(nèi)部再次調(diào)用setTimeout。不過這里調(diào)用之后形成遞歸怪得,無需那樣做咱枉。簡單來說就是不管改變x坐標(biāo)卑硫,清除畫布,重新繪制庞钢。這樣波浪就動(dòng)起來了拔恰。
5 進(jìn)度控制
這個(gè)只需要改變波浪的y軸坐標(biāo)就行了。
if(pro == 0) {
mWaveDy = h;
} else if(pro == obj.mMaxValue)
{ mWaveDy = 0; }
else if(pro <= obj.mBorderwidth)
{ //進(jìn)度小于線寬 圓的線過寬會(huì)遮住波浪 所以上移一點(diǎn)
mWaveDy = h - 2 * obj.mBorderwidth;
}
else if(pro >= obj.mMaxValue - obj.mBorderwidth)
{
//避免遮住 下移一點(diǎn)
mWaveDy = h - (pro / obj.mMaxValue) * h + 2 * obj.mBorderwidth;
}
else { mWaveDy = h - (pro / obj.mMaxValue) * h;
}
需要注意的是如果圓的線寬設(shè)置了大于1基括,波浪的高度需要相應(yīng)的做處理颜懊,不然進(jìn)度太低(比如1)波浪會(huì)顯示不出,進(jìn)度太高(比如98)风皿,就完全占滿圓形了河爹。
6 封裝成一個(gè)js。
封裝涉及到j(luò)s的面向?qū)ο笤O(shè)計(jì)桐款,大家可以看看JS高級(jí)程序設(shè)計(jì)咸这。
完整的代碼js學(xué)習(xí)