最近闲来无事,打开网易云音乐,发现还有鲸云音效这种东西,嗯?『水晶音波』,挺炫。嗯?黑胶VIP专享?(其实我已经是黑胶VIP)好像实现起来也不很复杂呀,所以花了一下午,实现了一个简单版本。

这是网易云音乐的截图,结尾放我自己实现的效果

先明确一点,简单实现,所以没搞懂的,不想做的,都省略不做了。

HTML

简单嘛~
不需要太多元素,简简单单才是真

<div class="debut"><!-- 背景部分 --><canvas class="music-cover-background" id="background">your brower does not support canvas</canvas><!-- 前景部分 --><div class="music-cover"><img src="data:images/1753378458.jpg" class="music-cover-image"></img></div>
</div>

CSS

开局找个地,然后画个圈

.debut {position: absolute;width: 100%;height: 100%;display: inline-flex;align-items: center;justify-content: center;
}.music-cover {width: 23.75rem;  /* 380px */height: 23.75rem; /* 380px */box-sizing: border-box;border: .125rem solid #B3B3B3; /* 2px solid #B3B3B3 */border-radius: 50%;display: inline-flex;align-items: center;justify-content: center;
}

使用flex布局实现居中

圈中贴个图,让它转起来

.music-cover-image {width: 21.25rem; /* 340px */height: 21.25rem; /* 340px */border: none;border-radius: 50%;animation: rotate infinite linear 25s;
}@keyframes rotate {from { transform: rotate(0deg); }to { transform: rotate(360deg); }
}

动画时间25s是我用秒表测的

图后画阴影,颜色简单选

.music-cover::before {content: "";position: absolute;width: 21.25rem; /* 340px */height: 21.25rem; /* 340px */border-radius: 50%;filter: blur(1.875rem); /* 30px */background-image: radial-gradient(white, silver);
}

使用伪元素就够了

一通操作之后,“唱片”就实现了,下面是效果图:

嗯,还行,接下来才是canvas画背景部分,也就是三角形往外飘嘛~
不难。

canvas

画布定个位

.music-cover-background {position: absolute;
}

position: absolute后,会因为父元素.debut采用flex布局而居中

紧接定大小

const canvas = document.getElementById('background');
canvas.width = canvas.height = Math.ceil(canvas.parentNode.lastElementChild.offsetWidth * 1.68421);

堆个三角形

const PI2 = 2 * Math.PI;
class Triangle {constructor(context, speed, pole, range) {this.ctx = context;this.pole = pole;this.range = range;this.speed = speed;this.points = [[0, 0], [0, 0], [0, 0]];this.__restart();}__restart() {this.angle = Math.random() * PI2; // 随机生成一个移动方向this.speedX = Math.cos(this.angle) * this.speed;this.speedY = Math.sin(this.angle) * this.speed;this.opacity = 1;const dist = Math.random() * 150; // 为了让三角形生成错落有致,所以让三角形从距离pole点的一个随机距离dist出发const distX = Math.cos(this.angle) * dist;const distY = Math.sin(this.angle) * dist;const θ = Math.random() * PI2; // 将三角形随机旋转一个θ°const x2 = Math.random() * 10;const y2 = 20 + Math.random() * 20;const x3 = 10 + Math.random() * 15;const y3 = 12 + Math.random() * 6;this.points[0][0] = Math.floor(this.pole[0] + distX);this.points[0][1] = Math.floor(this.pole[1] + distY);this.points[1][0] = Math.floor(this.pole[0] + distX + (x2 * Math.cos(θ) - y2 * Math.sin(θ)));this.points[1][1] = Math.floor(this.pole[1] + distY + (y2 * Math.cos(θ) + x2 * Math.sin(θ)));this.points[2][0] = Math.floor(this.pole[0] + distX + (x3 * Math.cos(θ) - y3 * Math.sin(θ)));this.points[2][1] = Math.floor(this.pole[1] + distY + (y3 * Math.cos(θ) + x3 * Math.sin(θ)));}__distance() {const dx = this.points[0][0] - this.pole[0];const dy = this.points[0][1] - this.pole[1];return Math.floor(Math.sqrt(dx * dx + dy * dy));}__lerp(src, dst, coeff) {return src + (dst - src) * coeff;}__update() {const dist = this.__distance();if (dist - this.range > 0.0001)this.__restart();else {this.points.forEach((point, index) => {this.points[index][0] = point[0] + this.speedX;this.points[index][1] = point[1] + this.speedY;});this.opacity = this.__lerp(1, 0, dist / this.range);}}render() {this.__update();this.ctx.lineWidth = 2;this.ctx.lineJoin = "miter";this.ctx.strokeStyle = `rgba(179, 179, 179, ${this.opacity})`;this.ctx.beginPath();this.ctx.moveTo(this.points[0][0], this.points[0][1]);this.ctx.lineTo(this.points[1][0], this.points[1][1]);this.ctx.lineTo(this.points[2][0], this.points[2][1]);this.ctx.closePath();this.ctx.stroke();this.ctx.fillStyle = 'rgba(67, 67, 67, .2)';this.ctx.fill();}
}

定义个“场景”

class Scene {constructor(canvas) {this.cvs = canvas;this.ctx = canvas.getContext('2d');this.triangleSet = [];this.triangleNum = 25; // 三角形个数const realm = this.cvs.width / 2; // 画布中心for (let i = 0; i < this.triangleNum; ++i)this.triangleSet[i] = new Triangle(this.ctx, 1.5, [realm, realm], realm);}render() {this.ctx.clearRect(0, 0, this.cvs.width, this.cvs.height);  // 及时清除画布this.triangleSet.forEach(triangle => triangle.render());}run() {if (!this.timer) {this.timer = setInterval(this.render.bind(this), 25);}}stop() {if (this.timer) {clearInterval(this.timer);this.timer = 0;}}
}

最后“跑场景”

const canvas = document.getElementById('background');
canvas.width = canvas.height = Math.ceil(canvas.parentNode.lastElementChild.offsetWidth * 1.68421);
const scene = new Scene(canvas);
scene.run();

完成,下面是最终效果
源码链接在这:github

在线演示:codepen

codepen上的代码会有些不同,因为不想引用图片,所以用css简单画了一个唱片,效果如下

下篇:【canvas】网易云音乐鲸云动效『孤独星球』的简单实现

【canvas】网易云音乐鲸云动效『水晶音波』的简单实现相关推荐

