尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

鸿蒙HarmonyOS NEXT 球型水波纹动画

鸿蒙HarmonyOS NEXT 球型水波纹动画 找了很久水波纹动画不是扩散的那种水波纹没找到都是看来没人搞那我来搞一个吧线上图看效果注释写的很详细了我就不过多阐述了看代码吧Entry Component struct WaterWaveBall { private settings: RenderingContextSettings new RenderingContextSettings(true); private context: CanvasRenderingContext2D new CanvasRenderingContext2D(this.settings); State private phase: number 0; // 波浪相位 private timer: number 0; // 定时器ID private centerX: number 100; // 球心X坐标200/2100 private centerY: number 100; // 球心Y坐标200/2100 private radius: number 100; // 球体半径留出边框空间 private amplitude: number 10; // 波浪振幅按比例缩小 private waveLength: number 180; // 波浪长度按比例缩小 private waterLevel: number 180; // 水位高度按比例缩小 private waveSpeed: number 2; // 波浪速度按比例调整 aboutToAppear() { // 启动波浪动画 this.setprogress(0.5) this.startWaveAnimation(); } aboutToDisappear() { // 清除定时器 if (this.timer) { clearInterval(this.timer); this.timer 0; } } setprogress(p: number) { this.waterLevel 180 - 180 * p } // 启动波浪动画 startWaveAnimation() { if (!this.timer) { this.timer setInterval(() { // 更新波浪相位 - 确保波浪由左向右移动 this.phase (this.phase this.waveSpeed) % this.waveLength; }, 30); } } // 计算波浪Y坐标确保波浪向右移动 calculateWaveY(x: number, phase: number): number { return this.waterLevel this.amplitude * Math.sin(2 * Math.PI * (x - phase) / this.waveLength); } // 绘制波浪尺寸优化版 drawWave(ctx: CanvasRenderingContext2D) { const canvasSize 200; // 画布尺寸改为200 // 1. 清除画布 ctx.clearRect(0, 0, canvasSize, canvasSize); // 2. 绘制绿色边框 ctx.beginPath(); ctx.arc(this.centerX, this.centerY, this.radius, 0, Math.PI * 2); ctx.lineWidth 20; ctx.strokeStyle Color.Orange; ctx.stroke(); // 3. 设置圆形裁剪区域 ctx.beginPath(); ctx.arc(this.centerX, this.centerY, this.radius - 10, 0, Math.PI * 2); ctx.clip(); // 4. 绘制水面区域粉色- 波浪由左向右移动 ctx.beginPath(); // 起始点 const startY this.calculateWaveY(0, this.phase); ctx.moveTo(0, startY); // 使用二次贝塞尔曲线绘制主波浪 const points 30; // 减少点数以适应小尺寸 for (let i 1; i points; i) { const x (i / points) * canvasSize; const y this.calculateWaveY(x, this.phase); // 前一个点 const prevX ((i - 1) / points) * canvasSize; const prevY this.calculateWaveY(prevX, this.phase); // 计算控制点取中点 const cpx (prevX x) / 2; const cpy (prevY y) / 2; // 使用二次贝塞尔曲线 ctx.quadraticCurveTo(cpx, cpy, x, y); } // 封闭路径 ctx.lineTo(canvasSize, canvasSize); ctx.lineTo(0, canvasSize); ctx.closePath(); // 5. 填充波浪区域粉色渐变 const gradient ctx.createLinearGradient(0, this.waterLevel - 25, 0, canvasSize); gradient.addColorStop(0, #3de1ad); // 浅绿色 gradient.addColorStop(0.7, #0eb83a); // 绿色 gradient.addColorStop(1, #0c8918); // 深绿色 ctx.fillStyle gradient; ctx.fill(); // 6. 绘制球体内部的渐变效果 ctx.beginPath(); ctx.arc(this.centerX, this.centerY, this.radius - 2, 0, Math.PI * 2); const ballGradient ctx.createRadialGradient( this.centerX, this.centerY - 15, 10, this.centerX, this.centerY, this.radius ); ballGradient.addColorStop(0, rgba(224, 247, 250, 0.9)); ballGradient.addColorStop(0.7, rgba(224, 247, 250, 0.5)); ballGradient.addColorStop(1, rgba(224, 247, 250, 0.1)); ctx.fillStyle ballGradient; ctx.fill(); } build() { Column() { // 标题 Text(小型球体水波浪动画) .fontSize(20) .fontWeight(FontWeight.Bold) .margin({ bottom: 15 }) .fontColor(#333) // 球形容器 Stack() { // 绘制波浪球 Canvas(this.context) .width(200) .height(200) .onReady(() { // 初始绘制 this.drawWave(this.context); // 设置动画循环 setInterval(() { this.drawWave(this.context); }, 30); }) } .width(200) .height(200) .borderRadius(100) .margin({ bottom: 15 }) .backgroundColor(#387ec3) .clip(true) // 确保内容被裁剪为圆形 } .width(100%) .height(100%) .justifyContent(FlexAlign.Center) .alignItems(HorizontalAlign.Center) .backgroundColor(#F5F5F5) .padding(20) } }
返回列表