Ngoài những món quà tặng Giáng sinh thông thường, các chàng trai có thể tự làm ra một trái tim độc đáo từ những đoạn code đơn giản để gửi tặng nàng vào đúng đêm Giáng sinh và khiến nàng phải bất ngờ vì món quà “hot trend” đẹp, độc, lạ này.
Để có thể “bắt trend” tỏ tình ngọt ngào của thủ khoa Lý và tạo ra một món quà Giáng sinh lãng mạn để tặng cho người yêu, hãy cùng điểm qua những cách làm code trái tim độc đáo và ấn tượng sau đây:
Đây là một trong những mẫu trái tim cơ bản được sử dụng phổ biến nhất ngay từ lúc trào lưu làm code trái tim trở nên thịnh hành trên các trang mạng xã hội.
Theo đó, hình trái tim đơn giản này được lập trình bởi code HTML để tạo ra hiệu ứng chuyển động của các trái tim nhỏ màu hồng thành phần viền của một trái tim lớn. Cách làm này rất dễ thực hiện mà vẫn có thể tạo ra một thành quả không kém phần đẹp mắt, ấn tượng để dành tặng người yêu trong dịp Noel.
Chi tiết cách làm code trái tim cơ bản:
Bước 1: Sao chép nguồn code trái tim cơ bản sau đây:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> Heart </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<style>
html, body {
height: 100%;
padding: 0;
margin: 0;
background: black;
}
canvas {
position: absolute;
width: 100%;
height: 100%;
}
</style>
</HEAD>
<BODY>
<canvas id="pinkboard"></canvas>
<script>
/*
* Settings
*/
var settings = {
particles: {
length: 500, // maximum amount of particles
duration: 2, // particle duration in sec
velocity: 100, // particle velocity in pixels/sec
effect: -0.75, // play with this for a nice effect
size: 30, // particle size in pixels
},
};
/*
* RequestAnimationFrame polyfill by Erik Möller
*/
(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=new Date().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() {
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() {
var length = this.length();
this.x /= length;
this.y /= length;
return this;
};
return Point;
})();
/*
* Particle class
*/
var 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;
}
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;
function ParticlePool(length) {
// create and populate particle pool
particles = new Array(length);
for (var 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);
// handle circular queue
firstFree++;
if (firstFree == particles.length) firstFree = 0;
if (firstActive == firstFree ) firstActive++;
if (firstActive == particles.length) firstActive = 0;
};
ParticlePool.prototype.update = function(deltaTime) {
var i;
// update active particles
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);
}
// remove inactive particles
while (particles[firstActive].age >= duration && firstActive != firstFree) {
firstActive++;
if (firstActive == particles.length) firstActive = 0;
}
};
ParticlePool.prototype.draw = function(context, image) {
// draw active particles
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;
})();
/*
* Putting it all together
*/
(function(canvas) {
var context = canvas.getContext('2d'),
particles = new ParticlePool(settings.particles.length),
particleRate = settings.particles.length / settings.particles.duration, // particles/sec
time;
// get point on heart with -PI <= t <= PI
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
);
}
// creating the particle image using a dummy canvas
var image = (function() {
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
canvas.width = settings.particles.size;
canvas.height = settings.particles.size;
// helper function to create the path
function to(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;
}
// create the path
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();
// create the fill
context.fillStyle = '#ea80b0';
context.fill();
// create the image
var image = new Image();
image.src = canvas.toDataURL();
return image;
})();
// render that thing!
function render() {
// next animation frame
requestAnimationFrame(render);
// update time
var newTime = new Date().getTime() / 1000,
deltaTime = newTime - (time || newTime);
time = newTime;
// clear canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// create new particles
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);
}
// update and draw particles
particles.update(deltaTime);
particles.draw(context, image);
}
// handle (re-)sizing of the canvas
function onResize() {
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
}
window.onresize = onResize;
// delay rendering bootstrap
setTimeout(function() {
onResize();
render();
}, 10);
})(document.getElementById('pinkboard'));
var colours=new Array('#f00', '#f06', '#f0f', '#f6f', '#f39', '#f9c'); // colours of the hearts
var minisize=10; // smallest size of hearts in pixels
var maxisize=20; // biggest size of hearts in pixels
var hearts=100; // maximum number of hearts on screen
var over_or_under="over"; // set to "over" for hearts to always be on top, or "under" to allow them to float behind other objects
/*****************************
*JavaScript Love Heart Cursor*
* (c)2013+ mf2fm web-design *
* http://www.mf2fm.com/rv *
* DON'T EDIT BELOW THIS BOX *
*****************************/
var x=ox=400;
var y=oy=300;
var swide=800;
var shigh=600;
var sleft=sdown=0;
var herz=new Array();
var herzx=new Array();
var herzy=new Array();
var herzs=new Array();
var kiss=false;
if (typeof('addRVLoadEvent')!='function') function addRVLoadEvent(funky) {
var oldonload=window.onload;
if (typeof(oldonload)!='function') window.onload=funky;
else window.onload=function() {
if (oldonload) oldonload();
funky();
}
}
addRVLoadEvent(mwah);
function mwah() { if (document.getElementById) {
var i, heart;
for (i=0; i<hearts; i++) {
heart=createDiv("auto", "auto");
heart.style.visibility="hidden";
heart.style.zIndex=(over_or_under=="over")?"1001":"0";
heart.style.color=colours[i%colours.length];
heart.style.pointerEvents="none";
if (navigator.appName=="Microsoft Internet Explorer") heart.style.filter="alpha(opacity=75)";
else heart.style.opacity=0.45;
heart.appendChild(document.createTextNode(String.fromCharCode(9829)));
document.body.appendChild(heart);
herz[i]=heart;
herzy[i]=false;
}
set_scroll();
set_width();
herzle();
}}
function herzle() {
var c;
if (Math.abs(x-ox)>1 || Math.abs(y-oy)>1) {
ox=x;
oy=y;
for (c=0; c<hearts; c++) if (herzy[c]===false) {
herz[c].firstChild.nodeValue=String.fromCharCode(9829);
herz[c].style.left=(herzx[c]=x-minisize/2)+"px";
herz[c].style.top=(herzy[c]=y-minisize)+"px";
herz[c].style.fontSize=minisize+"px";
herz[c].style.fontWeight='normal';
herz[c].style.visibility='visible';
herzs[c]=minisize;
break;
}
}
for (c=0; c<hearts; c++) if (herzy[c]!==false) blow_me_a_kiss(c);
setTimeout("herzle()", 30);
}
document.onmousedown=pucker;
document.onmouseup=function(){clearTimeout(kiss);};
function pucker() {
ox=-1;
oy=-1;
kiss=setTimeout('pucker()', 100);
}
function blow_me_a_kiss(i) {
herzy[i]-=herzs[i]/minisize+i%2;
herzx[i]+=(i%5-2)/5;
if (herzy[i]<sdown-herzs[i] || herzx[i]<sleft-herzs[i] || herzx[i]>sleft+swide-herzs[i]) {
herz[i].style.visibility="hidden";
herzy[i]=false;
}
else if (herzs[i]>minisize+1 && Math.random()<2.5/hearts) break_my_heart(i);
else {
if (Math.random()<maxisize/herzy[i] && herzs[i]<maxisize) herz[i].style.fontSize=(++herzs[i])+"px";
herz[i].style.top=herzy[i]+"px";
herz[i].style.left=herzx[i]+"px";
}
}
function break_my_heart(i) {
var t;
herz[i].firstChild.nodeValue=String.fromCharCode(9676);
herz[i].style.fontWeight='bold';
herzy[i]=false;
for (t=herzs[i]; t<=maxisize; t++) setTimeout('herz['+i+'].style.fontSize="'+t+'px"', 60*(t-herzs[i]));
setTimeout('herz['+i+'].style.visibility="hidden";', 60*(t-herzs[i]));
}
document.onmousemove=mouse;
function mouse(e) {
if (e) {
y=e.pageY;
x=e.pageX;
}
else {
set_scroll();
y=event.y+sdown;
x=event.x+sleft;
}
}
window.onresize=set_width;
function set_width() {
var sw_min=999999;
var sh_min=999999;
if (document.documentElement && document.documentElement.clientWidth) {
if (document.documentElement.clientWidth>0) sw_min=document.documentElement.clientWidth;
if (document.documentElement.clientHeight>0) sh_min=document.documentElement.clientHeight;
}
if (typeof(self.innerWidth)=='number' && self.innerWidth) {
if (self.innerWidth>0 && self.innerWidth<sw_min) sw_min=self.innerWidth;
if (self.innerHeight>0 && self.innerHeight<sh_min) sh_min=self.innerHeight;
}
if (document.body.clientWidth) {
if (document.body.clientWidth>0 && document.body.clientWidth<sw_min) sw_min=document.body.clientWidth;
if (document.body.clientHeight>0 && document.body.clientHeight<sh_min) sh_min=document.body.clientHeight;
}
if (sw_min==999999 || sh_min==999999) {
sw_min=800;
sh_min=600;
}
swide=sw_min;
shigh=sh_min;
}
window.onscroll=set_scroll;
function set_scroll() {
if (typeof(self.pageYOffset)=='number') {
sdown=self.pageYOffset;
sleft=self.pageXOffset;
}
else if (document.body && (document.body.scrollTop || document.body.scrollLeft)) {
sdown=document.body.scrollTop;
sleft=document.body.scrollLeft;
}
else if (document.documentElement && (document.documentElement.scrollTop || document.documentElement.scrollLeft)) {
sleft=document.documentElement.scrollLeft;
sdown=document.documentElement.scrollTop;
}
else {
sdown=0;
sleft=0;
}
}
function createDiv(height, width) {
var div=document.createElement("div");
div.style.position="absolute";
div.style.height=height;
div.style.width=width;
div.style.overflow="hidden";
div.style.backgroundColor="transparent";
return (div);
}
// ]]>
</script>
</BODY>
</HTML>
Bước 2: Truy cập vào đường link https://www.tutorialspoint.com/online_html_editor.php và dán mã nguồn vào khung “Source Code” phía bên trái.
Thành quả hình trái tim được tạo ra từ phần mã nguồn sẽ được hiển thị ở khung phía bên phải màn hình.
Chỉ với hai bước đơn giản là bạn đã có thể tạo ra một món quà Giáng sinh đậm chất “ngôn tình” khiến cho nàng phải “rung rinh” vì sự lãng mạn của mình.
Một cách cách làm khác mà bạn có thể tham khảo chính là sử dụng đoạn mã nguồn HTML để tạo ra một trái tim màu đỏ với hiệu ứng chuyển động theo nhịp đập chân thật.
Khác với mẫu trái tim trước, điểm nhấn của hình trái tim màu đỏ này chính là phần hiệu ứng động của hàng loạt trái tim nhỏ lan tỏa xung quanh tạo nên một trái tim màu đỏ rực rỡ vô cùng “xịn sò” và dễ thương. Chắc hẳn các nàng sẽ rất bất ngờ và hạnh phúc khi nhận được món quà Giáng sinh độc đáo này.
Về cơ bản, các trái tim bằng code đều có cách làm giống nhau, vì vậy để làm code trái tim đập màu đỏ bạn cũng sẽ thực hiện các bước tương tự như sau:
Chi tiết cách làm code trái tim đập màu đỏ:
Bước 1: Sao chép nguồn code trái tim đập màu đỏ sau đây:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> MINH IT </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<link rel="stylesheet" href="style.css">
<style>
html, body {
height: 100%;
padding: 0;
margin: 0;
background: rgba(0, 0, 0, 0.851);
}
canvas {
position: absolute;
width: 100%;
height: 100%;
}
</style>
</HEAD>
<BODY>
<div class="box">
<canvas id="pinkboard"></canvas>
</div>
<script>
var settings = {
particles: {
length: 10000, // maximum amount of particles
duration: 4, // particle duration in sec
velocity: 80, // particle velocity in pixels/sec
effect: -1.3, // play with this for a nice effect
size: 8, // particle size in pixels
},
};
/*
*/
(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=new Date().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() {
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() {
var length = this.length();
this.x /= length;
this.y /= length;
return this;
};
return Point;
})();
/*
* Particle class
*/
var 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;
}
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;
function ParticlePool(length) {
// create and populate particle pool
particles = new Array(length);
for (var 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);
// handle circular queue
firstFree++;
if (firstFree == particles.length) firstFree = 0;
if (firstActive == firstFree ) firstActive++;
if (firstActive == particles.length) firstActive = 0;
};
ParticlePool.prototype.update = function(deltaTime) {
var i;
// update active particles
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);
}
// remove inactive particles
while (particles[firstActive].age >= duration && firstActive != firstFree) {
firstActive++;
if (firstActive == particles.length) firstActive = 0;
}
};
ParticlePool.prototype.draw = function(context, image) {
// draw active particles
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;
})();
/*
* Putting it all together
*/
(function(canvas) {
var context = canvas.getContext('2d'),
particles = new ParticlePool(settings.particles.length),
particleRate = settings.particles.length / settings.particles.duration, // particles/sec
time;
// get point on heart with -PI <= t <= PI
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
);
}
// creating the particle image using a dummy canvas
var image = (function() {
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
canvas.width = settings.particles.size;
canvas.height = settings.particles.size;
// helper function to create the path
function to(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;
}
// create the path
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();
// create the fill
context.fillStyle = '#f50b02';
context.fill();
// create the image
var image = new Image();
image.src = canvas.toDataURL();
return image;
})();
// render that thing!
function render() {
// next animation frame
requestAnimationFrame(render);
// update time
var newTime = new Date().getTime() / 1000,
deltaTime = newTime - (time || newTime);
time = newTime;
// clear canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// create new particles
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);
}
// update and draw particles
particles.update(deltaTime);
particles.draw(context, image);
}
// handle (re-)sizing of the canvas
function onResize() {
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
}
window.onresize = onResize;
// delay rendering bootstrap
setTimeout(function() {
onResize();
render();
}, 10);
})(document.getElementById('pinkboard'));
</script>
</BODY>
</HTML>
Bước 2: Truy cập vào liên kết https://www.tutorialspoint.com/online_html_editor.php
Sau đó dán mã nguồn vào khung “Source Code” phía bên trái. Tiếp theo, hình trái tim chuyển động màu đỏ sẽ được hiển thị ở khung kết quả nằm ở phía bên phải màn hình.
Bạn có thể phóng to hoặc thu nhỏ phần khung kết quả này để có thể chiêm ngưỡng thành quả sắc nét và đẹp mắt hơn.
Nếu như bạn đang tìm kiếm một trái tim sáng tạo và ấn tượng để tặng cho người yêu trong ngày Giáng sinh, ắt hẳn mẫu trái tim huyền bí này sẽ là sự lựa chọn hoàn hảo dành cho bạn.
Đây là một mẫu code được các “cao thủ” IT tại Việt Nam sáng tạo theo sở thích của mình, do đó hình ảnh trái tim này không được lập trình dựa trên bản gốc mà sở hữu một giao diện rất đặc biệt với hiệu ứng in-out “ảo diệu”.
Điểm nổi bật của mẫu trái tim này chính là phần hiệu ứng những vệt sáng lấp lánh, lung linh được kết nối lại thành hình trái tim chuyển động độc đáo, mới lạ.
Dưới đây là các bước để làm code trái tim huyền bí mà bạn có thể tham khảo:
Chi tiết cách làm code trái tim huyền bí:
Bước 1: Sao chép nguồn code trái tim màu đỏ huyền bí sau đây:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
canvas {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .2);
}
</style>
</head>
<body>
<canvas id="heart"></canvas>
<script>
window.requestAnimationFrame =
window.__requestAnimationFrame ||
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
(function () {
return function (callback, element) {
var lastTime = element.__lastTime;
if (lastTime === undefined) {
lastTime = 0;
}
var currTime = Date.now();
var timeToCall = Math.max(1, 33 - (currTime - lastTime));
window.setTimeout(callback, timeToCall);
element.__lastTime = currTime + timeToCall;
};
})();
window.isDevice = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(((navigator.userAgent || navigator.vendor || window.opera)).toLowerCase()));
var loaded = false;
var init = function () {
if (loaded) return;
loaded = true;
var mobile = window.isDevice;
var koef = mobile ? 0.5 : 1;
var canvas = document.getElementById('heart');
var ctx = canvas.getContext('2d');
var width = canvas.width = koef * innerWidth;
var height = canvas.height = koef * innerHeight;
var rand = Math.random;
ctx.fillStyle = "rgba(0,0,0,1)";
ctx.fillRect(0, 0, width, height);
var heartPosition = function (rad) {
//return [Math.sin(rad), Math.cos(rad)];
return [Math.pow(Math.sin(rad), 3), -(15 * Math.cos(rad) - 5 * Math.cos(2 * rad) - 2 * Math.cos(3 * rad) - Math.cos(4 * rad))];
};
var scaleAndTranslate = function (pos, sx, sy, dx, dy) {
return [dx + pos[0] * sx, dy + pos[1] * sy];
};
window.addEventListener('resize', function () {
width = canvas.width = koef * innerWidth;
height = canvas.height = koef * innerHeight;
ctx.fillStyle = "rgba(0,0,0,1)";
ctx.fillRect(0, 0, width, height);
});
var traceCount = mobile ? 20 : 50;
var pointsOrigin = [];
var i;
var dr = mobile ? 0.3 : 0.1;
for (i = 0; i < Math.PI * 2; i += dr) pointsOrigin.push(scaleAndTranslate(heartPosition(i), 210, 13, 0, 0));
for (i = 0; i < Math.PI * 2; i += dr) pointsOrigin.push(scaleAndTranslate(heartPosition(i), 150, 9, 0, 0));
for (i = 0; i < Math.PI * 2; i += dr) pointsOrigin.push(scaleAndTranslate(heartPosition(i), 90, 5, 0, 0));
var heartPointsCount = pointsOrigin.length;
var targetPoints = [];
var pulse = function (kx, ky) {
for (i = 0; i < pointsOrigin.length; i++) {
targetPoints[i] = [];
targetPoints[i][0] = kx * pointsOrigin[i][0] + width / 2;
targetPoints[i][1] = ky * pointsOrigin[i][1] + height / 2;
}
};
var e = [];
for (i = 0; i < heartPointsCount; i++) {
var x = rand() * width;
var y = rand() * height;
e[i] = {
vx: 0,
vy: 0,
R: 2,
speed: rand() + 5,
q: ~~(rand() * heartPointsCount),
D: 2 * (i % 2) - 1,
force: 0.2 * rand() + 0.7,
f: "hsla(0," + ~~(40 * rand() + 60) + "%," + ~~(60 * rand() + 20) + "%,.3)",
trace: []
};
for (var k = 0; k < traceCount; k++) e[i].trace[k] = { x: x, y: y };
}
var config = {
traceK: 0.4,
timeDelta: 0.01
};
var time = 0;
var loop = function () {
var n = -Math.cos(time);
pulse((1 + n) * .5, (1 + n) * .5);
time += ((Math.sin(time)) < 0 ? 9 : (n > 0.8) ? .2 : 1) * config.timeDelta;
ctx.fillStyle = "rgba(0,0,0,.1)";
ctx.fillRect(0, 0, width, height);
for (i = e.length; i--;) {
var u = e[i];
var q = targetPoints[u.q];
var dx = u.trace[0].x - q[0];
var dy = u.trace[0].y - q[1];
var length = Math.sqrt(dx * dx + dy * dy);
if (10 > length) {
if (0.95 < rand()) {
u.q = ~~(rand() * heartPointsCount);
}
else {
if (0.99 < rand()) {
u.D *= -1;
}
u.q += u.D;
u.q %= heartPointsCount;
if (0 > u.q) {
u.q += heartPointsCount;
}
}
}
u.vx += -dx / length * u.speed;
u.vy += -dy / length * u.speed;
u.trace[0].x += u.vx;
u.trace[0].y += u.vy;
u.vx *= u.force;
u.vy *= u.force;
for (k = 0; k < u.trace.length - 1;) {
var T = u.trace[k];
var N = u.trace[++k];
N.x -= config.traceK * (N.x - T.x);
N.y -= config.traceK * (N.y - T.y);
}
ctx.fillStyle = u.f;
for (k = 0; k < u.trace.length; k++) {
ctx.fillRect(u.trace[k].x, u.trace[k].y, 1, 1);
}
}
//ctx.fillStyle = "rgba(255,255,255,1)";
//for (i = u.trace.length; i--;) ctx.fillRect(targetPoints[i][0], targetPoints[i][1], 2, 2);
window.requestAnimationFrame(loop, canvas);
};
loop();
};
var s = document.readyState;
if (s === 'complete' || s === 'loaded' || s === 'interactive') init();
else document.addEventListener('DOMContentLoaded', init, false);
</script>
</body>
</html>
Bước 2: Truy cập vào liên kết https://www.tutorialspoint.com/online_html_editor.php
Kế đến, dán phần mã nguồn vừa sao chép vào khung “Source Code” phía bên trái. Cuối cùng, ở phía bên phải màn hình sẽ cho ra kết quả là một hình trái tim chuyển động màu đỏ vô cùng ấn tượng.
Trong trường hợp bạn muốn chèn thêm những lời chúc Giáng sinh ý nghĩa hoặc những tâm tư, tình cảm ngọt ngào đến nửa kia, bạn cũng có thể sử dụng mẫu trái tim chèn chữ làm bằng code này.
Xét về phần hiệu ứng, hình trái tim này độc đáo hơn các mẫu code khác do phần khung trái tim có thể chuyển động phóng to và thu nhỏ theo nhịp đập của trái tim. Bên cạnh đó, phần nội dung mà người gửi muốn truyền tải sẽ được hiển thị ngay chính giữa khiến cho mẫu trái tim này trở nên đặc biệt hơn.
Để tạo ra hình trái tim đập có chèn chữ này, bạn có thể tham khảo các bước thực hiện cụ thể sau đây:
Chi tiết cách làm code trái tim đập chèn chữ:
Bước 1: Sao chép nguồn code trái tim có hiệu ứng chèn chữ sau đây:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> Heart </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<style>
html, body {
height: 100%;
padding: 0;
margin: 0;
background: #000;
display: flex;
justify-content: center;
align-items: center;
}
.box {
width: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
}
canvas {
position: absolute;
width: 100%;
height: 100%;
}
#pinkboard {
position: relative;
margin: auto;
height: 500px;
width: 500px;
animation: animate 1.3s infinite;
}
#pinkboard:before, #pinkboard:after {
content: '';
position: absolute;
background: #FF5CA4;
width: 100px;
height: 160px;
border-top-left-radius: 50px;
border-top-right-radius: 50px;
}
#pinkboard:before {
left: 100px;
transform: rotate(-45deg);
transform-origin: 0 100%;
box-shadow: 0 14px 28px rgba(0,0,0,0.25),
0 10px 10px rgba(0,0,0,0.22);
}
#pinkboard:after {
left: 0;
transform: rotate(45deg);
transform-origin: 100% 100%;
}
@keyframes animate {
0% {
transform: scale(1);
}
30% {
transform: scale(.8);
}
60% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
</style>
</HEAD>
<BODY>
<div class="box">
<canvas id="pinkboard"></canvas>
</div>
<script>
/*
* Settings
*/
var settings = {
particles: {
length: 2000, // maximum amount of particles
duration: 2, // particle duration in sec
velocity: 100, // particle velocity in pixels/sec
effect: -1.3, // play with this for a nice effect
size: 13, // particle size in pixels
},
};
/*
* RequestAnimationFrame polyfill by Erik Möller
*/
(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=new Date().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() {
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() {
var length = this.length();
this.x /= length;
this.y /= length;
return this;
};
return Point;
})();
/*
* Particle class
*/
var 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;
}
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;
function ParticlePool(length) {
// create and populate particle pool
particles = new Array(length);
for (var 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);
// handle circular queue
firstFree++;
if (firstFree == particles.length) firstFree = 0;
if (firstActive == firstFree ) firstActive++;
if (firstActive == particles.length) firstActive = 0;
};
ParticlePool.prototype.update = function(deltaTime) {
var i;
// update active particles
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);
}
// remove inactive particles
while (particles[firstActive].age >= duration && firstActive != firstFree) {
firstActive++;
if (firstActive == particles.length) firstActive = 0;
}
};
ParticlePool.prototype.draw = function(context, image) {
// draw active particles
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;
})();
/*
* Putting it all together
*/
(function(canvas) {
var context = canvas.getContext('2d'),
particles = new ParticlePool(settings.particles.length),
particleRate = settings.particles.length / settings.particles.duration, // particles/sec
time;
// get point on heart with -PI <= t <= PI
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
);
}
// creating the particle image using a dummy canvas
var image = (function() {
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
canvas.width = settings.particles.size;
canvas.height = settings.particles.size;
// helper function to create the path
function to(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;
}
// create the path
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();
// create the fill
context.fillStyle = '#FF5CA4';
context.fill();
// create the image
var image = new Image();
image.src = canvas.toDataURL();
return image;
})();
// render that thing!
function render() {
// next animation frame
requestAnimationFrame(render);
// update time
var newTime = new Date().getTime() / 1000,
deltaTime = newTime - (time || newTime);
time = newTime;
// clear canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// create new particles
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);
}
// update and draw particles
particles.update(deltaTime);
particles.draw(context, image);
}
// handle (re-)sizing of the canvas
function onResize() {
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
}
window.onresize = onResize;
// delay rendering bootstrap
setTimeout(function() {
onResize();
render();
}, 10);
})(document.getElementById('pinkboard'));
</script>
<div class="center-text",
style="background-color:rgb(0, 0, 0);
width: 100%;
color: rgb(225, 12, 168);
height:100%;
font-size: 31px;
font-style: italic;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 5px;
text-align: center;">I Love You</div>
</BODY>
</HTML>
Bước 2: Truy cập vào đường link https://www.tutorialspoint.com/online_html_editor.php và dán mã nguồn vào khung “Source Code” nằm ở phía bên trái. Sau đó, thành quả hình trái tim sẽ được hiển thị ở khung phía bên phải màn hình.
Đặc biệt, bạn hoàn toàn có thể điều chỉnh nội dung tùy theo ý muốn bằng cách nhập phần nội dung thay thế vào đoạn code được in đậm phía trên.
Còn món quà Giáng sinh nào ý nghĩa hơn một trái tim chân thành chứa đựng những lời nhắn nhủ ngọt ngào từ người yêu. Cách làm code trái tim chèn chữ này chắc chắn sẽ khiến các nàng đắm chìm trong hạnh phúc khi nhìn thấy.
Bên cạnh các mã nguồn hình trái tim thông thường hoặc có thêm chữ bên trong, nguồn code trái tim có chèn hình ảnh này cũng là một sự lựa chọn ấn tượng mà bạn không nên bỏ qua.
Bằng cách chèn thêm hình ảnh của mình và nửa kia vào trái tim kết hợp với hiệu ứng chuyển động theo nhịp đập và các tia sáng lấp lánh xung quanh, mẫu code trái tim này sẽ giúp bạn tạo nên một “tác phẩm nghệ thuật” mang tính cá nhân và là một món quà Giáng sinh đặc biệt dành riêng cho người ấy.
Cùng tham khảo từng bước thực hiện code trái tim đập chèn hình ảnh chi tiết để có thể tự mình làm ra một trái tim “độc nhất vô nhị” dành tặng cho người yêu trong dịp Giáng sinh này.
Chi tiết cách làm code trái tim có chèn hình ảnh:
Bước 1: Truy cập vào đường link Google Drive này để tải file lập trình code trái tim đập có hình ảnh về máy:
Sau khi thư mục đã được tải xuống thì tiến hành giải nén file.
Bước 2: Di chuyển file hình ảnh cần chèn vào chung thư mục có chứa code trái tim để có thể điều chỉnh code và chèn ảnh vào phần mã nguồn.
Bước 3: Tiếp theo, click chọn chuột phải và chọn “Properties” để xem định dạng file ảnh là JPG hay PNG, sau đó sao chép tên file và loại file ảnh để chèn vào code.
Bước 4: Click chuột phải vào file index.html, chọn Notepad để mở file.
Bạn cũng có thể sử dụng công cụ đọc file HTML đã cài sẵn trên máy tính nếu có.
Bước 5: Trong mục EDIT Here, tiến hành điều chỉnh nội dung xuất hiện trong trái tim, cụ thể như sau:
- Tại dòng STARDUST1, bạn có thể thay đổi nội dung “2022” tùy theo ý thích.
- Tại dòng STARDUST2, hãy điền tên của mình cùng với nửa kia.
- Ở dòng STARDUST3, bạn có thể điều chỉnh dòng chữ “Love You” thành nội dung mà mình muốn truyền tải.
- Kế đến, ở phần img, điền vào tên và định dạng của hình ảnh mà bạn muốn chèn vào trái tim như hình bên dưới.
Bước 6: Nhấn vào File và chọn nút Save để lưu lại thành phẩm.
Để ngắm nhìn thành quả của mình, bạn chỉ cần click chọn và mở file HTML lên như bình thường.
Có thể thấy, đoạn code trái tim này có phần khác biệt, độc lạ nhất so với các mẫu trái tim làm bằng code khác.
Thay vì tạo thành phần khung trái tim hay một trái tim hoàn chỉnh, mẫu code này sẽ bao gồm các đường viền hình trái tim xếp nối tiếp nhau, kết hợp với hiệu ứng chuyển động nhịp nhàng, chân thật.
Nếu như bạn vẫn chưa tìm được món quà lý tưởng cho người yêu trong dịp Giáng sinh 2022, mẫu code trái tim có nhịp đập chân thật này sẽ là một sự lựa chọn không tồi dành cho bạn.
Để làm ra mẫu trái tim này, bạn sẽ không phải mất quá nhiều thời gian và công sức chỉnh sửa, mà chỉ cần thực hiện theo các bước như sau:
Chi tiết cách làm code trái tim chuyển động theo nhịp đập:
Bước 1: Sao chép nguồn code trái tim có hiệu ứng nhịp đập sau đây:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> MINH IT </TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="">
<META NAME="Keywords" CONTENT="">
<META NAME="Description" CONTENT="">
<link rel="stylesheet" href="style.css">
<style>
html, body {
height: 100%;
padding: 0;
margin: 0;
background: rgba(0, 0, 0, 0.851);
}
canvas {
position: absolute;
width: 100%;
height: 100%;
}
</style>
</HEAD>
<BODY>
<div class="box">
<canvas id="pinkboard"></canvas>
</div>
<script>
var settings = {
particles: {
length: 10000, // maximum amount of particles
duration: 4, // particle duration in sec
velocity: 80, // particle velocity in pixels/sec
effect: -1.3, // play with this for a nice effect
size: 8, // particle size in pixels
},
};
/*
*/
(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=new Date().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() {
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() {
var length = this.length();
this.x /= length;
this.y /= length;
return this;
};
return Point;
})();
/*
* Particle class
*/
var 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;
}
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;
function ParticlePool(length) {
// create and populate particle pool
particles = new Array(length);
for (var 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);
// handle circular queue
firstFree++;
if (firstFree == particles.length) firstFree = 0;
if (firstActive == firstFree ) firstActive++;
if (firstActive == particles.length) firstActive = 0;
};
ParticlePool.prototype.update = function(deltaTime) {
var i;
// update active particles
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);
}
// remove inactive particles
while (particles[firstActive].age >= duration && firstActive != firstFree) {
firstActive++;
if (firstActive == particles.length) firstActive = 0;
}
};
ParticlePool.prototype.draw = function(context, image) {
// draw active particles
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;
})();
/*
* Putting it all together
*/
(function(canvas) {
var context = canvas.getContext('2d'),
particles = new ParticlePool(settings.particles.length),
particleRate = settings.particles.length / settings.particles.duration, // particles/sec
time;
// get point on heart with -PI <= t <= PI
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
);
}
// creating the particle image using a dummy canvas
var image = (function() {
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
canvas.width = settings.particles.size;
canvas.height = settings.particles.size;
// helper function to create the path
function to(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;
}
// create the path
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();
// create the fill
context.fillStyle = '#f50b02';
context.fill();
// create the image
var image = new Image();
image.src = canvas.toDataURL();
return image;
})();
// render that thing!
function render() {
// next animation frame
requestAnimationFrame(render);
// update time
var newTime = new Date().getTime() / 1000,
deltaTime = newTime - (time || newTime);
time = newTime;
// clear canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// create new particles
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);
}
// update and draw particles
particles.update(deltaTime);
particles.draw(context, image);
}
// handle (re-)sizing of the canvas
function onResize() {
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
}
window.onresize = onResize;
// delay rendering bootstrap
setTimeout(function() {
onResize();
render();
}, 10);
})(document.getElementById('pinkboard'));
</script>
</BODY>
</HTML>
Bước 2: Truy cập vào đường link https://www.tutorialspoint.com/online_html_editor.php
Sau đó dán mã nguồn vào khung “Source Code” phía bên trái. Mẫu hình trái tim này sẽ được hiển thị trong khung kết quả phía bên phải màn hình.
Đối với những người yêu thích sự sáng tạo và mới lạ, chắc chắn mẫu code trái tim kim cương rực rỡ sắc màu này sẽ là một sự lựa chọn thú vị mang đến cho bạn và nửa kia một kỉ niệm đáng nhớ trong mùa Giáng sinh này.
Có thể thấy, mẫu trái tim này hoàn toàn khác biệt từ thiết kế đến hiệu ứng. Điểm nhấn đặc biệt nhất chính là hình trái tim kim cương 3D chuyển động xoay vòng ở chính giữa và phần viền trái tim được tạo thành từ những đốm sáng lung linh, huyền ảo xung quanh.
Ngoài ra, phần phông nền cũng được thiết kế thêm các trái tim nhỏ nhỏ xinh xinh với nhiều màu sắc khác nhau khiến cho hình trái tim làm bằng code này thêm phần ấn tượng, độc đáo.
Dưới đây là cách tạo ra hình trái tim kim cương lung linh sắc màu từ code HTML mà bạn có thể tham khảo để dành tặng cho cô gái của mình trong mùa lễ Noel năm nay:
Chi tiết cách làm code trái tim kim cương có hiệu ứng màu sắc rực rỡ:
Bước 1: Sao chép nguồn code trái tim kim cương nhiều màu sắc sau đây:
<!DOCTYPE html>
<html lang="en"><head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>I Love You</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
overflow: hidden;
background-color: #000 !important;
}
body {
-webkit-font-soothing: antialiased;
}
.webgl {
position: fixed;
width: 100vw;
height: 100vw;
top: 0;
left: 0;
outline: none;
}
h1{
position: absolute;
top: 10vh;
left: 2.5rem;
right: 1rem;
text-align: center;
font-size: max(1rem, 3vh);
}
button {
position: absolute;
left: 0;
top: 0;
bottom: 0;
height: 12vh;
width: 12vh;
transform: translateY(2vh);
right: 0;
margin: auto;
-webkit-appearance: none;
background: transparent;
color: inherit;
border: none;
cursor: pointer;
}
svg{
width: 3.5vh;
}
</style>
<script>
window.console = window.console || function(t) {};
</script>
<script>
if (document.location.search.match(/type=embed/gi)) {
window.parent.postMessage("resize", "*");
}
</script>
</head>
<body translate="no">
<canvas class="webgl" data-engine="three.js r135" width="682" height="157" style="width: 682px; height: 157px;"></canvas>
<button id="play-music" type="button" aria-label="Play music" style="opacity: 1;"><svg fill="currentColor" viewBox="0 0 512 512" width="100" title="music">
<!-- <path d="M470.38 1.51L150.41 96A32 32 0 0 0 128 126.51v261.41A139 139 0 0 0 96 384c-53 0-96 28.66-96 64s43 64 96 64 96-28.66 96-64V214.32l256-75v184.61a138.4 138.4 0 0 0-32-3.93c-53 0-96 28.66-96 64s43 64 96 64 96-28.65 96-64V32a32 32 0 0 0-41.62-30.49z" /> -->
</svg></button>
<script type="x-shader/x-vertex" id="vertexShader">
#define M_PI 3.1415926535897932384626433832795
uniform float uTime;
uniform float uSize;
attribute float aScale;
attribute vec3 aColor;
attribute float random;
attribute float random1;
attribute float aSpeed;
varying vec3 vColor;
varying vec2 vUv;
void main() {
float sign = 2.0* (step(random, 0.5) -.5);
float t = sign*mod(-uTime * aSpeed* 0.005 + 10.0*aSpeed*aSpeed, M_PI);
float a = pow(t, 2.0) * pow((t - sign * M_PI), 2.0);
float radius = 0.14;
vec3 myOffset =
vec3(t, 1.0, 0.0);
myOffset = vec3(radius *16.0 * pow(sin(t), 2.0) * sin(t), radius * (13.0 * cos(t) - 5.0 * cos(2.0 * t) - 2.0 * cos(3.0 * t) - cos(4.0 * t)), .15*(a*(random1 - .5))*sin(abs(10.0*(sin(.2*uTime + .2*random)))*t));
vec3 displacedPosition = myOffset;
vec4 modelPosition = modelMatrix * vec4(displacedPosition.xyz, 1.0);
vec4 viewPosition = viewMatrix * modelPosition;
viewPosition.xyz += position * aScale * uSize * pow(a, .5) * .5;
gl_Position = projectionMatrix * viewPosition;
vColor = aColor;
vUv = uv;
}
</script>
<script type="x-shader/x-fragment" id="fragmentShader">
varying vec3 vColor;
varying vec2 vUv;
void main() {
vec2 uv = vUv;
vec3 color = vColor;
float strength = distance(uv, vec2(0.5));
strength *= 2.0;
strength = 1.0 - strength;
gl_FragColor = vec4(strength * color, 1.0);
}
</script>
<script type="x-shader/x-vertex" id="vertexShader1">
#define M_PI 3.1415926535897932384626433832795
uniform float uTime;
uniform float uSize;
attribute float aScale;
attribute vec3 aColor;
attribute float phi;
attribute float random;
attribute float random1;
varying vec3 vColor;
varying vec2 vUv;
void main() {
float t = 0.01 * uTime + 12.0;
float angle = phi;
t = mod((-uTime + 100.0) * 0.06* random1 + random *2.0 * M_PI , 2.0 * M_PI);
vec3 myOffset = vec3(5.85*cos(angle * (t )), 2.0*(t - M_PI), 3.0*sin(angle * (t )/t));
vec4 modelPosition = modelMatrix * vec4(myOffset, 1.0);
vec4 viewPosition = viewMatrix * modelPosition;
viewPosition.xyz += position * aScale * uSize;
gl_Position = projectionMatrix * viewPosition;
vColor = aColor;
vUv = uv;
}
</script>
<script type="x-shader/x-fragment" id="fragmentShader1">
uniform sampler2D uTex;
varying vec3 vColor;
varying vec2 vUv;
void main() {
vec2 uv = vUv;
vec3 color = vColor;
float strength = distance(uv, vec2(0.5, .65));
strength *= 2.0;
strength = 1.0 - strength;
vec3 texture = texture2D(uTex, uv).rgb;
gl_FragColor = vec4(texture * color * (strength + .3), 1.);
}
</script>
<script src="https://cpwebassets.codepen.io/assets/common/stopExecutionOnTimeout-2c7831bb44f98c1391d6a4ffda0e1fd302503391ca806e7fcc7b9b87197aec26.js"></script>
<script id="rendered-js" type="module">
/* Poly Heart model by Quaternius [CC0] (https://creativecommons.org/publicdomain/zero/1.0/) via Poly Pizza (https://poly.pizza/m/1yCRUwFnwX)
*/
import * as THREE from "https://cdn.skypack.dev/three@0.135.0";
import { gsap } from "https://cdn.skypack.dev/gsap@3.8.0";
import { GLTFLoader } from "https://cdn.skypack.dev/three@0.135.0/examples/jsm/loaders/GLTFLoader";
class World {
constructor({
canvas,
width,
height,
cameraPosition,
fieldOfView = 75,
nearPlane = 0.1,
farPlane = 100 })
{
this.parameters = {
count: 1500,
max: 12.5 * Math.PI,
a: 2,
c: 4.5 };
this.textureLoader = new THREE.TextureLoader();
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0x16000a);
this.clock = new THREE.Clock();
this.data = 0;
this.time = { current: 0, t0: 0, t1: 0, t: 0, frequency: 0.0005 };
this.angle = { x: 0, z: 0 };
this.width = width || window.innerWidth;
this.height = height || window.innerHeight;
this.aspectRatio = this.width / this.height;
this.fieldOfView = fieldOfView;
this.camera = new THREE.PerspectiveCamera(
fieldOfView,
this.aspectRatio,
nearPlane,
farPlane);
this.camera.position.set(
cameraPosition.x,
cameraPosition.y,
cameraPosition.z);
this.scene.add(this.camera);
this.renderer = new THREE.WebGLRenderer({
canvas,
antialias: true });
this.pixelRatio = Math.min(window.devicePixelRatio, 2);
this.renderer.setPixelRatio(this.pixelRatio);
this.renderer.setSize(this.width, this.height);
this.timer = 0;
this.addToScene();
this.addButton();
this.render();
this.listenToResize();
this.listenToMouseMove();
}
start() {}
render() {
this.renderer.render(this.scene, this.camera);
this.composer && this.composer.render();
}
loop() {
this.time.elapsed = this.clock.getElapsedTime();
this.time.delta = Math.min(
60,
(this.time.current - this.time.elapsed) * 1000);
if (this.analyser && this.isRunning) {
this.time.t = this.time.elapsed - this.time.t0 + this.time.t1;
this.data = this.analyser.getAverageFrequency();
this.data *= this.data / 2000;
this.angle.x += this.time.delta * 0.001 * 0.63;
this.angle.z += this.time.delta * 0.001 * 0.39;
const justFinished = this.isRunning && !this.sound.isPlaying;
if (justFinished) {
this.time.t1 = this.time.t;
this.audioBtn.disabled = false;
this.isRunning = false;
const tl = gsap.timeline();
this.angle.x = 0;
this.angle.z = 0;
tl.to(this.camera.position, {
x: 0,
z: 4.5,
duration: 4,
ease: "expo.in" });
tl.to(this.audioBtn, {
opacity: () => 1,
duration: 1,
ease: "power1.out" });
} else {
this.camera.position.x = Math.sin(this.angle.x) * this.parameters.a;
this.camera.position.z = Math.min(
Math.max(Math.cos(this.angle.z) * this.parameters.c, 1.75),
6.5);
}
}
this.camera.lookAt(this.scene.position);
if (this.heartMaterial) {
this.heartMaterial.uniforms.uTime.value +=
this.time.delta * this.time.frequency * (1 + this.data * 0.2);
}
if (this.model) {
this.model.rotation.y -= 0.0005 * this.time.delta * (1 + this.data);
}
if (this.snowMaterial) {
this.snowMaterial.uniforms.uTime.value +=
this.time.delta * 0.0004 * (1 + this.data);
}
this.render();
this.time.current = this.time.elapsed;
requestAnimationFrame(this.loop.bind(this));
}
listenToResize() {
window.addEventListener("resize", () => {
// Update sizes
this.width = window.innerWidth;
this.height = window.innerHeight;
// Update camera
this.camera.aspect = this.width / this.height;
this.camera.updateProjectionMatrix();
this.renderer.setSize(this.width, this.height);
});
}
listenToMouseMove() {
window.addEventListener("mousemove", e => {
const x = e.clientX;
const y = e.clientY;
gsap.to(this.camera.position, {
x: gsap.utils.mapRange(0, window.innerWidth, 0.2, -0.2, x),
y: gsap.utils.mapRange(0, window.innerHeight, 0.2, -0.2, -y) });
});
}
addHeart() {
this.heartMaterial = new THREE.ShaderMaterial({
fragmentShader: document.getElementById("fragmentShader").textContent,
vertexShader: document.getElementById("vertexShader").textContent,
uniforms: {
uTime: { value: 0 },
uSize: { value: 0.2 },
uTex: {
value: new THREE.TextureLoader().load(
"https://assets.codepen.io/74321/heart.png") } },
depthWrite: false,
blending: THREE.AdditiveBlending,
transparent: true });
const count = this.parameters.count; //2000
const scales = new Float32Array(count * 1);
const colors = new Float32Array(count * 3);
const speeds = new Float32Array(count);
const randoms = new Float32Array(count);
const randoms1 = new Float32Array(count);
const colorChoices = [
"white",
"red",
"pink",
"crimson",
"hotpink",
"green",
"aquamarine",
"blue"];
const squareGeometry = new THREE.PlaneGeometry(1, 1);
this.instancedGeometry = new THREE.InstancedBufferGeometry();
Object.keys(squareGeometry.attributes).forEach(attr => {
this.instancedGeometry.attributes[attr] = squareGeometry.attributes[attr];
});
this.instancedGeometry.index = squareGeometry.index;
this.instancedGeometry.maxInstancedCount = count;
for (let i = 0; i < count; i++) {
const phi = Math.random() * Math.PI * 2;
const i3 = 3 * i;
randoms[i] = Math.random();
randoms1[i] = Math.random();
scales[i] = Math.random() * 0.35;
const colorIndex = Math.floor(Math.random() * colorChoices.length);
const color = new THREE.Color(colorChoices[colorIndex]);
colors[i3 + 0] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
speeds[i] = Math.random() * this.parameters.max;
}
this.instancedGeometry.setAttribute(
"random",
new THREE.InstancedBufferAttribute(randoms, 1, false));
this.instancedGeometry.setAttribute(
"random1",
new THREE.InstancedBufferAttribute(randoms1, 1, false));
this.instancedGeometry.setAttribute(
"aScale",
new THREE.InstancedBufferAttribute(scales, 1, false));
this.instancedGeometry.setAttribute(
"aSpeed",
new THREE.InstancedBufferAttribute(speeds, 1, false));
this.instancedGeometry.setAttribute(
"aColor",
new THREE.InstancedBufferAttribute(colors, 3, false));
this.heart = new THREE.Mesh(this.instancedGeometry, this.heartMaterial);
console.log(this.heart);
this.scene.add(this.heart);
}
addToScene() {
this.addModel();
this.addHeart();
this.addSnow();
}
async addModel() {
this.model = await this.loadObj(
"https://assets.codepen.io/74321/heart.glb");
this.model.scale.set(0.01, 0.01, 0.01);
this.model.material = new THREE.MeshMatcapMaterial({
matcap: this.textureLoader.load(
"https://assets.codepen.io/74321/3.png",
() => {
gsap.to(this.model.scale, {
x: 0.35,
y: 0.35,
z: 0.35,
duration: 1.5,
ease: "Elastic.easeOut" });
}),
color: "#fff" });
this.scene.add(this.model);
}
addButton() {
this.audioBtn = document.querySelector("button");
this.audioBtn.addEventListener("click", () => {
this.audioBtn.disabled = true;
if (this.analyser) {
this.sound.play();
this.time.t0 = this.time.elapsed;
this.data = 0;
this.isRunning = true;
gsap.to(this.audioBtn, {
opacity: 0,
duration: 1,
ease: "power1.out" });
} else {
this.loadMusic().then(() => {
console.log("music loaded");
});
}
});
}
loadObj(path) {
const loader = new GLTFLoader();
return new Promise(resolve => {
loader.load(
path,
response => {
resolve(response.scene.children[0]);
},
xhr => {},
err => {
console.log(err);
});
});
}
loadMusic() {
return new Promise(resolve => {
const listener = new THREE.AudioListener();
this.camera.add(listener);
// create a global audio source
this.sound = new THREE.Audio(listener);
const audioLoader = new THREE.AudioLoader();
audioLoader.load(
"https://res.cloudinary.com/dmnxeusyw/video/upload/v1668310333/sharecs.net/music_ji3iak.mp3",
buffer => {
this.sound.setBuffer(buffer);
this.sound.setLoop(false);
this.sound.setVolume(0.5);
this.sound.play();
this.analyser = new THREE.AudioAnalyser(this.sound, 32);
// get the average frequency of the sound
const data = this.analyser.getAverageFrequency();
this.isRunning = true;
this.t0 = this.time.elapsed;
resolve(data);
},
progress => {
gsap.to(this.audioBtn, {
opacity: () => 1 - progress.loaded / progress.total,
duration: 1,
ease: "power1.out" });
},
error => {
console.log(error);
});
});
}
addSnow() {
this.snowMaterial = new THREE.ShaderMaterial({
fragmentShader: document.getElementById("fragmentShader1").textContent,
vertexShader: document.getElementById("vertexShader1").textContent,
uniforms: {
uTime: { value: 0 },
uSize: { value: 0.3 },
uTex: {
value: new THREE.TextureLoader().load(
"https://assets.codepen.io/74321/heart.png") } },
depthWrite: false,
blending: THREE.AdditiveBlending,
transparent: true });
const count = 550;
const scales = new Float32Array(count * 1);
const colors = new Float32Array(count * 3);
const phis = new Float32Array(count);
const randoms = new Float32Array(count);
const randoms1 = new Float32Array(count);
const colorChoices = ["red", "pink", "hotpink", "green", "aquamarine", "blue"];
const squareGeometry = new THREE.PlaneGeometry(1, 1);
this.instancedGeometry = new THREE.InstancedBufferGeometry();
Object.keys(squareGeometry.attributes).forEach(attr => {
this.instancedGeometry.attributes[attr] = squareGeometry.attributes[attr];
});
this.instancedGeometry.index = squareGeometry.index;
this.instancedGeometry.maxInstancedCount = count;
for (let i = 0; i < count; i++) {
const phi = (Math.random() - 0.5) * 10;
const i3 = 3 * i;
phis[i] = phi;
randoms[i] = Math.random();
randoms1[i] = Math.random();
scales[i] = Math.random() * 0.35;
const colorIndex = Math.floor(Math.random() * colorChoices.length);
const color = new THREE.Color(colorChoices[colorIndex]);
colors[i3 + 0] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
this.instancedGeometry.setAttribute(
"phi",
new THREE.InstancedBufferAttribute(phis, 1, false));
this.instancedGeometry.setAttribute(
"random",
new THREE.InstancedBufferAttribute(randoms, 1, false));
this.instancedGeometry.setAttribute(
"random1",
new THREE.InstancedBufferAttribute(randoms1, 1, false));
this.instancedGeometry.setAttribute(
"aScale",
new THREE.InstancedBufferAttribute(scales, 1, false));
this.instancedGeometry.setAttribute(
"aColor",
new THREE.InstancedBufferAttribute(colors, 3, false));
this.snow = new THREE.Mesh(this.instancedGeometry, this.snowMaterial);
this.scene.add(this.snow);
}}
const world = new World({
canvas: document.querySelector("canvas.webgl"),
cameraPosition: { x: 0, y: 0, z: 4.5 } });
world.loop();
//# sourceURL=pen.js
</script>
</body>
</html>
Bước 2: Truy cập vào đường link https://www.tutorialspoint.com/online_html_editor.php
Tiếp đến, dán mã nguồn vào khung “Source Code” phía bên trái để thu được thành quả xinh lung linh ở khung kết quả hiển thị phía bên phải màn hình.