Html Canvas 自定义绘图

Html Canvas 自定义绘图

制作 Html 的时候我们总是不可避免的会遇到需要自定义 Canvas
绘图的情况,最近我在做网页的时候就遇到了需要需要自定义的绘图控件,效果图如下,框起来的地方就是我遇到的难点:
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;
Search by:GoogleBingBaidu