0% found this document useful (0 votes)
32 views9 pages

Heart Animation with Particles

This document defines code for generating and animating particles that move and fade over time to form the shape of a heart within a canvas element. The code initializes settings for particle properties, defines classes for points, particles and particle pools, and includes functions for adding particles, updating their positions and drawing them to the canvas over successive animation frames.

Uploaded by

Hồng Nhật
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
32 views9 pages

Heart Animation with Particles

This document defines code for generating and animating particles that move and fade over time to form the shape of a heart within a canvas element. The code initializes settings for particle properties, defines classes for points, particles and particle pools, and includes functions for adding particles, updating their positions and drawing them to the canvas over successive animation frames.

Uploaded by

Hồng Nhật
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

<!

DOCT
YPE
HTML
PUBL
IC
"-//
W3C/
/DTD
HTML
4.0
Tran
siti
onal
//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="[Link]">
<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<[Link]&&!
[Link];++a){[Link]=window[c[a]
+"RequestAnimationFrame"];[Link]=window[c[a]
+"CancelAnimationFrame"]||window[c[a]+"CancelRequestAnimationFrame"]}if(!
[Link]){[Link]=function(h,e){var d=new
Date().getTime();var f=[Link](0,16-(d-b));var g=[Link](function()
{h(d+f)},f);b=d+f;return g}}if(![Link])
{[Link]=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;
}
[Link] = function() {
return new Point(this.x, this.y);
};
[Link] = function(length) {
if (typeof length == 'undefined')
return [Link](this.x * this.x + this.y * this.y);
[Link]();
this.x *= length;
this.y *= length;
return this;
};
[Link] = function() {
var length = [Link]();
this.x /= length;
this.y /= length;
return this;
};
return Point;
})();
/*
* Particle class
*/
var Particle = (function() {
function Particle() {
[Link] = new Point();
[Link] = new Point();
[Link] = new Point();
[Link] = 0;
}
[Link] = function(x, y, dx, dy) {
[Link].x = x;
[Link].y = y;
[Link].x = dx;
[Link].y = dy;
[Link].x = dx * [Link];
[Link].y = dy * [Link];
[Link] = 0;
};
[Link] = function(deltaTime) {
[Link].x += [Link].x * deltaTime;
[Link].y += [Link].y * deltaTime;
[Link].x += [Link].x * deltaTime;
[Link].y += [Link].y * deltaTime;
[Link] += deltaTime;
};
[Link] = function(context, image) {
function ease(t) {
return (--t) * t * t + 1;
}
var size = [Link] * ease([Link] / [Link]);
[Link] = 1 - [Link] / [Link];
[Link](image, [Link].x - size / 2, [Link].y - size /
2, size, size);
};
return Particle;
})();
/*
* ParticlePool class
*/
var ParticlePool = (function() {
var particles,
firstActive = 0,
firstFree = 0,
duration = [Link];

function ParticlePool(length) {
// create and populate particle pool
particles = new Array(length);
for (var i = 0; i < [Link]; i++)
particles[i] = new Particle();
}
[Link] = function(x, y, dx, dy) {
particles[firstFree].initialize(x, y, dx, dy);

// handle circular queue


firstFree++;
if (firstFree == [Link]) firstFree = 0;
if (firstActive == firstFree ) firstActive++;
if (firstActive == [Link]) firstActive = 0;
};
[Link] = 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 < [Link]; 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 == [Link]) firstActive = 0;
}
};
[Link] = 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 < [Link]; 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 = [Link]('2d'),
particles = new ParticlePool([Link]),
particleRate = [Link] / [Link], //
particles/sec
time;

// get point on heart with -PI <= t <= PI


function pointOnHeart(t) {
return new Point(
160 * [Link]([Link](t), 3),
130 * [Link](t) - 50 * [Link](2 * t) - 20 * [Link](3 * t) - 10 *
[Link](4 * t) + 25
);
}

// creating the particle image using a dummy canvas


var image = (function() {
var canvas = [Link]('canvas'),
context = [Link]('2d');
[Link] = [Link];
[Link] = [Link];
// helper function to create the path
function to(t) {
var point = pointOnHeart(t);
point.x = [Link] / 2 + point.x * [Link] /
350;
point.y = [Link] / 2 - point.y * [Link] /
350;
return point;
}
// create the path
[Link]();
var t = -[Link];
var point = to(t);
[Link](point.x, point.y);
while (t < [Link]) {
t += 0.01; // baby steps!
point = to(t);
[Link](point.x, point.y);
}
[Link]();
// create the fill
[Link] = '#f50b02';
[Link]();
// create the image
var image = new Image();
[Link] = [Link]();
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
[Link](0, 0, [Link], [Link]);

// create new particles


var amount = particleRate * deltaTime;
for (var i = 0; i < amount; i++) {
var pos = pointOnHeart([Link] - 2 * [Link] * [Link]());
var dir = [Link]().length([Link]);
[Link]([Link] / 2 + pos.x, [Link] / 2 - pos.y, dir.x, -
dir.y);
}

// update and draw particles


[Link](deltaTime);
[Link](context, image);
}

// handle (re-)sizing of the canvas


function onResize() {
[Link] = [Link];
[Link] = [Link];
}
[Link] = onResize;

// delay rendering bootstrap


setTimeout(function() {
onResize();
render();
}, 10);
})([Link]('pinkboard'));
</script>
</BODY>
</HTML>
body
{
display: flex;
justify-content: center;
align-items: center;
background: #2c3e50
}

.box {
width: 1000px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
}

