人們總說(shuō)理工科男生不懂浪漫,不懂得講情話(huà)。在這里 W3Cschool 小編覺(jué)得很有必要為他們正名一下。誰(shuí)說(shuō)我們不懂浪漫,只是你們不懂我們的浪漫。前有偉大的數(shù)學(xué)家笛卡爾寫(xiě)出告白公式,后又有程序員小哥哥開(kāi)發(fā)陪聊系統(tǒng),全天 24 小時(shí)推送問(wèn)候,自動(dòng)回復(fù)女友的微信消息。你看,理工科男生浪漫起來(lái)誰(shuí)能抵擋呢?
笛卡爾的心形公式
那么今天,我們用 HTML+CSS+JavaScript 編寫(xiě)一個(gè)告白神器,女朋友一看,都感動(dòng)到哭呢!
先來(lái)看下運(yùn)行最終結(jié)果!??!在線(xiàn)演示地址:http://www.zuidaima.com/html/1695882735602688/index.html
HTML源碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>W3Cschool-編程獅</title>
<style type="text/css">
@font-face {
font-family: digit;
src: url('digital-7_mono.ttf') format("truetype");
}
</style>
<link href="css/default.css" type="text/css" rel="stylesheet">
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/garden.js"></script>
<script type="text/javascript" src="js/functions.js"></script>
</head>
<body>
<div id="mainDiv">
<div id="content">
<div id="code">
<span class="comments">/**</span><br />
<span class="space"/><span class="comments">*2020—02-19,</span><br />
<span class="space"/><span class="comments">*2021_03_09.</span><br />
<span class="space"/><span class="comments">*/</span><br />
Boy name = <span class="keyword">Mr</span> Leo<br />
Girl name = <span class="keyword">Mrs</span> Jenny<br />
<span class="comments">// Fall in love river. </span><br />
The boy love the girl;<br />
<span class="comments">// They love each other.</span><br />
The girl loved the boy;<br />
<span class="comments">// AS time goes on.</span><br />
The boy can not be separated the girl;<br />
<span class="comments">// At the same time.</span><br />
The girl can not be separated the boy;<br />
<span class="comments">// Both wind and snow all over the sky.</span><br />
<span class="comments">// Whether on foot or 5 kilometers.</span><br />
<span class="keyword">The boy</span> very <span class="keyword">happy</span>;<br />
<span class="keyword">The girl</span> is also very <span class="keyword">happy</span>;<br />
<span class="placeholder"/><span class="comments">// Whether it is right now</span><br />
<span class="placeholder"/><span class="comments">// Still in the distant future.</span><br />
<span class="placeholder"/>The boy has but one dream;<br />
<span class="comments">// The boy wants the girl could well have been happy.</span><br />
<br>
<br>
I want to say:<br />
Baby, I would love you forever;<br />
</div>
<div id="loveHeart">
<canvas id="garden"></canvas>
<div id="words">
<div id="messages">
親愛(ài)的,這是我們?cè)谝黄鹱哌^(guò)的時(shí)光。
<div id="elapseClock"></div>
</div>
<div id="loveu">
Love you forever!!!<br/>
<div class="signature">- Loving</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var offsetX = $("#loveHeart").width() / 2;
var offsetY = $("#loveHeart").height() / 2 - 55;
var together = new Date();
together.setFullYear(2020, 01, 19);//月份一欄的數(shù)據(jù)填入是0-11,即01為2月份。
together.setHours(0);
together.setMinutes(0);
together.setSeconds(0);
together.setMilliseconds(0);
if (!document.createElement('canvas').getContext) {
var msg = document.createElement("div");
msg.id = "errorMsg";
msg.innerHTML = "Your browser doesn't support HTML5!<br/>Recommend use Chrome 14+/IE 9+/Firefox 7+/Safari 4+";
document.body.appendChild(msg);
$("#code").css("display", "none")
$("#copyright").css("position", "absolute");
$("#copyright").css("bottom", "10px");
document.execCommand("stop");
} else {
setTimeout(function () {
startHeartAnimation();
}, 3000);
timeElapse(together);
setInterval(function () {
timeElapse(together);//elapse:計(jì)算時(shí)間差函數(shù);
}, 500);
adjustCodePosition();
$("#code").typewriter();
}
</script>
</body>
</html>
css源碼:
body{margin:0;padding:0;background:#ffe;font-size:12px;overflow:auto}
#mainDiv{width:100%;height:100%}
#loveHeart{float:left;width:670px;height:625px}
#garden{width:100%;height:100%}
#elapseClock{text-align:right;font-size:18px;margin-top:10px;margin-bottom:10px}
#words{font-family:"sans-serif";width:500px;font-size:24px;color:#666}
#messages{display:none}
#elapseClock .digit{font-family:"digit";font-size:36px}
#loveu{padding:5px;font-size:22px;margin-top:80px;margin-right:120px;text-align:right;display:none}
#loveu .signature{margin-top:10px;font-size:20px;font-style:italic}
#clickSound{display:none}
#code{float:left;width:440px;height:400px;color:#333;font-family:"Consolas","Monaco","Bitstream Vera Sans Mono","Courier New","sans-serif";font-size:12px}
#code .string{color:#2a36ff}
#code .keyword{color:#7f0055;font-weight:bold}
#code .placeholder{margin-left:15px}#code .space{margin-left:7px}
#code .comments{color:#3f7f5f}
#copyright{margin-top:10px;text-align:center;width:100%;color:#666}
#errorMsg{width:100%;text-align:center;font-size:24px;position:absolute;top:100px;left:0}
#copyright a{color:#666}
JavaScript源碼:
//function.js
var $window = $(window), gardenCtx, gardenCanvas, $garden, garden;
var clientWidth = $(window).width();
var clientHeight = $(window).height();
$(function () {
// setup garden
$loveHeart = $("#loveHeart");
var offsetX = $loveHeart.width() / 2;
var offsetY = $loveHeart.height() / 2 - 55;
$garden = $("#garden");
gardenCanvas = $garden[0];
gardenCanvas.width = $("#loveHeart").width();
gardenCanvas.height = $("#loveHeart").height()
gardenCtx = gardenCanvas.getContext("2d");
gardenCtx.globalCompositeOperation = "lighter";
garden = new Garden(gardenCtx, gardenCanvas);
$("#content").css("width", $loveHeart.width() + $("#code").width());
$("#content").css("height", Math.max($loveHeart.height(), $("#code").height()));
$("#content").css("margin-top", Math.max(($window.height() - $("#content").height()) / 2, 10));
$("#content").css("margin-left", Math.max(($window.width() - $("#content").width()) / 2, 10));
// renderLoop
setInterval(function () {
garden.render();
}, Garden.options.growSpeed);
});
$(window).resize(function() {
var newWidth = $(window).width();
var newHeight = $(window).height();
if (newWidth != clientWidth && newHeight != clientHeight) {
location.replace(location);
}
});
function getHeartPoint(angle) {
var t = angle / Math.PI;
var x = 19.5 * (16 * Math.pow(Math.sin(t), 3));
var y = - 20 * (13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t));
return new Array(offsetX + x, offsetY + y);
}
function startHeartAnimation() {
var interval = 50;
var angle = 10;
var heart = new Array();
var animationTimer = setInterval(function () {
var bloom = getHeartPoint(angle);
var draw = true;
for (var i = 0; i < heart.length; i++) {
var p = heart[i];
var distance = Math.sqrt(Math.pow(p[0] - bloom[0], 2) + Math.pow(p[1] - bloom[1], 2));
if (distance < Garden.options.bloomRadius.max * 1.3) {
draw = false;
break;
}
}
if (draw) {
heart.push(bloom);
garden.createRandomBloom(bloom[0], bloom[1]);
}
if (angle >= 30) {
clearInterval(animationTimer);
showMessages();
} else {
angle += 0.2;
}
}, interval);
}
(function($) {
$.fn.typewriter = function() {
this.each(function() {
var $ele = $(this), str = $ele.html(), progress = 0;
$ele.html('');
var timer = setInterval(function() {
var current = str.substr(progress, 1);
if (current == '<') {
progress = str.indexOf('>', progress) + 1;
} else {
progress++;
}
$ele.html(str.substring(0, progress) + (progress & 1 ? '_' : ''));
if (progress >= str.length) {
clearInterval(timer);
}
}, 75);
});
return this;
};
})(jQuery);
function timeElapse(date){
var current = Date();
var seconds = (Date.parse(current) - Date.parse(date)) / 1000;
var days = Math.floor(seconds / (3600 * 24));
seconds = seconds % (3600 * 24);
var hours = Math.floor(seconds / 3600);
if (hours < 10) {
hours = "0" + hours;
}
seconds = seconds % 3600;
var minutes = Math.floor(seconds / 60);
if (minutes < 10) {
minutes = "0" + minutes;
}
seconds = seconds % 60;
if (seconds < 10) {
seconds = "0" + seconds;
}
var result = "<span class=\"digit\">" + days + "</span> days <span class=\"digit\">" + hours + "</span> hours <span class=\"digit\">" + minutes + "</span> minutes <span class=\"digit\">" + seconds + "</span> seconds";
$("#elapseClock").html(result);
}
function showMessages() {
adjustWordsPosition();
$('#messages').fadeIn(5000, function() {
showLoveU();
});
}
function adjustWordsPosition() {
$('#words').css("position", "absolute");
$('#words').css("top", $("#garden").position().top + 195);
$('#words').css("left", $("#garden").position().left + 70);
}
function adjustCodePosition() {
$('#code').css("margin-top", ($("#garden").height() - $("#code").height()) / 2);
}
function showLoveU() {
$('#loveu').fadeIn(3000);
}
//garden.js
function Vector(x, y) {
this.x = x;
this.y = y;
};
Vector.prototype = {
rotate: function (theta) {
var x = this.x;
var y = this.y;
this.x = Math.cos(theta) * x - Math.sin(theta) * y;
this.y = Math.sin(theta) * x + Math.cos(theta) * y;
return this;
},
mult: function (f) {
this.x *= f;
this.y *= f;
return this;
},
clone: function () {
return new Vector(this.x, this.y);
},
length: function () {
return Math.sqrt(this.x * this.x + this.y * this.y);
},
subtract: function (v) {
this.x -= v.x;
this.y -= v.y;
return this;
},
set: function (x, y) {
this.x = x;
this.y = y;
return this;
}
};
function Petal(stretchA, stretchB, startAngle, angle, growFactor, bloom) {
this.stretchA = stretchA;
this.stretchB = stretchB;
this.startAngle = startAngle;
this.angle = angle;
this.bloom = bloom;
this.growFactor = growFactor;
this.r = 1;
this.isfinished = false;
//this.tanAngleA = Garden.random(-Garden.degrad(Garden.options.tanAngle), Garden.degrad(Garden.options.tanAngle));
//this.tanAngleB = Garden.random(-Garden.degrad(Garden.options.tanAngle), Garden.degrad(Garden.options.tanAngle));
}
Petal.prototype = {
draw: function () {
var ctx = this.bloom.garden.ctx;
var v1, v2, v3, v4;
v1 = new Vector(0, this.r).rotate(Garden.degrad(this.startAngle));
v2 = v1.clone().rotate(Garden.degrad(this.angle));
v3 = v1.clone().mult(this.stretchA); //.rotate(this.tanAngleA);
v4 = v2.clone().mult(this.stretchB); //.rotate(this.tanAngleB);
ctx.strokeStyle = this.bloom.c;
ctx.beginPath();
ctx.moveTo(v1.x, v1.y);
ctx.bezierCurveTo(v3.x, v3.y, v4.x, v4.y, v2.x, v2.y);
ctx.stroke();
},
render: function () {
if (this.r <= this.bloom.r) {
this.r += this.growFactor; // / 10;
this.draw();
} else {
this.isfinished = true;
}
}
}
function Bloom(p, r, c, pc, garden) {
this.p = p;
this.r = r;
this.c = c;
this.pc = pc;
this.petals = [];
this.garden = garden;
this.init();
this.garden.addBloom(this);
}
Bloom.prototype = {
draw: function () {
var p, isfinished = true;
this.garden.ctx.save();
this.garden.ctx.translate(this.p.x, this.p.y);
for (var i = 0; i < this.petals.length; i++) {
p = this.petals[i];
p.render();
isfinished *= p.isfinished;
}
this.garden.ctx.restore();
if (isfinished == true) {
this.garden.removeBloom(this);
}
},
init: function () {
var angle = 360 / this.pc;
var startAngle = Garden.randomInt(0, 90);
for (var i = 0; i < this.pc; i++) {
this.petals.push(new Petal(Garden.random(Garden.options.petalStretch.min, Garden.options.petalStretch.max), Garden.random(Garden.options.petalStretch.min, Garden.options.petalStretch.max), startAngle + i * angle, angle, Garden.random(Garden.options.growFactor.min, Garden.options.growFactor.max), this));
}
}
}
function Garden(ctx, element) {
this.blooms = [];
this.element = element;
this.ctx = ctx;
}
Garden.prototype = {
render: function () {
for (var i = 0; i < this.blooms.length; i++) {
this.blooms[i].draw();
}
},
addBloom: function (b) {
this.blooms.push(b);
},
removeBloom: function (b) {
var bloom;
for (var i = 0; i < this.blooms.length; i++) {
bloom = this.blooms[i];
if (bloom === b) {
this.blooms.splice(i, 1);
return this;
}
}
},
createRandomBloom: function (x, y) {
this.createBloom(x, y, Garden.randomInt(Garden.options.bloomRadius.min, Garden.options.bloomRadius.max), Garden.randomrgba(Garden.options.color.rmin, Garden.options.color.rmax, Garden.options.color.gmin, Garden.options.color.gmax, Garden.options.color.bmin, Garden.options.color.bmax, Garden.options.color.opacity), Garden.randomInt(Garden.options.petalCount.min, Garden.options.petalCount.max));
},
createBloom: function (x, y, r, c, pc) {
new Bloom(new Vector(x, y), r, c, pc, this);
},
clear: function () {
this.blooms = [];
this.ctx.clearRect(0, 0, this.element.width, this.element.height);
}
}
Garden.options = {
petalCount: {
min: 8,
max: 15
},
petalStretch: {
min: 0.1,
max: 3
},
growFactor: {
min: 0.1,
max: 1
},
bloomRadius: {
min: 8,
max: 10
},
density: 10,
growSpeed: 1000 / 60,
color: {
rmin: 128,
rmax: 255,
gmin: 0,
gmax: 128,
bmin: 0,
bmax: 128,
opacity: 0.1
},
tanAngle: 60
};
Garden.random = function (min, max) {
return Math.random() * (max - min) + min;
};
Garden.randomInt = function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
Garden.circle = 2 * Math.PI;
Garden.degrad = function (angle) {
return Garden.circle / 360 * angle;
};
Garden.raddeg = function (angle) {
return angle / Garden.circle * 360;
};
Garden.rgba = function (r, g, b, a) {
return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
};
Garden.randomrgba = function (rmin, rmax, gmin, gmax, bmin, bmax, a) {
var r = Math.round(Garden.random(rmin, rmax));
var g = Math.round(Garden.random(gmin, gmax));
var b = Math.round(Garden.random(bmin, bmax));
var limit = 5;
if (Math.abs(r - g) <= limit && Math.abs(g - b) <= limit && Math.abs(b - r) <= limit) {
return Garden.rgba(rmin, rmax, gmin, gmax, bmin, bmax, a);
} else {
return Garden.rgba(r, g, b, a);
}
};
以上就是代碼的全部。學(xué)習(xí)完順便做個(gè)效果向女朋友表白噢。
更多好玩有趣的效果學(xué)習(xí),請(qǐng)關(guān)注 W3Cschool 官網(wǎng)。
推薦課程:
- JavaScript 實(shí)戰(zhàn):動(dòng)態(tài)網(wǎng)站開(kāi)發(fā)
- 微信小程序之豆瓣電影項(xiàng)目實(shí)戰(zhàn)
- JavaScript 交互式網(wǎng)站實(shí)戰(zhàn)開(kāi)發(fā)