资讯专栏INFORMATION COLUMN

canvas实现仪表盘

caiyongji / 1758人阅读

摘要:根据项目要求,要实现这样一个仪表盘的效果拿到图之后首先做一个拆分,分成几个小模块。其中是圆心角度数,是半径,是圆心角弧长。

根据项目要求,要实现这样一个仪表盘的效果:

拿到图之后首先做一个拆分,分成几个小模块。从里往外看,首先需要一个内环的刻度条,这个内环刻度条由若干个点构成,所以我的实现方式为:先画一根线,通过循环,旋转得到一个圆形的刻度条

//innerLineNums 为刻度数量
ctx.save(); 
for (var i = 0; i <= $this.innerLineNums; i++) {
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = "rgba(155,157,183,1)";               
    ctx.moveTo(82, 0);
    ctx.lineTo(80, 0);
    ctx.stroke();
    //每个点的弧度,360°弧度为2π,即旋转弧度为 2π / 75
    ctx.rotate(2*Math.PI / $this.innerLineNums);
}                      
ctx.restore();    

其次再是里面的长刻度线,以及数字标志,还有中间的文字

// 内环刻度线
ctx.save();
for (var i = 0; i < 6; i++) {
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = "rgba(155,157,183,1)";
    ctx.moveTo(82, 0);
    ctx.lineTo(78, 0);
    ctx.stroke();

    //每10个点分一个刻度,共5个刻度,旋转角度为deg1 * 10
    ctx.rotate(deg1 * 10);
}
ctx.restore();

//内环刻度上面数字
ctx.save();
ctx.rotate(Math.PI / 2);
for (i = 0; i < 6; i++) {
    ctx.fillStyle = "rgba(165,180,198, .4)";
    ctx.font = "10px Microsoft yahei";
    ctx.textAlign = "center";
    ctx.fillText(20 * i, 0, -65);
    ctx.rotate(deg1 * 10);
}
ctx.restore();

//内环文字
ctx.save();
ctx.rotate(210 * Math.PI / 180);
ctx.fillStyle = "#000";
ctx.font = "44px Microsoft yahei";
ctx.textAlign = "center";
ctx.textBaseLine = "top";
ctx.fillText(process, 0, 10);
var width = ctx.measureText(process).width;

ctx.fillStyle = "#000";
ctx.font = "20px Microsoft yahei";
ctx.fillText("分", width / 2 + 10, 10);

好了,此时内环的效果已经有了,可以看到如下效果:

再来看外环的刻度条,外环刻度条有一个缺口,目测估算一下,算缺口为1/3,即外环的刻度线需要画120-360°,我们这里分数满分为100分,从0开始,为了方便计算就给他画50根刻度线,那么每根刻度线的角度deg1的算法为:

//弧长计算公式是一个数学公式,为L=n(圆心角度数)× π(1)× r(半径)/180(角度制),L=α(弧度)× r(半径) (弧度制)。其中n是圆心角度数,r是半径,L是圆心角弧长。
//整个运动的角度是(360-120)度,转换成弧度就是12π/9,一共分成了50个分数段,那么每一个分数段就是12π/450 = 2π / 75
//如需旋转 5 度,可规定下面的公式:5*Math.PI/180。            
deg1() {
    return (Math.PI * 12) / (9 * this.lineNums)
}

从这里我们知道了外环2/3个圆的刻度线为50根,那么内环整个圆的刻度线innerLineNums = 50 * 3 / 2 = 75根。好了,知道角度之后还是按照之前的方法,画一根线,然后循环,在旋转,跳跃画出灰色的外环刻度线:

// 细分内环刻度线
ctx.save();
for (var i = 0; i <= $this.innerLineNums; i++) {
    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = "rgba(155,157,183,1)";
    ctx.moveTo(82, 0);
    ctx.lineTo(80, 0);
    ctx.stroke();

    //每个点的弧度,360°弧度为2π,即旋转弧度为 2π / 75
    ctx.rotate(2 * Math.PI / $this.innerLineNums);
}
ctx.restore();

这个时候效果是这样的:

还差外环的渐变线,以及线上面的那个点,那根线是根据分数动态画的,所以长度需要计算,我打算用一个圆弧来实现,上面说过每个线之间的旋转弧度为deg1,那圆弧的长度就等于score * deg1 / 2,根据公式画出线如下:

 //色彩段数与彩色刻度条保持一致,线条无间隔,所以段数 * 2
