admin管理员组文章数量:1336752
I need help to apply the water effect which is fading like the below image. In the image the white particles are fading to blue blurry effect. This is what I am trying to achieve.
I believe with fast blur or simplex-noise we should be able to achieve this, but not sure how to proceed.
(click to enlarge)
Achieved the water fall with splinters in HTML5 canvas.
CodePen Source
const canvas = document.getElementById('fountainCanvas');
const ctx = canvas.getContext('2d');
// Set canvas size
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const particles = [];
const splinters = [];
const gravity = 0.1; // Gravity constant
const fountainX = canvas.width / 2;
const fountainY = canvas.height / 2;
// Mouse position
let mouseX = fountainX;
let mouseY = fountainY;
// Particle class
class Particle {
constructor(x, y, angle, isSplinter = false) {
this.x = x;
this.y = y;
const speed = Math.random() * 3 + 2; // Random speed
const spread = Math.random() * 0.4 - 0.2; // Randomize direction slightly
this.vx = isSplinter ?
(Math.random() * 2 - 1) * 3 :
Math.cos(angle + spread) * speed;
this.vy = isSplinter ?
Math.random() * -3 :
Math.sin(angle + spread) * speed;
this.alpha = isSplinter ? 1 : 1; // Opacity
this.radius = isSplinter ? Math.random() : Math.random() + 1; // Size
this.isSplinter = isSplinter;
}
update() {
this.x += this.vx;
this.y += this.vy;
this.vy += gravity; // Apply gravity
this.alpha -= this.isSplinter ? 0.02 : 0.005; // Fade out
// Check if main particles reach the bottom of the canvas
if (!this.isSplinter && this.y >= canvas.height) {
this.createSplinters(); // Create splinters on impact
this.alpha = 0; // Make particle invisible
}
}
createSplinters() {
for (let i = 0; i < 10; i++) {
splinters.push(new Particle(this.x, canvas.height, 0, true));
}
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = `hsla(199, 100%, 67%, ${this.alpha})`; // Blue shade with opacity
ctx.fill();
}
isAlive() {
return this.alpha > 0; // Check if particle is still visible
}
}
// Create particles over time
function emitParticles() {
const angle = Math.atan2(mouseY - fountainY, mouseX - fountainX);
for (let i = 0; i < 5; i++) { // Emit a few particles per frame
particles.push(new Particle(fountainX, fountainY, angle));
}
}
// Animation loop
function animate() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.2)'; // Trail effect
ctx.fillRect(0, 0, canvas.width, canvas.height);
emitParticles(); // Emit new particles continuously
// Update and draw particles
particles.forEach((particle, index) => {
particle.update();
if (!particle.isAlive()) {
particles.splice(index, 1); // Remove dead particles
} else {
particle.draw();
}
});
// Update and draw splinters
splinters.forEach((splinter, index) => {
splinter.update();
if (!splinter.isAlive()) {
splinters.splice(index, 1); // Remove dead splinters
} else {
splinter.draw();
}
});
requestAnimationFrame(animate);
}
// Update mouse position on move
canvas.addEventListener('mousemove', (event) => {
mouseX = event.clientX;
mouseY = event.clientY;
});
// Initialize animation
animate();
canvas {
display: block;
margin: 0 auto;
background: #000;
/* Black background */
}
<canvas id="fountainCanvas"></canvas>
I need help to apply the water effect which is fading like the below image. In the image the white particles are fading to blue blurry effect. This is what I am trying to achieve.
I believe with fast blur or simplex-noise we should be able to achieve this, but not sure how to proceed.
(click to enlarge)
Achieved the water fall with splinters in HTML5 canvas.
CodePen Source
const canvas = document.getElementById('fountainCanvas');
const ctx = canvas.getContext('2d');
// Set canvas size
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const particles = [];
const splinters = [];
const gravity = 0.1; // Gravity constant
const fountainX = canvas.width / 2;
const fountainY = canvas.height / 2;
// Mouse position
let mouseX = fountainX;
let mouseY = fountainY;
// Particle class
class Particle {
constructor(x, y, angle, isSplinter = false) {
this.x = x;
this.y = y;
const speed = Math.random() * 3 + 2; // Random speed
const spread = Math.random() * 0.4 - 0.2; // Randomize direction slightly
this.vx = isSplinter ?
(Math.random() * 2 - 1) * 3 :
Math.cos(angle + spread) * speed;
this.vy = isSplinter ?
Math.random() * -3 :
Math.sin(angle + spread) * speed;
this.alpha = isSplinter ? 1 : 1; // Opacity
this.radius = isSplinter ? Math.random() : Math.random() + 1; // Size
this.isSplinter = isSplinter;
}
update() {
this.x += this.vx;
this.y += this.vy;
this.vy += gravity; // Apply gravity
this.alpha -= this.isSplinter ? 0.02 : 0.005; // Fade out
// Check if main particles reach the bottom of the canvas
if (!this.isSplinter && this.y >= canvas.height) {
this.createSplinters(); // Create splinters on impact
this.alpha = 0; // Make particle invisible
}
}
createSplinters() {
for (let i = 0; i < 10; i++) {
splinters.push(new Particle(this.x, canvas.height, 0, true));
}
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = `hsla(199, 100%, 67%, ${this.alpha})`; // Blue shade with opacity
ctx.fill();
}
isAlive() {
return this.alpha > 0; // Check if particle is still visible
}
}
// Create particles over time
function emitParticles() {
const angle = Math.atan2(mouseY - fountainY, mouseX - fountainX);
for (let i = 0; i < 5; i++) { // Emit a few particles per frame
particles.push(new Particle(fountainX, fountainY, angle));
}
}
// Animation loop
function animate() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.2)'; // Trail effect
ctx.fillRect(0, 0, canvas.width, canvas.height);
emitParticles(); // Emit new particles continuously
// Update and draw particles
particles.forEach((particle, index) => {
particle.update();
if (!particle.isAlive()) {
particles.splice(index, 1); // Remove dead particles
} else {
particle.draw();
}
});
// Update and draw splinters
splinters.forEach((splinter, index) => {
splinter.update();
if (!splinter.isAlive()) {
splinters.splice(index, 1); // Remove dead splinters
} else {
splinter.draw();
}
});
requestAnimationFrame(animate);
}
// Update mouse position on move
canvas.addEventListener('mousemove', (event) => {
mouseX = event.clientX;
mouseY = event.clientY;
});
// Initialize animation
animate();
canvas {
display: block;
margin: 0 auto;
background: #000;
/* Black background */
}
<canvas id="fountainCanvas"></canvas>
Share
edited Nov 27, 2024 at 14:33
DarkBee
15.5k8 gold badges72 silver badges117 bronze badges
asked Nov 19, 2024 at 18:23
satyanarayan mishrasatyanarayan mishra
1096 bronze badges
4
|
3 Answers
Reset to default 1Working on the effect
https://codepen.io/satya4satyanm/pen/YPKwBQV?editors=1010
Need to fix the gravity in this.
<div style="top: 50px; text-align:center">
<canvas id="canvasOne" width="640" height="640">
Your browser does not support HTML5 canvas.
</canvas>
<script src="https://dangries/rectangleworld/demos/Modernizr/modernizr-2.0.6.js"></script>
<script src="https://dangries/rectangleworld/demos/Nova_Canvas/FastBlur.js"></script>
<script>
/*
Particle effect by Dan Gries, rectangleworld.
The FastBlur is created by Mario Klingemann, quasimondo. Sincere thanks to Mario for publicly sharing the code!
*/
//for debug messages
window.addEventListener("load", windowLoadHandler, false);
var Debugger = function() {};
Debugger.log = function(message) {
try {
console.log(message);
} catch (exception) {
return;
}
}
function windowLoadHandler() {
canvasApp();
}
function canvasSupport() {
return Modernizr.canvas;
}
function canvasApp() {
if (!canvasSupport()) {
return;
}
var theCanvas = document.getElementById("canvasOne");
var context = theCanvas.getContext("2d");
var timer;
var wait;
var count;
var particleList;
var recycleBin;
var emitX;
var emitY;
var displayWidth;
var displayHeight;
var particleAlpha;
var baseColorR;
var baseColorG;
var baseColorB;
var r;
var g;
var b;
var phaseR;
var phaseG;
var phaseB;
var targetPhaseR;
var targetPhaseG;
var targetPhaseB;
var lastTargetPhaseR;
var lastTargetPhaseG;
var lastTargetPhaseB;
var phaseShiftDuration;
var phaseShiftCount;
var particleColor;
var numToAddEachFrame;
var gravity = 3;
init();
function init() {
bgColor = "#000000";
context.fillStyle = bgColor;
context.fillRect(0, 0, theCanvas.width, theCanvas.height);
wait = 1;
count = wait - 1;
numToAddEachFrame = 2;
particleAlpha = 1;
targetPhaseR = 4;
targetPhaseG = 3;
targetPhaseB = 0;
phaseShiftDuration = 2000;
phaseShiftCount = phaseShiftDuration - 1;
displayWidth = theCanvas.width;
displayHeight = theCanvas.height;
emitX = 100;//displayWidth / 2;
emitY = 100;//displayHeight / 2;
particleList = {};
recycleBin = {};
timer = setInterval(onTimer, 1000 / 24);
}
function onTimer() {
count++;
if (count >= wait) {
var time = Date.now();
r = 50;
g = 135;
b = 168;
count = 0;
for (i = 0; i < numToAddEachFrame; i++) {
var mag = 1.5 + 0.5 * (Math.random());
var angle = Math.random() / 3 * (Math.PI);
var p = addParticle(emitX, emitY, mag * Math.cos(angle), mag * Math.sin(angle));
p.color = "rgba(" + r + "," + g + "," + b + "," + particleAlpha + ")";
p.setEnvelope(10, 100, 50,
4, 10, 10,
0, 0.4 + 0.8 * Math.random(), 0);
}
}
updateParticles();
drawScreen();
}
Particle.prototype.setEnvelope = function(a, h, d, av, hv, dv, r0, r1, r2) {
this.attack = a + (2 * Math.random() - 1) * av;
this.hold = h + (2 * Math.random() - 1) * hv;
this.decay = d + (2 * Math.random() - 1) * dv;
this.rInit = r0;
this.rHold = r1;
this.rLast = r2;
this.rad = this.rInit;
}
function updateParticles() {
var p = particleList.first;
var outsideTest;
var nextParticle;
while (p != null) {
//before list is altered record next particle
nextParticle = p.next;
//add air resistance later
p.x += p.velX;
p.pvyg = p.velY * gravity;
p.y += p.pvyg;
//update age
p.age++;
//update size
if (p.age < p.attack + p.hold + p.decay) {
if (p.age < p.attack) {
p.rad = (p.rHold - p.rInit) / 15 / p.attack * p.age + p.rInit;
} else if (p.age < p.attack + p.hold) {
p.rad = p.rHold;
} else if (p.age < p.attack + p.hold + p.decay) {
p.rad = (p.rLast - p.rHold) / 15 / p.decay * (p.age - p.attack - p.hold) + p.rHold;
}
} else {
p.dead = true;
}
//test if particle is outside of window
outsideTest = (p.x + p.rad < 0) || (p.y + p.rad < 0) || (p.x > displayWidth - p.rad) || (p.y > displayWidth - p.rad);
if (outsideTest || p.dead) {
recycle(p);
}
p = nextParticle;
}
}
function Particle() {
//The particle class does not need anything in the constructor. Properties will be added dynamically.
//This class is being used ony for anizational purposes - the "setEnvelope" function is attached to the prototype object
//later.
}
function addParticle(x0, y0, vx0, vy0) {
var newParticle;
var color;
//check recycle bin for available drop:
if (recycleBin.first != null) {
newParticle = recycleBin.first;
//remove from bin
if (newParticle.next != null) {
recycleBin.first = newParticle.next;
newParticle.next.prev = null;
} else {
recycleBin.first = null;
}
}
//if the recycle bin is empty, create a new particle:
else {
newParticle = new Particle();
}
//add to beginning of particle list
if (particleList.first == null) {
particleList.first = newParticle;
newParticle.prev = null;
newParticle.next = null;
} else {
newParticle.next = particleList.first;
particleList.first.prev = newParticle;
particleList.first = newParticle;
newParticle.prev = null;
}
//initialize
newParticle.x = x0;
newParticle.y = y0;
newParticle.velX = vx0;
newParticle.velY = vy0;
newParticle.color = color;
newParticle.age = 0;
newParticle.dead = false;
return newParticle;
}
function recycle(p) {
//remove from particleList
if (particleList.first == p) {
if (p.next != null) {
p.next.prev = null;
particleList.first = p.next;
} else {
particleList.first = null;
}
} else {
if (p.next == null) {
p.prev.next = null;
} else {
p.prev.next = p.next;
p.next.prev = p.prev;
}
}
//add to recycle bin
if (recycleBin.first == null) {
recycleBin.first = p;
p.prev = null; //may be unnecessary
p.next = null;
} else {
p.next = recycleBin.first;
recycleBin.first.prev = p; //may be unnecessary
recycleBin.first = p;
p.prev = null; //may be unnecessary
}
//reset accel
}
function drawScreen() {
//stack blur by Mario Klingemann, quasimondo
boxBlurCanvasRGB("canvasOne", 0, 0, theCanvas.width, theCanvas.height, 2);
var p = particleList.first;
var pcount = 0;
while (p != null) {
pcount++;
context.fillStyle = p.color;
context.beginPath();
context.arc(p.x, p.y, p.rad, 0, 2 * Math.PI, false);
context.closePath();
context.fill();
p = p.next;
}
}
}
</script>
In your code you fade the particles with the alpha:
ctx.fillStyle = `hsla(199, 100%, 67%, ${this.alpha})`;
But your background is black so the fade is from blue to black
If you want to create the illusion of fading from one color to another, you can draw two arc
on the exact same location but the first one do it with a different color while that will be on the background, and should create the experience you are looking for...
const canvas = document.getElementById('fountainCanvas');
const ctx = canvas.getContext('2d');
var particles = []
class Particle {
constructor(x, y) {
this.x = x;
this.y = y;
this.alpha = 1;
}
draw() {
this.alpha -= 0.005;
ctx.beginPath();
ctx.arc(this.x, this.y, 15, 0, Math.PI * 2);
ctx.fillStyle = `red`;
ctx.fill();
ctx.beginPath();
ctx.arc(this.x, this.y, 15, 0, Math.PI * 2);
ctx.fillStyle = `hsla(199, 100%, 67%, ${this.alpha})`;
ctx.fill();
}
}
function emitParticles() {
particles= []
for (let i = 2; i < 7; i++) {
particles.push(new Particle(35*i, 20+10*i));
}
}
function animate() {
ctx.reset();
particles.forEach(p => p.draw());
requestAnimationFrame(animate);
}
setInterval(emitParticles, 4000)
emitParticles()
animate();
canvas {
display: block;
margin: 0 auto;
background: #000;
/* Black background */
}
<canvas id="fountainCanvas"></canvas>
You can also transition to other colors:
https://www.w3schools/colors/colors_hsl.asp
const canvas = document.getElementById('fountainCanvas');
const ctx = canvas.getContext('2d');
var particles = []
class Particle {
constructor(x, y) {
this.x = x;
this.y = y;
this.alpha = 1;
this.color = 199
}
draw() {
this.alpha -= 0.005;
this.color -= 1;
ctx.beginPath();
ctx.arc(this.x, this.y, 15, 0, Math.PI * 2);
ctx.fillStyle = `hsla(${this.color}, 100%, 67%, ${this.alpha})`;
ctx.fill();
}
}
function emitParticles() {
particles= []
for (let i = 2; i < 7; i++) {
particles.push(new Particle(35*i, 20+10*i));
}
}
function animate() {
ctx.reset();
particles.forEach(p => p.draw());
requestAnimationFrame(animate);
}
setInterval(emitParticles, 4000)
emitParticles()
animate();
canvas {
display: block;
margin: 0 auto;
background: #000;
/* Black background */
}
<canvas id="fountainCanvas"></canvas>
// script.js
const container = document.getElementById("waterfall-container");
function createFallingElement() {
// Create a new div element
const waterfallItem = document.createElement("div");
waterfallItem.classList.add("waterfall-item");
// Set a random horizontal position
const randomX = Math.random() * window.innerWidth;
waterfallItem.style.left = `${randomX}px`;
// Append the element to the container
container.appendChild(waterfallItem);
// Remove the element after animation ends to avoid clutter
waterfallItem.addEventListener("animationend", () => {
container.removeChild(waterfallItem);
});
}
// Create new falling elements every 200ms
setInterval(createFallingElement, 200);
本文标签: javascriptHow to create a waterfall effectStack Overflow
版权声明:本文标题:javascript - How to create a waterfall effect? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742406330a2468896.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
color-mix()
css function, even in the canvas 2D API. – Kaiido Commented Nov 28, 2024 at 1:34