<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><defs><filter id="a" x="-.08" width="1.16" y="-.076" height="1.152" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="2.532"/></filter></defs><path d="M84.732 103.394l-2.143-4.376-1.25-1.34-.715-1.07-1.07-.804-2.412-6.608-1.34-2.41-1.34-2.322-.267-1.785.268-1.34.715-2.68.445-.98.98-2.77.002-.624-.178-.536.802-3.84.357-6.25.535-3.214.625-2.053.625-.714 1.25-1.162 3.482-2.143 2.59-1.786.982-1.608.356-1.428-.18-1.16-.535-1.073-.802-.624-.893-.446-1.16-.536-.447-.535-.267-.716v-.803l-.268-.714-.446-.178-.536-.09h-.536l-.268-.267.18-.267.178-.536.178-.714-.357-.625-.536-.357-.715-.356-.625-.18-.446-.445-.268-.448-.09-.357v-.446l.536-.894.357-.804-.035-.632-.253-.568-.568-.568-.758-.316-1.2-.252-1.325-.253-.946-.252-1.263-.315-.946-.316-1.073-.127-.694-.063-.38-.126-.314-.188-.505-.002-.505-.126-.632-.568-.82-.82-.82-1.138-.19-.757-.316-.316-.82-.506-.57-.568-.567-1.263-.632-1.64-.82-.76-1.705-1.45-.947-.38-.38-.442-.504-.378-1.58-.63-2.335.062-2.21.316-1.326.38-1.39-.064-.568.312-1.137.003-.568.127-.442.632.063-.57-.568.064-.505.442-1.073.505-.947.19-.82.316-.317.252-.757.127-1.514.19-.695.44-.567.064-.82.252-.632.505-1.01.694-1.01 1.074-1.388.82-1.768 1.39-1.263.758.064-.695-.442.505-1.452 1.642-1.768 2.4-2.21 2.524-1.325 2.463-1.263 2.78-1.39 3.47L21.34 48.8l-1.01 3.472-.885 4.735-.063 1.894-.315 2.21.315 1.072.063 1.452-.063 1.453-.505 1.83-1.2 5.114-1.893 4.673-2.02 5.935-.948 2.588-.884 6.82v1.45l.19 1.453 1.01 2.903.694 1.58.947 3.78z" fill="#2b3e47" fill-rule="evenodd" filter="url(#a)"/></svg>
<canvas id="canvas" width="100" height="100"></canvas>
@import url('https://rsms.me/inter/inter-ui.css');
body {
background:
linear-gradient(
limegreen,
transparent
),
linear-gradient(
90deg,
skyblue,
transparent
),
linear-gradient(
-90deg,
coral,
transparent
);
background-blend-mode: screen;
height: 100vh;
margin: 0;
position: relative;
}
svg,
canvas {
bottom: 0;
height: 100vmin;
margin-left: calc(50% - 50vmin);
position: absolute;
width: 100vmin;
}
canvas {
background: #555;
-webkit-clip-path: polygon(82.95% 100%,82.59% 99.02%,81.34% 97.68%,80.63% 96.61%,79.56% 95.81%,77.15% 89.2%,75.81% 86.79%,74.47% 84.47%,74.2% 82.68%,74.47% 81.34%,75.18% 78.66%,75.63% 77.68%,76.61% 74.91%,76.61% 74.28%,76.43% 73.74%,77.23% 69.9%,77.59% 63.65%,78.13% 60.44%,78.76% 58.39%,79.39% 57.68%,80.64% 56.52%,84.12% 54.38%,86.71% 52.59%,87.69% 50.98%,88.05% 49.55%,87.87% 48.39%,87.33% 47.32%,86.53% 46.69%,85.64% 46.24%,84.48% 45.7%,84.03% 45.16%,83.76% 44.45%,83.76% 43.65%,83.49% 42.94%,83.04% 42.76%,82.5% 42.67%,81.96% 42.67%,81.69% 42.4%,81.87% 42.13%,82.05% 41.59%,82.23% 40.88%,81.87% 40.25%,81.33% 39.89%,80.62% 39.53%,79.99% 39.35%,79.54% 38.9%,79.27% 38.45%,79.18% 38.09%,79.18% 37.64%,79.72% 36.75%,80.08% 35.95%,80.05% 35.32%,79.8% 34.75%,79.23% 34.18%,78.47% 33.86%,77.27% 33.61%,75.94% 33.36%,74.99% 33.11%,73.73% 32.79%,72.78% 32.47%,71.71% 32.34%,71.02% 32.28%,70.64% 32.15%,70.32% 31.96%,69.81% 31.96%,69.3% 31.83%,68.67% 31.26%,67.85% 30.44%,67.03% 29.3%,66.84% 28.54%,66.52% 28.22%,65.7% 27.71%,65.13% 27.14%,64.56% 25.88%,63.93% 24.24%,63.11% 23.48%,61.41% 22.03%,60.46% 21.65%,60.08% 21.21%,59.57% 20.83%,57.99% 20.2%,55.65% 20.26%,53.44% 20.58%,52.11% 20.96%,50.72% 20.9%,50.15% 21.21%,49.01% 21.21%,48.44% 21.34%,48% 21.97%,48.06% 21.4%,47.49% 21.46%,46.98% 21.9%,45.91% 22.41%,44.96% 22.6%,44.14% 22.92%,43.82% 23.17%,43.06% 23.3%,41.54% 23.49%,40.85% 23.93%,40.28% 23.99%,39.46% 24.24%,38.83% 24.75%,37.82% 25.44%,36.81% 26.51%,35.42% 27.33%,33.65% 28.72%,32.39% 29.48%,32.45% 28.79%,32.01% 29.3%,30.56% 30.94%,28.79% 33.34%,26.58% 35.87%,25.25% 38.33%,23.99% 41.11%,22.6% 44.58%,21.27% 48.75%,20.26% 52.22%,19.38% 56.96%,19.32% 58.85%,19% 61.06%,19.32% 62.13%,19.38% 63.58%,19.32% 65.03%,18.81% 66.86%,17.61% 71.97%,15.72% 76.64%,13.7% 82.57%,12.75% 85.16%,11.87% 91.98%,11.87% 93.43%,12.06% 94.88%,13.07% 97.78%,13.76% 99.36%,14.71% 99.93%);
clip-path: polygon(82.95% 100%,82.59% 99.02%,81.34% 97.68%,80.63% 96.61%,79.56% 95.81%,77.15% 89.2%,75.81% 86.79%,74.47% 84.47%,74.2% 82.68%,74.47% 81.34%,75.18% 78.66%,75.63% 77.68%,76.61% 74.91%,76.61% 74.28%,76.43% 73.74%,77.23% 69.9%,77.59% 63.65%,78.13% 60.44%,78.76% 58.39%,79.39% 57.68%,80.64% 56.52%,84.12% 54.38%,86.71% 52.59%,87.69% 50.98%,88.05% 49.55%,87.87% 48.39%,87.33% 47.32%,86.53% 46.69%,85.64% 46.24%,84.48% 45.7%,84.03% 45.16%,83.76% 44.45%,83.76% 43.65%,83.49% 42.94%,83.04% 42.76%,82.5% 42.67%,81.96% 42.67%,81.69% 42.4%,81.87% 42.13%,82.05% 41.59%,82.23% 40.88%,81.87% 40.25%,81.33% 39.89%,80.62% 39.53%,79.99% 39.35%,79.54% 38.9%,79.27% 38.45%,79.18% 38.09%,79.18% 37.64%,79.72% 36.75%,80.08% 35.95%,80.05% 35.32%,79.8% 34.75%,79.23% 34.18%,78.47% 33.86%,77.27% 33.61%,75.94% 33.36%,74.99% 33.11%,73.73% 32.79%,72.78% 32.47%,71.71% 32.34%,71.02% 32.28%,70.64% 32.15%,70.32% 31.96%,69.81% 31.96%,69.3% 31.83%,68.67% 31.26%,67.85% 30.44%,67.03% 29.3%,66.84% 28.54%,66.52% 28.22%,65.7% 27.71%,65.13% 27.14%,64.56% 25.88%,63.93% 24.24%,63.11% 23.48%,61.41% 22.03%,60.46% 21.65%,60.08% 21.21%,59.57% 20.83%,57.99% 20.2%,55.65% 20.26%,53.44% 20.58%,52.11% 20.96%,50.72% 20.9%,50.15% 21.21%,49.01% 21.21%,48.44% 21.34%,48% 21.97%,48.06% 21.4%,47.49% 21.46%,46.98% 21.9%,45.91% 22.41%,44.96% 22.6%,44.14% 22.92%,43.82% 23.17%,43.06% 23.3%,41.54% 23.49%,40.85% 23.93%,40.28% 23.99%,39.46% 24.24%,38.83% 24.75%,37.82% 25.44%,36.81% 26.51%,35.42% 27.33%,33.65% 28.72%,32.39% 29.48%,32.45% 28.79%,32.01% 29.3%,30.56% 30.94%,28.79% 33.34%,26.58% 35.87%,25.25% 38.33%,23.99% 41.11%,22.6% 44.58%,21.27% 48.75%,20.26% 52.22%,19.38% 56.96%,19.32% 58.85%,19% 61.06%,19.32% 62.13%,19.38% 63.58%,19.32% 65.03%,18.81% 66.86%,17.61% 71.97%,15.72% 76.64%,13.7% 82.57%,12.75% 85.16%,11.87% 91.98%,11.87% 93.43%,12.06% 94.88%,13.07% 97.78%,13.76% 99.36%,14.71% 99.93%);
}
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let width, height;
let forces = [], particles = [];
let nParticles = 250;
let p = 0;
noise.seed(Math.random());
class V2 {
constructor(x, y) {
this.x = x || 0;
this.y = y || 0;
}
add(vector) {
this.x += vector.x;
this.y += vector.y;
}
reset(x, y) {
this.x = x;
this.y = y;
}
lerp(vector, n) {
this.x += (vector.x - this.x)*n;
this.y += (vector.y - this.y)*n;
}
}
class Particle {
constructor(x,y) {
this.position = new V2(-100,-100);
this.velocity = new V2();
this.acceleration = new V2();
this.alpha = 0;
this.color = '#000000';
this.points = [new V2(-10 + Math.random()*400, -10 + Math.random()*400),
new V2(-10 + Math.random()*400, -10 + Math.random()*400),
new V2(-10 + Math.random()*400, -10 + Math.random()*400)];
}
update() {
this.velocity.add(this.acceleration);
this.position.add(this.velocity);
this.acceleration.reset(0,0);
this.alpha -= 0.01;
if (this.alpha < 0) this.alpha = 0;
}
follow() {
var x = Math.floor(this.position.x / 20);
var y = Math.floor(this.position.y / 20);
var index = x * Math.floor(height/20) + y;
var force = forces[index];
if (force) this.applyForce(force);
}
applyForce(force) {
this.acceleration.add(force);
}
draw() {
ctx.globalAlpha = this.alpha;
ctx.beginPath();
ctx.moveTo(this.position.x+this.points[0].x, this.position.y+this.points[0].y);
ctx.lineTo(this.position.x+this.points[1].x, this.position.y+this.points[1].y);
ctx.lineTo(this.position.x+this.points[2].x, this.position.y+this.points[2].y);
ctx.closePath();
ctx.fillStyle = this.color;
ctx.fill();
}
}
const resize = () => {
mouse = new V2(window.innerHeight/2, window.innerHeight/2);
emitter = new V2(window.innerHeight/2, window.innerHeight/2);
width = window.innerHeight;
height = window.innerHeight;
canvas.width = width;
canvas.height = height;
initForces();
}
const initForces = () => {
var i = 0;
for (var x = 0; x < width; x+=20) {
for (var y = 0; y < height; y+=20) {
if (!forces[i]) forces[i] = new V2();
i++;
}
}
if (i < forces.length) {
forces.splice(i+1);
}
}
const updateForces = (t) => {
var i = 0;
var xOff = 0, yOff = 0;
for (var x = 0; x < width; x+=20) {
xOff += 0.2;
for (var y = 0; y < height; y+=20) {
yOff += 0.2;
let a = noise.perlin3(xOff, yOff, t*0.005) * Math.PI * 4;
if (forces[i]) forces[i].reset(Math.cos(a)*0.1, Math.sin(a)*0.1);
i++;
}
}
}
const initParticles = () => {
for (var i = 0; i < nParticles; i++) {
particles.push(new Particle(Math.random()*width, Math.random()*height));
particles[i].velocity.y = 0.1;
}
}
const drawParticles = () => {
for (var i = 0; i < nParticles; i++) {
particles[i].update();
particles[i].follow();
particles[i].draw();
}
}
const launchParticle = () => {
particles[p].position.reset(emitter.x * 1.5, emitter.y - window.innerHeight/2 + Math.random()*window.innerHeight);
particles[p].velocity.reset(-6+ Math.random()*2, -1+Math.random()*2);
const myArray = ['#F55632', '#1D3132', '#F5DEB3', '#F5DEB3', 'grey', 'blue']
var randColor = myArray[Math.floor(Math.random() * myArray.length)];
particles[p].color = randColor;
particles[p].alpha = 1;
p++;
if (p === nParticles) p = 0;
}
const updateEmitter = () => {
emitter.lerp(mouse, 0.2);
}
const animate = (t) => {
ctx.clearRect(0, 0, width, height);
updateEmitter();
launchParticle();
launchParticle();
launchParticle();
updateForces(t);
drawParticles();
requestAnimationFrame(animate);
}
let mouse;
let emitter;
resize();
initParticles();
requestAnimationFrame(animate);
window.addEventListener('resize', resize);
Also see: Tab Triggers