众所周知,前不久刚热播的《打火机与公主裙》中出现了编程中的一幕:一颗跳动的爱心,所以作为一个整活up主,当然少不了要来横插一脚,所以今天就带大家复刻一下电视剧中的爱心桥段,那么为了拥有如此装逼的技术,up主都用了哪些手段呢?
手段1:c++语言的基础,我们先来看看最简单的C语言运行出来的字符型静态爱心是怎么来的,话不多说,直接上代码链接:
#include <stdio.h>
int main()
{
float a,x,y;
for(y = -1.5f; y < 1.5f; y += 0.1f)
{
for(x = 1.5f; x > -1.5f; x -= 0.05f)
{
a = x * x + y * y - 1;
char ch = a * a *a - x * x *y * y * y <= 0.0f ? '*' : ' ';
putchar(ch);
}
printf("\n");
}
return 0;
}
其实呢逻辑也没有那么复杂,就是在一个圆中抠出来一个爱心的形状就完了,就如电视剧中男主说的,高数不挂都能看懂。
那么第二种就开始有点挑战性了,一开始up主呢是想像电视剧一样通过C语言纯代码来实习,奈何实在是C语言功力不到位,于是转战到了自己擅长的网站开发领域,使用了html5的canvas来绘制出了一个爱心,网络上的代码呢终究是殊途同归,那么下面我们就来介绍一下canvas这门技术到底是什么?
HTML5 Canvas | 菜鸟教程
总的来说,canvas就是通过JavaScript在画布上面绘制一系列图片的工具,具体的方法可以参考菜鸟教程上的详细方法,下面为大家分享一下我的源码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>整活大队</title>
<link rel="shortcut icon" href="../../assets/images/icon/favicon.ico" type="image/x-icon">
<style>
html,
body {
height: 100%;
padding: 0;
margin: 0;
background-image: url("https://gimg2.baidu.com/image_search/src=http://picnew10.photophoto.cn/20160706/xuanlixingkongbeijing-23193270_1.jpg&refer=http://picnew10.photophoto.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1670479907&t=0c2d3f69b945926f461d3f02912e17f3");
width: 100%;
height: 100%;
}
canvas {
position: absolute;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<canvas id="pink">
Canvas Not Support
</canvas>
<script>
/*
* Settings
*/
let settings = {
particles: {
length: 500,
duration: 2,
velocity: 100,
effect: -0.75,
size: 30,
},
};
(function () {
let b = 0; let c = ["ms", "moz", "webkit", "o"];
for (let 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) { let d = new Date().getTime(); let f = Math.max(0, 16 - (d - b)); let g = window.setTimeout(function () { h(d + f) }, f); b = d + f; return g } }
if (!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function (d) {
clearTimeout(d)
}
}
}()
);
/*
* Point class
*/
let Point = (function () {
function Point(x, y) {
this.x = (typeof x !== 'undefined') ? x : 0;
this.y = (typeof y !== 'undefined') ? y : 0;
}
Point.prototype.clone = function () {
return new Point(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;
return this;
};
Point.prototype.normalize = function () {
let length = this.length();
this.x /= length;
this.y /= length;
return this;
};
return Point;
})();
let Particle = (function () {
function Particle() {
this.position = new Point();
this.velocity = new Point();
this.acceleration = new Point();
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) {
function ease(t) {
return (--t) * t * t + 1;
}
let 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;
})();
let ParticlePool = (function () {
let particles,
firstActive = 0,
firstFree = 0,
duration = settings.particles.duration;
function ParticlePool(length) {
particles = new Array(length);
for (let i = 0; i < particles.length; i++)
particles[i] = new Particle();
}
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) {
let 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) {
let context = canvas.getContext('2d'),
particles = new ParticlePool(settings.particles.length),
particleRate = settings.particles.length / settings.particles.duration, // particles/sec
time;
function pointOnHeart(t) {
return new Point(
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
);
}
let image = (function () {
let canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
canvas.width = settings.particles.size;
canvas.height = settings.particles.size;
function to(t) {
let 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();
let t = -Math.PI;
let point = to(t);
context.moveTo(point.x, point.y);
while (t < Math.PI) {
t += 0.01;
point = to(t);
context.lineTo(point.x, point.y);
}
context.closePath();
context.fillStyle = '#ea80b0';
context.fill();
let image = new Image();
image.src = canvas.toDataURL();
return image;
})();
function render() {
requestAnimationFrame(render);
let newTime = new Date().getTime() / 1000,
deltaTime = newTime - (time || newTime);
time = newTime;
context.clearRect(0, 0, canvas.width, canvas.height);
let amount = particleRate * deltaTime;
for (let i = 0; i < amount; i++) {
let pos = pointOnHeart(Math.PI - 2 * Math.PI * Math.random());
let 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);
}
function onResize() {
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
}
window.onresize = onResize;
setTimeout(function () {
onResize();
render();
}, 10);
})(document.getElementById('pink'));
</script>
</body>
</html>