文章目录
一、演示(python版)
代码
# 在等一句我愿意import random
from math import sin, cos, pi, log
from tkinter import*
CANVAS_WIDTH =640
CANVAS_HEIGHT =480
CANVAS_CENTER_X = CANVAS_WIDTH /2
CANVAS_CENTER_Y = CANVAS_HEIGHT /2
IMAGE_ENLARGE =11
HEART_COLOR ="#ff9999"# 心的颜色defheart_function(t, shrink_ratio:float= IMAGE_ENLARGE):# 基础函数
x =16*(sin(t)**3)
y =-(13* cos(t)-5* cos(2* t)-2* cos(3* t)- cos(4* t))# 放大
x *= shrink_ratio
y *= shrink_ratio
# 移到画布中央
x += CANVAS_CENTER_X
y += CANVAS_CENTER_Y
returnint(x),int(y)defscatter_inside(x, y, beta=0.15):
ratio_x =- beta * log(random.random())
ratio_y =- beta * log(random.random())
dx = ratio_x *(x - CANVAS_CENTER_X)
dy = ratio_y *(y - CANVAS_CENTER_Y)return x - dx, y - dy
defshrink(x, y, ratio):
force =-1/(((x - CANVAS_CENTER_X)**2+(y - CANVAS_CENTER_Y)**2)**0.6)
dx = ratio * force *(x - CANVAS_CENTER_X)
dy = ratio * force *(y - CANVAS_CENTER_Y)return x - dx, y - dy
defcurve(p):# 可以尝试换其他的动态函数,达到更有力量的效果return2*(2* sin(4* p))/(2* pi)classHeart:def__init__(self, generate_frame=20):
self._points =set()# 原始爱心坐标集合
self._edge_diffusion_points =set()# 边缘扩散效果点坐标集合
self._center_diffusion_points =set()# 中心扩散效果点坐标集合
self.all_points ={}# 每帧动态点坐标
self.build(2000)
self.random_halo =1000
self.generate_frame = generate_frame
for frame inrange(generate_frame):
self.calc(frame)defbuild(self, number):# 爱心for _ inrange(number):
t = random.uniform(0,2* pi)
x, y = heart_function(t)
self._points.add((x, y))# 爱心内扩散for _x, _y inlist(self._points):for _ inrange(3):
x, y = scatter_inside(_x, _y,0.1)
self._edge_diffusion_points.add((x, y))# 爱心内再次扩散
point_list =list(self._points)for _ inrange(4000):
x, y = random.choice(point_list)
x, y = scatter_inside(x, y,0.2)
self._center_diffusion_points.add((x, y))@staticmethoddefcalc_position(x, y, ratio):# 调整缩放比例
force =1/(((x - CANVAS_CENTER_X)**2+(y - CANVAS_CENTER_Y)**2)**0.520)# 好玩点
dx = ratio * force *(x - CANVAS_CENTER_X)+ random.randint(-1,1)
dy = ratio * force *(y - CANVAS_CENTER_Y)+ random.randint(-1,1)return x - dx, y - dy
defcalc(self, generate_frame):
ratio =10* curve(generate_frame /10* pi)
halo_radius =int(4+6*(1+ curve(generate_frame /10* pi)))
halo_number =int(3000+4000*abs(curve(generate_frame /10* pi)**2))
all_points =[]# 光环
heart_halo_point =set()# 光环的点坐标集合for _ inrange(halo_number):
t = random.uniform(0,2* pi)# 随机不到的地方造成爱心有缺口
x, y = heart_function(t, shrink_ratio=12)# 好玩点
x, y = shrink(x, y, halo_radius)if(x, y)notin heart_halo_point:# 处理新的点
heart_halo_point.add((x, y))
x += random.randint(-14,14)
y += random.randint(-14,14)
size = random.choice((1,2,2))
all_points.append((x, y, size))# 轮廓for x, y in self._points:
x, y = self.calc_position(x, y, ratio)
size = random.randint(1,3)
all_points.append((x, y, size))# 内容for x, y in self._edge_diffusion_points:
x, y = self.calc_position(x, y, ratio)
size = random.randint(1,2)
all_points.append((x, y, size))for x, y in self._center_diffusion_points:
x, y = self.calc_position(x, y, ratio)
size = random.randint(1,2)
all_points.append((x, y, size))
self.all_points[generate_frame]= all_points
defrender(self, render_canvas, render_frame):for x, y, size in self.all_points[render_frame % self.generate_frame]:
render_canvas.create_rectangle(
x, y, x + size, y + size, width=0, fill=HEART_COLOR)defdraw(main: Tk, render_canvas: Canvas, render_heart: Heart, render_frame=0):
render_canvas.delete('all')
render_heart.render(render_canvas, render_frame)
main.after(160, draw, main, render_canvas, render_heart, render_frame +1)if __name__ =='__main__':
root = Tk()
canvas = Canvas(root, bg='black', height=CANVAS_HEIGHT, width=CANVAS_WIDTH)
canvas.pack()
heart = Heart()
draw(root, canvas, heart)
root.mainloop()
二、演示(html版)
代码
<!DOCTYPEhtml><html><head><title></title></head><style>*{padding: 0;margin: 0;}html,
body{height: 100%;padding: 0;margin: 0;background:rgb(2, 2, 2);}canvas{position: absolute;width: 100%;height: 100%;}.aa{position: fixed;left: 50%;bottom: 10px;color:rgb(9, 194, 113)}</style><body><canvasid="pinkboard"></canvas><script>/*
* Settings
*/var settings ={particles:{length:1000,// 最大颗粒量duration:3,// 粒子持续时间(秒)velocity:100,// 粒子速度(像素/秒)effect:-0.75,// 玩这个效果很好size:20,// 颗粒大小(像素)},};(function(){var b =0;var c =["ms","moz","webkit","o"];for(var a =0; a < c.length &&!window.requestAnimationFrame;++a){ window.requestAnimationFrame = window[c[a]+"RequestAnimationFrame"]; window.cancelAnimationFrame = window[c[a]+"CancelAnimationFrame"]|| window[c[a]+"CancelRequestAnimationFrame"]}if(!window.requestAnimationFrame){ window.requestAnimationFrame=function(h, e){var d =newDate().getTime();var f = Math.max(0,16-(d - b));var g = window.setTimeout(function(){h(d + f)}, f); b = d + f;return g }}if(!window.cancelAnimationFrame){ window.cancelAnimationFrame=function(d){clearTimeout(d)}}}());/*
* Point class
*/var Point =(function(){functionPoint(x, y){this.x =(typeof x !=='undefined')? x :0;this.y =(typeof y !=='undefined')? y :0;}Point.prototype.clone=function(){returnnewPoint(this.x,this.y);};Point.prototype.length=function(length){if(typeof length =='undefined')return Math.sqrt(this.x *this.x +this.y *this.y);this.normalize();this.x *= length;this.y *= length;returnthis;};Point.prototype.normalize=function(){var length =this.length();this.x /= length;this.y /= length;returnthis;};return Point;})();/*
* Particle class
*/var Particle =(function(){functionParticle(){this.position =newPoint();this.velocity =newPoint();this.acceleration =newPoint();this.age =0;}Particle.prototype.initialize=function(x, y, dx, dy){this.position.x = x;this.position.y = y;this.velocity.x = dx;this.velocity.y = dy;this.acceleration.x = dx * settings.particles.effect;this.acceleration.y = dy * settings.particles.effect;this.age =0;};Particle.prototype.update=function(deltaTime){this.position.x +=this.velocity.x * deltaTime;this.position.y +=this.velocity.y * deltaTime;this.velocity.x +=this.acceleration.x * deltaTime;this.velocity.y +=this.acceleration.y * deltaTime;this.age += deltaTime;};Particle.prototype.draw=function(context, image){functionease(t){return(--t)* t * t +1;}var size = image.width *ease(this.age / settings.particles.duration);
context.globalAlpha =1-this.age / settings.particles.duration;
context.drawImage(image,this.position.x - size /2,this.position.y - size /2, size, size);};return Particle;})();/*
* ParticlePool class
*/var ParticlePool =(function(){var particles,
firstActive =0,
firstFree =0,
duration = settings.particles.duration;functionParticlePool(length){// 创建和填充粒子池
particles =newArray(length);for(var i =0; i < particles.length; i++)
particles[i]=newParticle();}ParticlePool.prototype.add=function(x, y, dx, dy){
particles[firstFree].initialize(x, y, dx, dy);//处理循环队列
firstFree++;if(firstFree == particles.length) firstFree =0;if(firstActive == firstFree) firstActive++;if(firstActive == particles.length) firstActive =0;};ParticlePool.prototype.update=function(deltaTime){var i;// 处理循环队列if(firstActive < firstFree){for(i = firstActive; i < firstFree; i++)
particles[i].update(deltaTime);}if(firstFree < firstActive){for(i = firstActive; i < particles.length; i++)
particles[i].update(deltaTime);for(i =0; i < firstFree; i++)
particles[i].update(deltaTime);}//移除非活性粒子while(particles[firstActive].age >= duration && firstActive != firstFree){
firstActive++;if(firstActive == particles.length) firstActive =0;}};ParticlePool.prototype.draw=function(context, image){//绘制活性粒子if(firstActive < firstFree){for(i = firstActive; i < firstFree; i++)
particles[i].draw(context, image);}if(firstFree < firstActive){for(i = firstActive; i < particles.length; i++)
particles[i].draw(context, image);for(i =0; i < firstFree; i++)
particles[i].draw(context, image);}};return ParticlePool;})();/*
* 把所有这些放在一起
*/(function(canvas){var context = canvas.getContext('2d'),
particles =newParticlePool(settings.particles.length),
particleRate = settings.particles.length / settings.particles.duration,//粒子/秒
time;// get point on heart with -PI <= t <= PIfunctionpointOnHeart(t){returnnewPoint(160* Math.pow(Math.sin(t),3),130* Math.cos(t)-50* Math.cos(2* t)-20* Math.cos(3* t)-10* Math.cos(4* t)+25);}//使用虚拟画布创建粒子图像var image =(function(){var canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
canvas.width = settings.particles.size;
canvas.height = settings.particles.size;//helper函数创建路径functionto(t){var point =pointOnHeart(t);
point.x = settings.particles.size /2+ point.x * settings.particles.size /350;
point.y = settings.particles.size /2- point.y * settings.particles.size /350;return point;}//创建路径
context.beginPath();var t =-Math.PI;var point =to(t);
context.moveTo(point.x, point.y);while(t < Math.PI){
t +=0.01;// baby steps!
point =to(t);
context.lineTo(point.x, point.y);}
context.closePath();//创建填充
context.fillStyle ='#ff9999';
context.fill();//创建图像var image =newImage();
image.src = canvas.toDataURL();return image;})();//渲染那个东西!functionrender(){//下一动画帧requestAnimationFrame(render);//更新时间var newTime =newDate().getTime()/1000,
deltaTime = newTime -(time || newTime);
time = newTime;//透明帆布
context.clearRect(0,0, canvas.width, canvas.height);//创建新粒子var amount = particleRate * deltaTime;for(var i =0; i < amount; i++){var pos =pointOnHeart(Math.PI-2* Math.PI* Math.random());var dir = pos.clone().length(settings.particles.velocity);
particles.add(canvas.width /2+ pos.x, canvas.height /2- pos.y, dir.x,-dir.y);}//更新和绘制粒子
particles.update(deltaTime);
particles.draw(context, image);}//处理画布的大小functiononResize(){
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;}
window.onresize = onResize;//延迟渲染引导setTimeout(function(){onResize();render();},10);})(document.getElementById('pinkboard'));</script></body></html>
本文转载自: https://blog.csdn.net/qq_52108058/article/details/127767880
版权归原作者 微笑伴你而行 所有, 如有侵权,请联系我们删除。
版权归原作者 微笑伴你而行 所有, 如有侵权,请联系我们删除。