HTML CSS JAVASCRIPT canvas particals Star animation

  HTML CSS JAVASCRIPT canvas particles Star  animation 



Source Code

     <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body {
width: 100%;
height: 100vh;
background-color: #000;
background-image: radial-gradient(circle at top right, rgba(121, 68, 154, 0.13), transparent),
radial-gradient(circle at 20% 80%, rgba(41, 196, 255, 0.13), transparent)
}
canvas {
position: fixed;
width: 100%;
height: 100%;
}

a {
position: absolute;
bottom: 2vmin;
right: 2vmin;
color: rgba(255,255,255,0.2);
text-decoration: none;
}

a:hover {
color: #fff;
}
</style>
</head>
<body>
<canvas></canvas>

<script>
/* * . * . * * .
. * move your mouse to over the stars .
* . . change these values: . *
. * . . * . */
const STAR_COLOR = '#fff';
const STAR_SIZE = 3;
const STAR_MIN_SCALE = 0.2;
const OVERFLOW_THRESHOLD = 50;
const STAR_COUNT = ( window.innerWidth + window.innerHeight ) / 8;

const canvas = document.querySelector( 'canvas' ),
context = canvas.getContext( '2d' );

let scale = 1, // device pixel ratio
width,
height;

let stars = [];

let pointerX,
pointerY;

let velocity = { x: 0, y: 0, tx: 0, ty: 0, z: 0.0005 };

let touchInput = false;

generate();
resize();
step();

window.onresize = resize;
canvas.onmousemove = onMouseMove;
canvas.ontouchmove = onTouchMove;
canvas.ontouchend = onMouseLeave;
document.onmouseleave = onMouseLeave;

function generate() {

for( let i = 0; i < STAR_COUNT; i++ ) {
stars.push({
x: 0,
y: 0,
z: STAR_MIN_SCALE + Math.random() * ( 1 - STAR_MIN_SCALE )
});
}

}

function placeStar( star ) {

star.x = Math.random() * width;
star.y = Math.random() * height;

}

function recycleStar( star ) {

let direction = 'z';

let vx = Math.abs( velocity.x ),
vy = Math.abs( velocity.y );

if( vx > 1 || vy > 1 ) {
let axis;

if( vx > vy ) {
axis = Math.random() < vx / ( vx + vy ) ? 'h' : 'v';
}
else {
axis = Math.random() < vy / ( vx + vy ) ? 'v' : 'h';
}

if( axis === 'h' ) {
direction = velocity.x > 0 ? 'l' : 'r';
}
else {
direction = velocity.y > 0 ? 't' : 'b';
}
}

star.z = STAR_MIN_SCALE + Math.random() * ( 1 - STAR_MIN_SCALE );

if( direction === 'z' ) {
star.z = 0.1;
star.x = Math.random() * width;
star.y = Math.random() * height;
}
else if( direction === 'l' ) {
star.x = -OVERFLOW_THRESHOLD;
star.y = height * Math.random();
}
else if( direction === 'r' ) {
star.x = width + OVERFLOW_THRESHOLD;
star.y = height * Math.random();
}
else if( direction === 't' ) {
star.x = width * Math.random();
star.y = -OVERFLOW_THRESHOLD;
}
else if( direction === 'b' ) {
star.x = width * Math.random();
star.y = height + OVERFLOW_THRESHOLD;
}

}

function resize() {

scale = window.devicePixelRatio || 1;

width = window.innerWidth * scale;
height = window.innerHeight * scale;

canvas.width = width;
canvas.height = height;

stars.forEach( placeStar );

}

function step() {

context.clearRect( 0, 0, width, height );

update();
render();

requestAnimationFrame( step );

}

function update() {

velocity.tx *= 0.96;
velocity.ty *= 0.96;

velocity.x += ( velocity.tx - velocity.x ) * 0.8;
velocity.y += ( velocity.ty - velocity.y ) * 0.8;

stars.forEach( ( star ) => {

star.x += velocity.x * star.z;
star.y += velocity.y * star.z;

star.x += ( star.x - width/2 ) * velocity.z * star.z;
star.y += ( star.y - height/2 ) * velocity.z * star.z;
star.z += velocity.z;

// recycle when out of bounds
if( star.x < -OVERFLOW_THRESHOLD || star.x > width + OVERFLOW_THRESHOLD || star.y < -OVERFLOW_THRESHOLD || star.y > height + OVERFLOW_THRESHOLD ) {
recycleStar( star );
}

} );

}

function render() {

stars.forEach( ( star ) => {

context.beginPath();
context.lineCap = 'round';
context.lineWidth = STAR_SIZE * star.z * scale;
context.globalAlpha = 0.5 + 0.5*Math.random();
context.strokeStyle = STAR_COLOR;

context.beginPath();
context.moveTo( star.x, star.y );

var tailX = velocity.x * 2,
tailY = velocity.y * 2;

// stroke() wont work on an invisible line
if( Math.abs( tailX ) < 0.1 ) tailX = 0.5;
if( Math.abs( tailY ) < 0.1 ) tailY = 0.5;

context.lineTo( star.x + tailX, star.y + tailY );

context.stroke();

} );

}

function movePointer( x, y ) {

if( typeof pointerX === 'number' && typeof pointerY === 'number' ) {

let ox = x - pointerX,
oy = y - pointerY;

velocity.tx = velocity.tx + ( ox / 8*scale ) * ( touchInput ? 1 : -1 );
velocity.ty = velocity.ty + ( oy / 8*scale ) * ( touchInput ? 1 : -1 );

}

pointerX = x;
pointerY = y;

}

function onMouseMove( event ) {

touchInput = false;

movePointer( event.clientX, event.clientY );

}

function onTouchMove( event ) {

touchInput = true;

movePointer( event.touches[0].clientX, event.touches[0].clientY, true );

event.preventDefault();

}

function onMouseLeave() {

pointerX = null;
pointerY = null;

}

</script>
</body>
</html>

Comments

Popular posts from this blog