
4

#盲盒+码# 【FFH】一颗会呼吸的心-开源基础软件社区-51CTO.COM
source link: https://ost.51cto.com/posts/20223
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

#盲盒+码# 【FFH】一颗会呼吸的心 原创 精华
今天来复刻一个会呼吸的心,在前些阵子电视剧《燃烧我,温暖你》中一颗会呼吸的心引起了众多开发者的复刻…
原剧中
复刻效果
1.逆向工程
分析原剧要素,首先是一个爱心的轮廓,爱心内外有许多随机分布的点,且心的内部扩张程度要大于外侧扩张程度,所以才有呼吸的效果。但显然原剧中的爱心应该不是单单依靠代码实现。
我们完成一下要素即可:
- 最外层的爱心轮廓
- 轮廓周围随机分布的点
- 内层跳动大于外层
要想内外扩张程度不一样的话,我们可能需要用到两个画布实例,为他们添加动画,并且内部扩大程度大于外侧画布。
2.代码实现
- javascript
export default {
data: {
title: ""
},
onInit() {
this.title = this.$t('strings.world');
},
onShow(){
this.heart();
this.heart2();
},
heart(){
const cvs = this.$refs.canvas;
const ctx = cvs.getContext('2d');
const width=1080;
const height=1080;
//计算弧度
let radian = 0
let radian_add = Math.PI / 180
//调整位置
ctx.translate(width / 3, height / 2)
//阴影
ctx.shadowBlur = 10
//拐弯角圆滑
ctx.lineJoin = 'round'
//颜色
ctx.shadowColor = 'rgba(255, 255, 255, 1.00)'
ctx.strokeStyle = 'rgba(255, 0, 114, 1.00)'
//两个点矩阵,都是用来画爱心,一个大一点一个小一点增加层次
const points = []
const mpoints=[]
while (radian <= Math.PI * 2) {
radian += radian_add
//(x,y)表示爱心坐标,16的爱心大一点
let x = this.getX(radian,16)
let y = this.getY(radian,16)
points.push({
x,
y,
//随机分布
list: new Array(10).fill('').map(v => {
const fw = 100
const fx = x + Math.random() * fw - fw / 2
const fy = y + Math.random() * fw - fw / 2
return {
x: x,
y: y,
endX: fx,
endY: fy,
stepX: x > fx ? -1 : 1,
stepY: y > fy ? -1 : 1,
parentX: x,
parentY: y
}
})
})
//再存一个小一点的爱心
x = this.getX(radian,14)
y = this.getY(radian,14)
// ctx.lineTo(x, y)
mpoints.push({
x,
y,
list: new Array(10).fill('').map(v => {
const fw = 100
const fx = x + Math.random() * fw - fw / 2
const fy = y + Math.random() * fw - fw / 2
return {
x: x,
y: y,
endX: fx,
endY: fy,
stepX: x > fx ? -1 : 1,
stepY: y > fy ? -1 : 1,
parentX: x,
parentY: y
}
})
})
}
const render = () => {
ctx.beginPath()
ctx.clearRect(-width/2, -height/2, width, height)
//设置粗细
ctx.lineWidth = 1
//绘制
mpoints.forEach(v => {
v.list.forEach(k => {
ctx.moveTo(k.x, k.y)
ctx.lineTo(k.x + ctx.lineWidth, k.y + ctx.lineWidth)
k.x += k.stepX
k.y += k.stepY
if (k.stepX > 0) {
if (k.x > k.endX) {
k.x = k.endX
}
} else {
if (k.x < k.endX) {
k.x = k.endX
}
}
if (k.stepY > 0) {
if (k.y > k.endY) {
k.y = k.endY
}
} else {
if (k.y < k.endY) {
k.y = k.endY
}
}
if (k.x === k.endX && k.y === k.endY) {
k.x = k.parentX
k.y = k.parentY
}
})
})
ctx.stroke()
ctx.beginPath()
ctx.lineWidth = 2
//绘制
points.forEach(v => {
v.list.forEach(k => {
ctx.moveTo(k.x, k.y)
ctx.lineTo(k.x + ctx.lineWidth, k.y + ctx.lineWidth)
k.x += k.stepX
k.y += k.stepY
if (k.stepX > 0) {
if (k.x > k.endX) {
k.x = k.endX
}
} else {
if (k.x < k.endX) {
k.x = k.endX
}
}
if (k.stepY > 0) {
if (k.y > k.endY) {
k.y = k.endY
}
} else {
if (k.y < k.endY) {
k.y = k.endY
}
}
if (k.x === k.endX && k.y === k.endY) {
k.x = k.parentX
k.y = k.parentY
}
})
})
ctx.stroke()
ctx.lineWidth = 2
points.forEach(k => {
v=>{
ctx.lineTo(v.x,v.y)
}
})
ctx.stroke()
requestAnimationFrame(render)}
render()
},
//依据爱心方程绘制
getX(t,w) {
return w * (12 * Math.sin(t) - 4 * Math.sin(3 * t))
},
getY(t, w,bl = 1) {
return (
-w *
(13 * Math.cos(t) -
5 * Math.cos(2 * t) -
2 * Math.cos(3 * t) -
Math.cos(4 * t))
)
},
heart2(){
//代码类似,但是是基于第二个画布,爱心更小一点,为了制作出呼吸的效果
}
}
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background-color: black;
}
.my_canvas{
animation: run infinite 1s linear;
width: 100%;
height: 100%;
background-color: black;
}
.my_canvs2{
position: absolute;
width: 100%;
height: 100%;
z-index: 10;
animation: run2 infinite 1s linear;
}
@keyframes run {
0% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
100% {
transform: scale(1);
}
}
@keyframes run2 {
0% {
transform: scale(1);
}
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
<div class="container">
<canvas class="my_canvas" ref="canvas">
</canvas>
<canvas class="my_canvs2" ref="canvas2">
</canvas>
</div>
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
Heart.zip 3.75M 2次下载
</div
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK