h5 canvas学习之绘制圆形波浪进度条

2018-11-26  本文已影响0人  全校最帅的人

         之前做android原生开发,现在公司又让搞搞h5,所有就开始学习js的相关知识,canvas是h5的一个重要元素(当然原生的Canvas要好用的多)。都是绘制图形来制作控件。当然了,画图的思想没太大变化,主要是API的不同以及语言区别,需要排坑。希望帮到才入坑的萌新。废话不多说,效果图:

        现在的流程是:画圆、画波浪、画文字、然后就是进度的设置和获取。以及各样式的设置和获取。最后就是封装在一个js文件中。

1 画圆

画图形的条件是上下文要存在

var myCanvas = document.getElementById(id);

var ctx = myCanvas.getContext("2d");

if(ctx) {

//画图

}

画圆API

arc(x, y, radius, startAngle, endAngle, anticlockwise)

画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle(弧度,弧度=(Math.PI/180)*角度)结束,按照anticlockwise给定的方向(默认为顺时针)来生成。关键代码

c.beginPath();

c.arc(X, Y, radius, 0, Math.PI * 2, true);

c.closePath();

c.stroke();

c.clip();

stroke()就是绘制空心的形状,clip就是裁剪画布,当前是什么形状,之后绘制的图形都只能现在在裁剪的画布上,这里裁剪掉圆之外的图形,

2 画波浪

波浪就是曲线,所以画曲线可以使用贝塞尔曲线就很方便了。

quadraticCurveTo(cp1x, cp1y, x, y)

绘制二次贝塞尔曲线,cp1x,cp1y为一个控制点,x,y为结束点。

bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

绘制三次贝塞尔曲线,cp1x,cp1y为控制点一,cp2x,cp2y为控制点二,x,y为结束点。

详细请移步贝塞尔曲线。 

静态的曲线有了之后再在x轴上不断的移动就形成了大波浪的样子。移动一次要重新绘制一次。

至于一个圆形内显示几个波,改变下波长即可

关键代码

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就是进度的控制。fill()就是填充

3 画文字

关键代码

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(),参数 (文字 x坐标 y坐标,可选的最大宽度)。

这里需要注意的是要把文字绘制在圆心(好看点,你非要写在其他地方也可以)。c.measureText(info).width这个方法是测量所绘制文字的宽度的,这样确定x的坐标,y坐标直接这只基线居中即可c.textBaseline = "middle";基线就是文字以那条线作为基准定位。可选的值包括:top, hanging, middle, alphabetic, ideographic, bottom。默认值是 alphabetic。图示(图片侵权的话联系我)

这样的话基本的图形就绘制号了,现在就可以添加动画了。

4 添加波浪动画。

if(window.requestAnimationFrame)

{ if(obj.anim)

{  cancelAnimationFrame(obj.anim);

}

var id = window.requestAnimationFrame(function() {

//波浪移动 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()

{ //波浪移动 mWaveDx += mWaveSpeed;

if(mWaveDx >= 2 * mWaveLength) { mWaveDx = 0;

}

c.clearRect(0, 0, w, h); draw(obj);

}, 20);

obj.anim = id;

}

没什么难度,就是改变x坐标的值然后重绘,方法clearRect就是清除一个矩形区域的图形,requestAnimationFrame方法是专门用来绘制图形的,这个方法要实现循环的话需要像setTimeout那样在函数内部再次调用setTimeout。不过这里调用之后形成递归,无需那样做。简单来说就是不管改变x坐标,清除画布,重新绘制。这样波浪就动起来了。

5 进度控制

这个只需要改变波浪的y轴坐标就行了。

if(pro == 0) {

mWaveDy = h;

} else if(pro == obj.mMaxValue)

{ mWaveDy = 0; }

else if(pro <= obj.mBorderwidth)

{ //进度小于线宽 圆的线过宽会遮住波浪 所以上移一点

mWaveDy = h - 2 * obj.mBorderwidth;

}

else if(pro >= obj.mMaxValue - obj.mBorderwidth)

{

//避免遮住 下移一点

mWaveDy = h - (pro / obj.mMaxValue) * h + 2 * obj.mBorderwidth;

}

else { mWaveDy = h - (pro / obj.mMaxValue) * h;

}

需要注意的是如果圆的线宽设置了大于1,波浪的高度需要相应的做处理,不然进度太低(比如1)波浪会显示不出,进度太高(比如98),就完全占满圆形了。

6 封装成一个js。

封装涉及到js的面向对象设计,大家可以看看JS高级程序设计。

完整的代码js学习

上一篇下一篇

猜你喜欢

热点阅读