自定义画圆进度条,带波浪动态效果

这篇博客详细介绍了如何利用HTML5的Canvas API来创建一个动态波浪运动效果。作者首先计算了圆弧的比例,然后通过定时器控制实体和空的圆弧部分形成波浪并左右移动,同时绘制背景和文字,最终实现了一个具有视觉吸引力的波浪动画。代码中涉及到的关键技术包括路径绘制、定时器、二次曲线和颜色填充等。

代码如下:

首先计算比例,通过高度与直径之比;

大于半径和小于半径两部分

            ctx.beginPath();
            if(posY>radius){
                ctx.arc(radius,radius,radius,startangle,Math.PI-startangle);
            }else{
                ctx.arc(radius,radius,radius,-startangle,Math.PI+startangle);
            }
            ctx.setFillStyle('#01BA48')
            ctx.setStrokeStyle('#01BA48')
            ctx.fill();
            ctx.stroke()

先画一个圆弧不带波浪的实体部分,如下图:

 

然后再话一个空的和实体的部分圆弧行成波浪,用一个定时器控制这个空的和实体两个小部分左右移动,方向自己定义

如下图:

最后画好背景和文字部分就完成了这个整体波浪运动效果,整体效果如下:

<template>
<view>
<view style="margin-top: 200rpx;">
    <view >
        <canvas class="cir-view" canvas-id="myCanvas4"></canvas>
    </view>
</view>
</view>
</template>
<script>
const app = getApp();
export default {
  data() {
    return {
      timer:null,
    };
  },
  
  onShow: async function () {
    this.drawQuadraticCurve4();
  },
  methods: {
   
    drawQuadraticCurve4() {
        var obj = this.obj;
        var startX = 150,
        itemWidth = 50,
        offset = 0,
        baseLine = 10,
        waveHeight = 20,
        direction = 1,
        waveDirection = -1,
        percent = 0.3,
        radius=91,
        offsetY=0.2,
        offsetrY= 0.3
        
        var posY = 2*radius * (1-percent); // 所在位置Y值
        var h= Math.abs(radius - posY); // 高
        var arrow = Math.sqrt(radius*radius - h*h);//半弦长
        console.log("arrow====>"+arrow);
        const ctx = uni.createCanvasContext('myCanvas4')
        var startX = radius - arrow;
        // d=200  80%   160  100   60 100
        // θ=2*acos(h/d)  弦对应角度
        var angle = 2*Math.acos(h/radius);
        
        
        
        console.log("angle====>"+angle);
        var startangle =  (Math.PI - angle)*0.5;
        console.log("startangle====>"+angle);
        
        
        var itemwidth = 2*arrow;
        var left = 0;
        
        
        
        
        setInterval(runcircle,100);
        
        function drawText() {
            ctx.globalCompositeOperation = 'source-over';
            var size = 34;
            ctx.font = '500 ' + size + 'px PingFang-SC-Medium, PingFang-SC';

            var txt = '+'+(percent.toFixed(2) * 100).toFixed(0) + '%';
            var fonty = radius + size / 2;
            var fontx = radius - size * 0.8;
            
            //字体颜色
            ctx.fillStyle = "rgba(8, 77, 25, 0.9)";
            ctx.textAlign = 'center';
            ctx.fillText(txt, radius + 5, radius)
            
        }
        function drawDescText() {
            ctx.globalCompositeOperation = 'source-over';
            var size = 13;
            ctx.font = '500 ' + size + 'px PingFang-SC-Medium, PingFang-SC';
        
            var txt = '+'+(percent.toFixed(2) * 100).toFixed(0) + '%';
            var fonty = radius + size / 2;
            var fontx = radius - size * 0.8;
            
            //字体颜色
            ctx.fillStyle = "#084D19";
            ctx.textAlign = 'center';
            ctx.fillText("本月成交率",radius + 5, radius + 24)
        }
        
        
        function runcircle(){
            
            ctx.beginPath();
            ctx.arc(radius,radius,radius,0,Math.PI*2);
            ctx.setFillStyle('#B3F0CB')
            ctx.setStrokeStyle('#B3F0CB')
            ctx.fill();
            ctx.stroke()
            
            ctx.beginPath();
            if(posY>radius){
                ctx.arc(radius,radius,radius,startangle,Math.PI-startangle);
            }else{
                ctx.arc(radius,radius,radius,-startangle,Math.PI+startangle);
            }
            ctx.setFillStyle('#01BA48')
            ctx.setStrokeStyle('#01BA48')
            ctx.fill();
            ctx.stroke()
            
            for(var i =0;i<6;i++){
                var posX = itemwidth*i + left;
                ctx.beginPath()
                ctx.moveTo(posX+offset+startX,posY+offsetY)
                ctx.quadraticCurveTo(posX +startX+arrow*0.5+offset,
                posY-waveHeight,posX +startX+arrow+offset, posY+offsetY);
                ctx.lineTo(posX+startX+offset, posY+offsetY)
                ctx.setFillStyle('#01BA48')
                ctx.setStrokeStyle('#01BA48')
                ctx.setLineWidth(0.01)
                ctx.fill()
                
                ctx.beginPath()
                ctx.moveTo(posX + radius+offset,posY-offsetrY)
                ctx.quadraticCurveTo(posX + arrow*1.5+offset,
                posY+waveHeight,posX+ (radius*2 - startX)+offset, posY-offsetrY);
                ctx.lineTo(posX + radius*2 - startX, posY-offsetrY)
                ctx.setFillStyle('#B3F0CB')
                ctx.setStrokeStyle('#B3F0CB')
                ctx.setLineWidth(0.01)
                ctx.fill()
            }
            
            
            // ctx.fillStyle="#ff00000";
            //         ctx.strokeStyle="#0000ff";
            //         ctx.lineWidth=3;
            //         ctx.rect(0,0,radius*2,radius*2);
            //         ctx.fill();//填充
            //         ctx.stroke();//绘制边框
            //         ctx.clearRect(50,50,150,150)
            //         ctx.clearRect()
            
            // ctx.beginPath();
            // ctx.moveTo(0,0)
            // ctx.lineTo(2*radius,0)
            // ctx.lineTo(2*radius,2*radius)
            // ctx.lineTo(0,2*radius)
            // ctx.setFillStyle('#F13737')
            // ctx.fill()
            
            ctx.beginPath();
            ctx.arc(radius,radius,radius,0,Math.PI*2);
            ctx.setFillStyle('transparent')
            ctx.setStrokeStyle('#FFFFFF')

            ctx.setLineWidth(15)
            ctx.fill();
            ctx.stroke()
            
            // ctx.beginPath();
            // ctx.arc(radius,radius,radius,0,Math.PI*2);
            // ctx.clip();
            
            drawText()
            drawDescText()
            ctx.draw()
            if (waveDirection == 1) {
                offset = offset + 1
            } else if (waveDirection == -1) {
                offset = offset - 1
            }
            if (offset >= 5*itemwidth) {
                offset = 0;
            }
            console.log("offset===>"+offset);
            
        }    
    }
  }
};
</script>
<style>
.cir-view{
    border-radius: 50%;
    width: 182px;
    height: 182px;
    background: #B3F0CB;
}
</style>

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值