var gradient = ctx.createLinearGradient(0, 0, $this.colorLineNums * 2, 0);
gradient.addColorStop("0", "rgba(252,3,44,.6)");
gradient.addColorStop("0.5", "rgba(134,37,168,.6)");
gradient.addColorStop("1.0", "rgba(54,63,255,.6)");

//外环渐变线
ctx.save();
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = gradient;
ctx.arc(0, 0, radius, 0, angle, false);
ctx.stroke();
ctx.restore();

此时效果是这样的:


还有圆外环彩线上面的圆点,可以用一个小圆实现,然后改变他的x,y坐标即可实现:

ctx.save();
ctx.beginPath();
ctx.fillStyle = "rgba(255, 255, 255, 1)";
ctx.arc(this.x, this.y, 5, 0, Math.PI * 2, false);
ctx.fill();
ctx.lineWidth = 1;
ctx.strokeStyle = "rgba(246, 5, 51, 1)";
ctx.stroke();
ctx.restore();

ctx.save();
ctx.beginPath();
ctx.fillStyle = "rgba(246, 5, 51, 1)";

ctx.arc(this.x, this.y, 3, 0, Math.PI * 2, false);
ctx.fill();

ctx.restore();

此时,还差个彩色的线,效果如下,额,这个彩色的线如何实现呢,刚开始也是不知如何下手,经过高人指点后,得出结局方案:把渐变色切割,多少根彩线就分割成多少份,然后感谢 嗑瓜子儿gf-颜色渐变的JS代码 写的博客,提供了算法

最终效果出来了:


预览组件

第一次写canvas组件,此代码仅供参考,最后感谢[masqli-canvas仿芝麻信用分仪表盘
][3],参考了前面两位博主的代码才能实现我项目的需求,所谓前人栽树,后人乘凉,今天把我写的也分享给大家,能帮到大家就更好,对我自己也算做个笔记了,在此再次感谢两位博主

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/99343.html

相关文章

  • canvas && CSS 两种实现表盘的方式

    摘要:先上效果图这种图形大家应该都见过,俗称仪表盘,当然,上图只是个最基本的仪表盘架子,可能在实际场景中还会其他很多花里胡哨的点缀,那些暂且不管,不是关键,这东西经常见到,但还没亲自上手在代码层面实现过,最近做的一个需求恰好有这个场景,这里归先上效果图: showImg(https://user-gold-cdn.xitu.io/2019/5/23/16ae28a94cb51d3e); 这种图形大...

    番茄西红柿 评论0 收藏0
  • canvas && CSS 两种实现表盘的方式

    摘要:先上效果图这种图形大家应该都见过,俗称仪表盘,当然,上图只是个最基本的仪表盘架子,可能在实际场景中还会其他很多花里胡哨的点缀,那些暂且不管,不是关键,这东西经常见到,但还没亲自上手在代码层面实现过,最近做的一个需求恰好有这个场景,这里归先上效果图: showImg(https://user-gold-cdn.xitu.io/2019/5/23/16ae28a94cb51d3e); 这种图形大...

    stormjun 评论0 收藏0
  • canvas仿芝麻信用分表盘

    摘要:,这是一个仿支付宝芝麻信用分的一个,其实就是一个动画仪表盘。首先,上原图这个是在下支付宝上的截图,分低各位见笑了。 hi,这是一个仿支付宝芝麻信用分的一个canvas,其实就是一个动画仪表盘。 首先, 上原图: showImg(https://segmentfault.com/img/bVbn3D6?w=750&h=1334); 这个是在下支付宝上的截图,分低各位见笑了。然后看下我用c...

    ASCH 评论0 收藏0
  • canvas 高仿 Apple Watch 表盘

    摘要:绘制表盘指针对指针的绘制,首先以原点为中心绘制一个圆,对延伸出来的指针思考了两种绘制方法第一种以轴左半边为例,点为起始点,以为控制点,为终点绘制三次贝塞尔曲线第二种以轴右半边为例,直接从点绘制直线到。 不知道大家童年时候有没有在手上画手表的经历,恰好最近在看 canvas ,于是就诞生了这个高仿表盘。 showImg(https://segmentfault.com/img/bV7y...

    Fourierr 评论0 收藏0

发表评论

0条评论

caiyongji

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<