【canvas】网易云音乐鲸云动效『水晶音波』的简单实现
最近闲来无事,打开网易云音乐,发现还有鲸云音效这种东西,嗯?『水晶音波』,挺炫。嗯?黑胶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】网易云音乐鲸云动效『水晶音波』的简单实现相关推荐
- 网易云音乐动效Android,Web Audio在音频可视化中的应用(网易云音乐鲸云动效)...
本文有两个关键词:音频可视化和Web Audio.前者是实践,后者是其背后的技术支持. Web Audio 是很大的知识点,本文会将重点放在如何获取音频数据这块,对于其 API 的更多内容,可以查看 ...
- 模仿网易云音乐鲸云特效动效
JinyunEffect 项目地址:tyhjh/JinyunEffect 简介: 模仿网易云音乐鲸云特效动效 更多:作者 提 Bug 标签: # Android 粒子特效--网易云鲸云特效 文 ...
- Android 贝塞尔曲线实战之网易云音乐鲸云特效
作者:哈哈将 -个推 Android 高级开发工程师 前言 APP开发市场已经告别"野蛮生长"时代,人们不再满足于APP外形创新,而将目光转向全方面的用户体验上.在这过程中,动效化 ...
- Android 贝塞尔曲线实战之网易云音乐鲸云特效,2021程序员进阶宝典
一阶这个比较简单,因为没有在网上找到可以直接输入数学公式的工具,就手工推导了下. ![在这里插入图片描述](https://img- <Android学习笔记总结+最新移动架构视频+大厂安卓面试 ...
- Android 贝塞尔曲线实战之网易云音乐鲸云特效,apm性能监控系统
小说阅读 APP 的翻页效果. 简介 ===================================================================== 在开始实战之前,我们还 ...
- 仿网易云音乐鲸云音效-孤独星球
闲来无事,打开网易云音乐,发现播放音乐时有好几款音效,属实夺人眼球,而网易云上的孤独星球音效是要vip权限才能开启的,这就让人不爽了,不想花钱那就手动撸一个出来自己边看边听歌,哇咔咔咔.由于是本人原创 ...
- 网易云音乐测试“云随机”播放功能 已注册产品功能相关专利
近日,网易云音乐"随机播放"功能全面升级为"云随机",该功能已在灰度测试,将于近期全量上线.网易云音乐"云随机"功能,支持用户对随机播放模式 ...
- PC端网易云音乐播放云盘音乐时显示加载失败,自动调转下一首的解决方法
PC端网易云音乐播放云盘音乐时显示加载失败,自动调转下一首解决方法 注意: 一定要看看是不是和你的情况一样,不一样不要用这种方法!!! 具体情况: 我们经常会下载歌曲存到电脑文件夹里,然后通过网易云音 ...
- [API ]新浪微博腾讯QQ音乐网易云音乐小米云钉钉笔记百度高德地图淘宝阿里云 API
常用&免费 微博: 需要先注册登录 https://open.weibo.com/wiki/API bilibili b站(part1@社会易姐QwQ) https://github.com/ ...
最新文章
- js提取url参数的几种方法。(搜集)
- python3 正则 验证邮箱手机
- Python之路(第二篇):Python基本数据类型字符串(一)
- 服务器进入bios用u盘启动不了系统,用u盘装系统,进入bios后没有usb启动项怎么办...
- SAP License:员工离职分析
- 网站html静态化 教程,新云CMS网站内容管理系统生成HTML静态化教程
- hive insert into语句 和 insert overwrite语句
- [core java学习笔记][第十一章异常断言日志调试]
- 中原工学院计算机网络,计算机网络 考试重点 中原工学院.doc
- Swift 中函数使用指南
- mongoVUE查询
- 计算机语言中索引什么意思,index在中是什么意思
- 计算机上播放时没声音什么故障,电脑播放视频没有声音是什么原因
- 抑郁量表c语言程序,抑郁自评量表(SDS)
- Vue:运行项目时报错:Module not found: Error: Can't resolve 'sass-loader' in
- 一键导出ChatGPT聊天记录:让备份更简单
- SQL注入漏洞测试(参数加密)
- Jetson Nano B01 无界面初始化安装系统+飞桨(Paddle)v2.0
- 北京高校大学期末试题试卷题库
- 加密算法的重要性以及了解加密算法分类