#pinkboard {
position: relative;
margin: auto;
height: 750px;
width: 750px;
animation: animate 1.2s infinite;
}

#pinkboard:before, #pinkboard:after {
content: '';
position: absolute;
background: #d63031;
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);
}
}

Common questions

Powered by AI

Combining HTML, CSS, and JavaScript results in a robust platform capable of delivering interactive multimedia experiences. HTML structures content and serves as the skeleton for any application. CSS enhances aesthetic appeal through styling and animations, creating complex visual effects with relatively little overhead. JavaScript adds behavioral layers, responding to user interactions and dynamically updating the UI. When effectively utilized, this trio facilitates responsive, engaging web applications. However, the challenge lies in maintaining effective integration, ensuring code optimization, managing assets efficiently, and preserving accessibility across devices. Advanced implementations, as seen in particle animations, showcase the potential while also highlighting the need for careful balancing of resources to ensure smooth performance and compatibility .

In the particle system, JavaScript and CSS interact to produce a visually dynamic and responsive user experience. JavaScript is responsible for the logic, behavior, and dynamic drawing of particles, controlling their motion, birth, lifespan, and how they respond to time. It updates the particle state via animations through requestAnimationFrame, ensuring smooth transitions without blocking rendering. CSS, on the other hand, provides static styles and animations for layout and aesthetic enhancements. Together, they create a synchronized interaction where JavaScript drives functional interactivity while CSS enhances appearance and scaling animations, contributing to an immersive experience that feels fluid and engaging for users .

The techniques used for particle initialization and updates are efficient in establishing a complex simulation environment. Initialization assigns starting positions and velocities, and computes initial accelerations based on direction and predefined settings for realistic motion effects. Updating particles involve calculating their new positions and velocities by applying acceleration over time steps, crucially considering frame deltas for smoother animations irrespective of frame rate deviations. This comprehensive handling ensures predictable animations, while implementation in a pool structure optimizes these processes over potentially vast computing iterations, enhancing performance in real-time execution .

While versatile and visually effective, JavaScript particle systems face limitations, including high computational load due to real-time physics calculations and rendering processes, which can strain low-powered devices. Handling large numbers of particles simultaneously can result in performance bottlenecks, especially if not optimized properly. Another challenge lies in maintaining interactivity without sacrificing frame rate, as the computational demand might compete with other browser tasks, potentially affecting responsiveness. Lastly, cross-browser discrepancies in JavaScript execution and rendering capabilities can introduce inconsistencies without careful browser-specific optimizations .

The behavior and movement of particles change over time due to the influence of velocity, acceleration, and lifespan specific to the environment settings. Particles possess initial velocities, which are altered as they move, due to applied accelerations calculated by multiplying direction with a defined effect factor. These calculations ensure that particles follow a path as defined by the logic for rendering their peculiar motion and effect within a heart-shaped configuration. Over time, particles age, affecting transparency and size when drawn; the transparency decreases linearly, and the size follows a cubic easing function based on age. The cessation of effect as they age out is managed by increasing the firstActive index in the particle pool once a particle's age exceeds its lifespan of the environment .

Dynamic resizing adjusts the canvas dimensions to match the client window size, addressing responsiveness by ensuring content scales appropriately across different screen sizes. This is achieved with an event listener attached to the window resize event that recalibrates canvas width and height. Solving problems associated with static sizing, this approach maintains visual integrity and user experience across various devices, eliminating scroll issues and ensuring content remains centered and proportionate, which is crucial for providing a seamless crossover between differing screen resolutions .

The implementation structure ensures cross-browser compatibility by employing a polyfill for requestAnimationFrame that accommodates older browser prefixes. It checks for vendor-prefixed versions of the function from various browser vendors such as 'ms', 'moz', 'webkit', and 'o'. If the native method is unavailable, a fallback is provided using setTimeout to simulate the behavior of requestAnimationFrame with a delay that approximates a 60 FPS animation. This approach broadens the compatibility spectrum, enabling smooth animations that adjust for existing differences in browser capabilities .

The visual aesthetics of the pinkboard element are enhanced through CSS animations and transformations that introduce dynamic visual changes and depth. The animations use keyframe rules to transition the scale of the element, creating a pulsating effect that draws viewer attention. Transformations, such as translation and rotation combined with shadows and border-radius properties, are applied to pseudo elements (::before and ::after), giving the appearance of three-dimensional curves and depth. These styles mimic a beating heart when animated, creating an engaging visual representation that stands out within the given design space. This approach demonstrates a mastery of CSS to enhance visual storytelling without the need for heavy graphical assets .

The 'ease' function in the rendering process modifies the size of particles over their duration of activity. Specifically, it is used to control the growth and decay of a particle’s size, ensuring a smooth transition effect by using the cubic easing formula (ease(t) = (--t) * t * t + 1). As a particle ages, this function creates a non-linear animation effect by adjusting the particle size, which in turn provides a visually pleasing effect of expansion and contraction as particles 'breathe' within the given lifecycle .

The particle pooling system optimizes performance by reusing particle objects within a fixed-size array, thus reducing the overhead associated with frequently creating and destroying objects. The design uses a circular queue that efficiently manages active particles, allowing new particles to occupy spaces freed by expired ones. This structure conserves memory, reduces garbage collection overhead, and maintains a constant particle count without frequent memory allocation and deallocation actions, which would be computationally expensive and could degrade performance in real-time rendering scenarios. The implications of this design are significant in maintaining consistent frame rates and smooth animations, particularly important in graphic-intensive applications where high efficiency is critical .

You might also like