  1. 网易云音乐动效Android,Web Audio在音频可视化中的应用(网易云音乐鲸云动效)...

    本文有两个关键词:音频可视化和Web Audio.前者是实践,后者是其背后的技术支持. Web Audio 是很大的知识点,本文会将重点放在如何获取音频数据这块,对于其 API 的更多内容,可以查看 ...

  2. 模仿网易云音乐鲸云特效动效

    JinyunEffect 项目地址:tyhjh/JinyunEffect  简介: 模仿网易云音乐鲸云特效动效 更多:作者   提 Bug 标签: # Android 粒子特效--网易云鲸云特效 文 ...

  3. Android 贝塞尔曲线实战之网易云音乐鲸云特效

    作者:哈哈将 -个推 Android 高级开发工程师 前言 APP开发市场已经告别"野蛮生长"时代,人们不再满足于APP外形创新,而将目光转向全方面的用户体验上.在这过程中,动效化 ...

  4. Android 贝塞尔曲线实战之网易云音乐鲸云特效,2021程序员进阶宝典

    一阶这个比较简单,因为没有在网上找到可以直接输入数学公式的工具,就手工推导了下. ![在这里插入图片描述](https://img- <Android学习笔记总结+最新移动架构视频+大厂安卓面试 ...

  5. Android 贝塞尔曲线实战之网易云音乐鲸云特效,apm性能监控系统

    小说阅读 APP 的翻页效果. 简介 ===================================================================== 在开始实战之前,我们还 ...

  6. 仿网易云音乐鲸云音效-孤独星球

    闲来无事,打开网易云音乐,发现播放音乐时有好几款音效,属实夺人眼球,而网易云上的孤独星球音效是要vip权限才能开启的,这就让人不爽了,不想花钱那就手动撸一个出来自己边看边听歌,哇咔咔咔.由于是本人原创 ...

  7. 网易云音乐测试“云随机”播放功能 已注册产品功能相关专利

    近日,网易云音乐"随机播放"功能全面升级为"云随机",该功能已在灰度测试,将于近期全量上线.网易云音乐"云随机"功能,支持用户对随机播放模式 ...

  8. PC端网易云音乐播放云盘音乐时显示加载失败,自动调转下一首的解决方法

    PC端网易云音乐播放云盘音乐时显示加载失败,自动调转下一首解决方法 注意: 一定要看看是不是和你的情况一样,不一样不要用这种方法!!! 具体情况: 我们经常会下载歌曲存到电脑文件夹里,然后通过网易云音 ...

  9. [API ]新浪微博腾讯QQ音乐网易云音乐小米云钉钉笔记百度高德地图淘宝阿里云 API

    常用&免费 微博: 需要先注册登录 https://open.weibo.com/wiki/API bilibili b站(part1@社会易姐QwQ) https://github.com/ ...

最新文章

  1. js提取url参数的几种方法。(搜集)
  2. python3 正则 验证邮箱手机
  3. Python之路(第二篇):Python基本数据类型字符串(一)
  4. 服务器进入bios用u盘启动不了系统,用u盘装系统,进入bios后没有usb启动项怎么办...
  5. SAP License:员工离职分析
  6. 网站html静态化 教程,新云CMS网站内容管理系统生成HTML静态化教程
  7. hive insert into语句 和 insert overwrite语句
  8. [core java学习笔记][第十一章异常断言日志调试]
  9. 中原工学院计算机网络,计算机网络 考试重点 中原工学院.doc
  10. Swift 中函数使用指南
  11. mongoVUE查询
  12. 计算机语言中索引什么意思,index在中是什么意思
  13. 计算机上播放时没声音什么故障,电脑播放视频没有声音是什么原因
  14. 抑郁量表c语言程序,抑郁自评量表(SDS)
  15. Vue:运行项目时报错:Module not found: Error: Can't resolve 'sass-loader' in
  16. 一键导出ChatGPT聊天记录:让备份更简单
  17. SQL注入漏洞测试(参数加密)
  18. Jetson Nano B01 无界面初始化安装系统+飞桨(Paddle)v2.0
  19. 北京高校大学期末试题试卷题库
  20. 加密算法的重要性以及了解加密算法分类

热门文章

  1. php购物车数据表,PHP开发简单购物车功能创建数据库表
  2. Dubbo 与 Feign 的区别
  3. 2021-08-05 Hello,word! Day 02
  4. 选择软件测试你后悔吗?
  5. 康佳电视KKTV无法开机刷机方法
  6. 【Kubernetes】 DaemonSet 详解
  7. Android Studio升级后,新建Activity始终报错,创建不了
  8. 新春特辑 | 数字经济专题合辑 报告下载
  9. 澳门移植“城市大脑”,阿里云提供全套AI解决方案
  10. SSM茶叶销售管理系统