代码如下:

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

1193

被折叠的 条评论
为什么被折叠?



