Html Canvas 自定义绘图
Html Canvas 自定义绘图
制作 Html 的时候我们总是不可避免的会遇到需要自定义 Canvas
绘图的情况,最近我在做网页的时候就遇到了需要需要自定义的绘图控件,效果图如下,框起来的地方就是我遇到的难点:
这是一个可以变化的进度条,上面有一个标签指向进度的位置。直接用html标签组合不实用,于是我想到了使用canvas的方式来绘制。
需求分析
- 只需要简单引用一个js文件
- 实现一个类,所有操作可以通过该类方法直接设置
- 可以复用
实现类
js
是脚本语言,没有类的概念,但是我们可以使用方法来实现类似类的效果,具体方法是:
//类
function ClassName(){
this.a = 0; //假设定义变量 a = 0
// ....变量定义 //
//方法
function functionName(){
//具体交互
this.a = 1 //改变变量的值
}
}
Canvas绘图
接下来我们来实现效果图的进度条效果,通过观察可以发现进度条控件可以分为两个部分,一个是底下的长条,另一部分就是上面的标签了。所以我们可以分为两个步骤来实现这个效果。
实现长条
我们可以将进度条拆分为上下两层,底下的灰色圆角矩形和表示进度的橘色圆角矩形,因为两个圆角矩形的区别只有长度和颜色,所以我们可以定义一个方法,用来绘制指定长度和颜色的圆角矩形:
/**画圆角矩形
* progress :进度1 -100
* color :颜色
*/
this.drawRectLine = function(progress, color) {
progress = Math.min(progress, 100);
progress = Math.max(progress, 0);
var height = this.canvas.getBoundingClientRect().height;
//进度条的高度
var lineHeight = height / 5;
var width = this.canvas.width - lineHeight / 2;
//设置填充颜色
this.ctx.fillStyle = color;
//开始绘制路径
this.ctx.beginPath();
//设置起点
this.ctx.moveTo(lineHeight / 2, height - lineHeight);
//终点的x坐标
var endX = progress / 100.0 * width;
endX = Math.max(endX, lineHeight / 2);
//绘制直线
this.ctx.lineTo(width - lineHeight / 2, height - lineHeight);
//绘制圆弧
this.ctx.arc(endX, height - lineHeight / 2, lineHeight / 2, -Math.PI / 2, Math.PI / 2);
this.ctx.lineTo(lineHeight / 2, height);
this.ctx.arc(lineHeight / 2, height - lineHeight / 2, lineHeight / 2, Math.PI / 2, -Math.PI / 2);
//填充路径
this.ctx.fill();
}
绘制进度标签
进度标签分为地步的气泡和上面的文字,可以分为两步完成。首先实现气泡背景,方法与绘制圆角矩形类似,只需要根据形状绘制路径填充即可。接下来是绘制文字:
//画文字
this.drawText = function() {
//设置文字的颜色
this.ctx.fillStyle = "white";
//设置文字的字体
this.ctx.font = "" + this.canvas.height / 4 + "px OpenSans";
//设置显示的文本
var s = "筹款中"
if(this.progress >= 100)
s = "完成"
//根据进度计算文字的x坐标
var x = this.progress / 100.0 * (this.canvas.width) - this.ctx.measureText(s).width / 2;
if(x < this.tagWidth / 2)
x = this.tagWidth / 2 - this.ctx.measureText(s).width / 2;
else if(x > this.canvas.width - this.tagWidth)
x = this.canvas.width - this.tagWidth / 2 - this.ctx.measureText(s).width / 2;
var y = this.canvas.height / 5 * 1.5;
//绘制文字
this.ctx.fillText(s, x, y);
}
定义外部调用方法
实现了绘制的逻辑之后,我们还需要定义一个方法,来实现进度的显示和改变。
// 设置进度
this.setProgress = function(progress) {
this.progress = progress;
this.showProgress();
}
//显示进度
this.showProgress = function() {
this.drawRectLine(100.0, this.bgColor);
this.drawRectLine(this.progress, this.hiColor);
this.drawTag();
this.drawText();
}
注意事项
这里有一个很大的坑,就是canvas默认是300x150
的大小,就算你在html里面设置了宽高,它也只会根据这个大小进行拉伸,所以显示会有拉伸现象。
解决办法: 根据canvas的大小对画布进行重新设置大小:
//重新设置画布的大小,解决画布拉伸的问题
this.canvas.width = this.canvas.offsetWidth;
this.canvas.height = this.canvas.offsetHeight;