canvas画波浪进度球
Posted pagoda
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了canvas画波浪进度球相关的知识,希望对你有一定的参考价值。
波浪进度球是一种非常常见的进度展示方式,常用于加载页。
首先来个例子
再来个过程
下面我们来学习一下如何画一个波浪进度球
- 首先我们分析一下进度球的组成部分有:一个圆,波纹,波纹的填充色,百分比文字
- 我们可以根据这几个组成部分来制作动画。
画一个圆
var drawCircle = function(){
ctx.beginPath();
ctx.strokeStyle = ‘#1080d0‘;
ctx.arc(r, r, cR+1, 0, 2 * Math.PI);
ctx.stroke();
}
上面代码中的:
ctx.arc() 方法就是画一个圆形路径,括号里面都是参数:坐标轴的位置,半径长度,起始位置弧度,终止位置弧度;
ctx.beginPath() 是用来开始一条路径或者重置一条路径,如果没有这个方法,画路径的时候会用新的笔触样式将之前的路径重画一遍。
而且不管你用moveTo把画笔移动到哪里,只要不beginPath,那你一直都是在画一条路径。如果你画出的图形和你想像的不一样,记得查看是否有合理的beginPath.
我们再来画波浪
var drawSin = function(xOffset, color, waveHeight){
ctx.save(); // 存储当前画布的样式等
var points=[]; //用于存放绘制Sin曲线的点
ctx.beginPath();
//在整个轴长上取点 , sx = 0; axisLength 是x轴轴长
for(var x = sX; x < sX + axisLength; x += Math.PI/6){
//此处坐标(x,y)的取点,依靠公式 “振幅高*sin(x*振幅宽 + 振幅偏移量)”
var y = Math.sin((sX + x) * waveWidth + xOffset) * 0.8 + 0.1;
var dY = mH * (1 - nowRange / 100 ); // 因为坐标系起点是左上角,所以y轴0点位置要用1-nowRange的差。
points.push([x, dY + y * waveHeight]); // 存储点
ctx.lineTo(x, dY + y * waveHeight); // 描路径
}
ctx.stroke()
ctx.restore(); // 恢复上一次ctx.save() 存储的,一定要有save()才有效,无默认。
};
主要内容就是三角函数里面的sin,画一个sin的坐标图来实现波纹。知识关联到canvas画图,就是将sin函数坐标点的xy轴坐标记录下来,并且用lineTo() 方法描点。上图是描点之后的样子,接下来我们需要填充颜色,填充颜色相关的方法是fill()。设置fillStyle颜色值。
ctx.fillStyle = color;
ctx.fill();
Σ(;?д?)
怎么成了这个鬼样子,和想象中不一样啊。对比之前的图片好像是根据y轴0坐标的位置形成的封闭回路做的填充。
所以我们需要规划一个封闭区间,因为我们的目的是要在波浪的下方填充颜色,所以需要将波浪下方的区域都包裹进来。我们要lineTo()到画布的右下角,再左下角,再回到起点。
这样我们再填充上颜色就会发现波浪线以下的区域都填充了颜色,但是可以预料到的是,这个颜色同时还覆盖了我们之前画的圆,成了圆上面的一个遮挡,并不像是圆里面的波浪。
将填充的颜色区域限制,让其看起来像在园内。
canvas有个方法叫clip(),对css比较熟悉的同学应会知道这个方法,他的作用就是限制可视范围的。我们可以在画圆的时候,用这个方法,将画布的可视范围限制在圆内, 记得不要在这里使用ctx.restore() ,否则无法做区域限制。
var drawCircle = function(){
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = ‘#1080d0‘;
ctx.arc(r, r, cR+1, 0, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(r, r, cR, 0, 2 * Math.PI);
ctx.clip();
}
//画sin 曲线函数 xOffset表示x轴方向的偏移距离
var drawSin = function(xOffset, color, waveHeight){
ctx.save();
var points=[]; //用于存放绘制Sin曲线的点
ctx.beginPath();
//在整个轴长上取点 , sx = 0; axisLength 是x轴轴长
for(var x = sX; x < sX + axisLength; x += Math.PI/6){
//此处坐标(x,y)的取点,依靠公式 “振幅高*sin(x*振幅宽 + 振幅偏移量)”
var y = Math.sin((sX + x) * waveWidth + xOffset) * 0.8 + 0.1;
var dY = mH * (1 - nowRange / 100 ); // 因为坐标系起点是左上角,所以y轴0点位置要用1-nowRange的差。
points.push([x, dY + y * waveHeight]); // 存储点
ctx.lineTo(x, dY + y * waveHeight); // 描路径
}
//封闭路径
ctx.lineTo(axisLength, mH); // 右下角的点
ctx.lineTo(sX, mH); // 左下角的点
ctx.lineTo(points[0][0],points[0][1]); // 波浪起点
// ctx.stroke()
ctx.fillStyle = color;
ctx.fill();
ctx.restore();
};
因为已经填充颜色了,所以ctx.stroke() 方法就不需要了。
让波浪动起来
波浪动起来的原理就是我们的sin曲线动起来,怎么动呢? 比较初级的就是水平平移,所以我们需要重复调用画曲线的方法,然后每次调用都给一个平移的值。这就是上面代码中xOffset的作用。
平移有了,然后就是需要让他自动重复调用这个方法就可以。这个我们可以用setTimeout或者setInterval来实现,但是这两个方法不是动画专用的方法,所以性能方面不是很优,最好使用由浏览器专门为动画提供的API——requestAnimationFrame() 。把上面的画圆画波浪方法放进一个render() 方法封装起来,然后requestAnimationFrame(render) 调用。就可以实现动画的效果了。但是这个时候我们发现上面的曲线虽然运动了,但是看起来很违和,这是因为波浪宽度太小的原因,我们可以修改参数将波浪扩大。也就是修改waveWidth 这个变量的值,waveWidth越小,波纹越宽。我们还可以再添加一个颜色潜一些的波纹,让波浪看起来更加立体。
写文字
var drawText = function(){
ctx.save();
var size = 0.4*cR;
ctx.font = size + ‘px Microsoft Yahei‘;
ctx.textAlign = ‘center‘;
ctx.fillStyle = "rgba(06, 85, 128, 0.5)";
ctx.fillText(~~nowRange + ‘%‘, r, r + size / 2); // ~是取反,~~ 的目的是为了保证nowRange是数字
ctx.restore();
};
这就是最终效果了,文中提到的是绘制的主要过程和思路,不是所有代码。————jsdoit
以上是关于canvas画波浪进度球的主要内容,如果未能解决你的问题,请参考以下文章
用canvas画布画一个圆形的进度条,里面的数字是模糊的怎么解决?谢谢