As on the attached fiddle, the background image on the canvas is just coming and getting disappearing
I tried both createPattern and drawImage both are having same issue.
I am not an expert in Canvas. Any help would be appreciated
(function(){
var canvas = document.getElementById('c'),
/** #type {CanvasRenderingContext2D} */
ctx = canvas.getContext('2d'),
width = 400,
height = 400,
half_width = width >> 1,
half_height = height >> 1,
size = width * (height + 2) * 2,
delay = 30,
oldind = width,
newind = width * (height + 3),
riprad = 3,
ripplemap = [],
last_map = [],
ripple,
texture,
line_width = 20,
step = line_width * 2,
count = height / line_width;
canvas.width = width;
canvas.height = height;
/*
* Water ripple demo can work with any bitmap image
*/
var imageObj = new Image();
imageObj.onload = function() {
var pattern = ctx.createPattern(imageObj, 'repeat');
ctx.rect(0, 0, width, height);
ctx.fillStyle = pattern;
ctx.fill();
ctx.save();
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/wood-pattern.png';
with (ctx) {
fillStyle = '#ccc';
fillRect(0, 0, width, height);
fillStyle = '#999999';
save();
rotate(-0.785);
for (var i = 0; i < count; i++) {
fillRect(-width, i * step, width * 3, line_width);
}
}
texture = ctx.getImageData(0, 0, width, height);
ripple = ctx.getImageData(0, 0, width, height);
for (var i = 0; i < size; i++) {
last_map[i] = ripplemap[i] = 0;
}
/**
* Main loop
*/
function run() {
newframe();
ctx.putImageData(ripple, 0, 0);
}
/**
* Disturb water at specified point
*/
function disturb(dx, dy) {
dx <<= 0;
dy <<= 0;
for (var j = dy - riprad; j < dy + riprad; j++) {
for (var k = dx - riprad; k < dx + riprad; k++) {
ripplemap[oldind + (j * width) + k] += 128;
}
}
}
/**
* Generates new ripples
*/
function newframe() {
var a, b, data, cur_pixel, new_pixel, old_data;
var t = oldind; oldind = newind; newind = t;
var i = 0;
// create local copies of variables to decrease
// scope lookup time in Firefox
var _width = width,
_height = height,
_ripplemap = ripplemap,
_last_map = last_map,
_rd = ripple.data,
_td = texture.data,
_half_width = half_width,
_half_height = half_height;
for (var y = 0; y < _height; y++) {
for (var x = 0; x < _width; x++) {
var _newind = newind + i, _mapind = oldind + i;
data = (
_ripplemap[_mapind - _width] +
_ripplemap[_mapind + _width] +
_ripplemap[_mapind - 1] +
_ripplemap[_mapind + 1]) >> 1;
data -= _ripplemap[_newind];
data -= data >> 5;
_ripplemap[_newind] = data;
//where data=0 then still, where data>0 then wave
data = 1024 - data;
old_data = _last_map[i];
_last_map[i] = data;
if (old_data != data) {
//offsets
a = (((x - _half_width) * data / 1024) << 0) + _half_width;
b = (((y - _half_height) * data / 1024) << 0) + _half_height;
//bounds check
if (a >= _width) a = _width - 1;
if (a < 0) a = 0;
if (b >= _height) b = _height - 1;
if (b < 0) b = 0;
new_pixel = (a + (b * _width)) * 4;
cur_pixel = i * 4;
_rd[cur_pixel] = _td[new_pixel];
_rd[cur_pixel + 1] = _td[new_pixel + 1];
_rd[cur_pixel + 2] = _td[new_pixel + 2];
}
++i;
}
}
}
canvas.onmousemove = function(/* Event */ evt) {
disturb(evt.offsetX || evt.layerX, evt.offsetY || evt.layerY);
};
setInterval(run, delay);
// generate random ripples
var rnd = Math.random;
var timeOut;
var intrvl = setInterval(function() {
clearTimeout(timeOut);
disturb(0, (height/40));
disturb((width/2.67), (height/40));
disturb((width/1.33), (height/40));
disturb(0, (height/2.67));
disturb((width/2.67), (height/2.67));
disturb((width/1.33), (height/2.67));
disturb(0, (height/1.33));
disturb((width/2.67), (height/1.33));
disturb((width/1.33), (height/1.33));
timeOut= setTimeout(function(){
disturb((width/1.8), (height/8));
disturb((width/-1.2), (height/8));
disturb((width/1.14), (height/8));
disturb((width/1.8), (height/2.13));
disturb((width/-1.2), (height/2.13));
disturb((width/1.14), (height/2.13));
disturb((width/1.8), (height/1.03));
disturb((width/-1.2), (height/1.03));
disturb((width/1.14), (height/1.03));;
},300);
}, 700);
setTimeout(function(){
clearInterval(intrvl);
},3000);
})();
this is the link to the fiddle
Related
The code is different, I apologize may I didn't ask the question the right way, you can understand well in principle, When I'm hovering the dots get colours and connect to each other, other dots are invisible, I want that all dots should be visible all time. live example available on codepen, https://codepen.io/tati420/pen/RwBamQo?editors=1111
(function () {
var width,
height,
largeHeader,
canvas,
ctx,
points,
target,
animateHeader = true;
// Main
initHeader();
initAnimation();
addListeners();
function initHeader() {
width = window.innerWidth;
height = window.innerHeight;
target = { x: width / 2, y: height / 2 };
largeHeader = document.getElementById("large-header");
largeHeader.style.height = height + "px";
canvas = document.getElementById("demo-canvas");
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext("2d");
// create points
points = [];
for (var x = 0; x < width; x = x + width / 20) {
for (var y = 0; y < height; y = y + height / 20) {
var px = x + (Math.random() * width) / 20;
var py = y + (Math.random() * height) / 20;
var p = { x: px, originX: px, y: py, originY: py };
points.push(p);
}
}
// for each point find the 5 closest points
for (var i = 0; i < points.length; i++) {
var closest = [];
var p1 = points[i];
for (var j = 0; j < points.length; j++) {
var p2 = points[j];
if (!(p1 == p2)) {
var placed = false;
for (var k = 0; k < 5; k++) {
if (!placed) {
if (closest[k] == undefined) {
closest[k] = p2;
placed = true;
}
}
}
for (var k = 0; k < 5; k++) {
if (!placed) {
if (getDistance(p1, p2) < getDistance(p1, closest[k])) {
closest[k] = p2;
placed = true;
}
}
}
}
}
p1.closest = closest;
}
// assign a circle to each point
for (var i in points) {
var c = new Circle(
points[i],
2 + Math.random() * 2,
"rgba(0,255,255,0.3)"
);
points[i].circle = c;
}
}
// Event handling
function addListeners() {
if (!("ontouchstart" in window)) {
window.addEventListener("mousemove", mouseMove);
}
window.addEventListener("scroll", scrollCheck);
window.addEventListener("resize", resize);
}
function mouseMove(e) {
var posx = (posy = 0);
if (e.pageX || e.pageY) {
posx = e.pageX;
posy = e.pageY;
} else if (e.clientX || e.clientY) {
posx =
e.clientX +
document.body.scrollLeft +
document.documentElement.scrollLeft;
posy =
e.clientY +
document.body.scrollTop +
document.documentElement.scrollTop;
}
target.x = posx;
target.y = posy;
}
function scrollCheck() {
if (document.body.scrollTop > height) animateHeader = false;
else animateHeader = true;
}
function resize() {
width = window.innerWidth;
height = window.innerHeight;
largeHeader.style.height = height + "px";
canvas.width = width;
canvas.height = height;
}
// animation
function initAnimation() {
animate();
for (var i in points) {
shiftPoint(points[i]);
}
}
function animate() {
if (animateHeader) {
ctx.clearRect(0, 0, width, height);
for (var i in points) {
// detect points in range
if (Math.abs(getDistance(target, points[i])) < 4000) {
points[i].active = 0.3;
points[i].circle.active = 0.6;
} else if (Math.abs(getDistance(target, points[i])) < 20000) {
points[i].active = 0.1;
points[i].circle.active = 0.3;
} else if (Math.abs(getDistance(target, points[i])) < 40000) {
points[i].active = 0.02;
points[i].circle.active = 0.1;
} else {
points[i].active = 0;
points[i].circle.active = 0;
}
drawLines(points[i]);
points[i].circle.draw();
}
}
requestAnimationFrame(animate);
}
function shiftPoint(p) {
TweenLite.to(p, 1 + 1 * Math.random(), {
x: p.originX - 50 + Math.random() * 100,
y: p.originY - 50 + Math.random() * 100,
ease: Circ.easeInOut,
onComplete: function () {
shiftPoint(p);
},
});
}
ctx.strokeStyle = "rgba(255,0,0," + p.active + ")";
// Canvas manipulation
function drawLines(p) {
if (!p.active) return;
for (var i in p.closest) {
ctx.beginPath();
ctx.moveTo(p.x, p.y);
ctx.lineTo(p.closest[i].x, p.closest[i].y);
ctx.strokeStyle = "rgba(0,255,255," + p.active + ")";
ctx.stroke();
}
}
function Circle(pos, rad, color) {
var _this = this;
// constructor
(function () {
_this.pos = pos || null;
_this.radius = rad || null;
_this.color = color || null;
})();
this.draw = function () {
if (!_this.active) return;
ctx.beginPath();
ctx.arc(_this.pos.x, _this.pos.y, _this.radius, 0, 2 * Math.PI, false);
ctx.fillStyle = "rgba(0,255,0," + _this.active + ")";
ctx.fill();
};
}
// Util
function getDistance(p1, p2) {
return Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2);
}
})();
If I understand your question correctly, you just want to make sure that every point.active = 1 and point.circle.active = 1:
function animate() {
if (animateHeader) {
ctx.clearRect(0, 0, width, height);
for (var i in points) {
points[i].active = 1;
points[i].circle.active = 1;
drawLines(points[i]);
points[i].circle.draw();
}
}
requestAnimationFrame(animate);
}
I have this working canvas javascript animation but i would like to use it multiple times, currently it's only possible to have one canvas element with the id "stars" and use that one. Could i perhaps add a class for them instead and get the elements class and loop or what would be my best solution for achieving this? I would like to make this work without repeating to much since i could end up using the animation on different pages.
// Settings
var particleCount = 40,
flareCount = 0,
motion = 0.05,
tilt = 0.05,
color = '#00FF7B',
particleSizeBase = 1,
particleSizeMultiplier = 0.5,
flareSizeBase = 100,
flareSizeMultiplier = 100,
lineWidth = 1,
linkChance = 75, // chance per frame of link, higher = smaller chance
linkLengthMin = 5, // min linked vertices
linkLengthMax = 7, // max linked vertices
linkOpacity = 0.25; // number between 0 & 1
linkFade = 90, // link fade-out frames
linkSpeed = 0, // distance a link travels in 1 frame
glareAngle = -60,
glareOpacityMultiplier = 0.4,
renderParticles = true,
renderParticleGlare = true,
renderFlares = false,
renderLinks = false,
renderMesh = false,
flicker = false,
flickerSmoothing = 15, // higher = smoother flicker
blurSize = 0,
orbitTilt = true,
randomMotion = true,
noiseLength = 1000,
noiseStrength = 3;
var canvas = document.getElementById('stars'),
context = canvas.getContext('2d'),
mouse = {
x: 0,
y: 0
},
m = {},
r = 0,
c = 1000, // multiplier for delaunay points, since floats too small can mess up the algorithm
n = 0,
nAngle = (Math.PI * 2) / noiseLength,
nRad = 100,
nScale = 0.5,
nPos = {
x: 0,
y: 0
},
points = [],
vertices = [],
triangles = [],
links = [],
particles = [],
flares = [];
function init() {
var i, j, k;
// requestAnimFrame polyfill
window.requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
// Size canvas
resize();
mouse.x = canvas.clientWidth / 2;
mouse.y = canvas.clientHeight / 2;
// Create particle positions
for (i = 0; i < particleCount; i++) {
var p = new Particle();
particles.push(p);
points.push([p.x * c, p.y * c]);
}
vertices = Delaunay.triangulate(points);
var tri = [];
for (i = 0; i < vertices.length; i++) {
if (tri.length == 3) {
triangles.push(tri);
tri = [];
}
tri.push(vertices[i]);
}
// Tell all the particles who their neighbors are
for (i = 0; i < particles.length; i++) {
// Loop through all tirangles
for (j = 0; j < triangles.length; j++) {
// Check if this particle's index is in this triangle
k = triangles[j].indexOf(i);
// If it is, add its neighbors to the particles contacts list
if (k !== -1) {
triangles[j].forEach(function(value, index, array) {
if (value !== i && particles[i].neighbors.indexOf(value) == -1) {
particles[i].neighbors.push(value);
}
});
}
}
}
var fps = 15;
var now;
var then = Date.now();
var interval = 1000 / fps;
var delta;
// Animation loop
(function animloop() {
requestAnimFrame(animloop);
now = Date.now();
delta = now - then;
if (delta > interval) {
then = now - (delta % interval);
resize();
render();
}
})();
}
function render() {
if (randomMotion) {
n++;
if (n >= noiseLength) {
n = 0;
}
nPos = noisePoint(n);
}
if (renderParticles) {
// Render particles
for (var i = 0; i < particleCount; i++) {
particles[i].render();
}
}
}
function resize() {
canvas.width = window.innerWidth * (window.devicePixelRatio || 1);
canvas.height = canvas.width * (canvas.clientHeight / canvas.clientWidth);
}
// Particle class
var Particle = function() {
this.x = random(-0.1, 1.1, true);
this.y = random(-0.1, 1.1, true);
this.z = random(0, 4);
this.color = color;
this.opacity = random(0.1, 1, true);
this.flicker = 0;
this.neighbors = []; // placeholder for neighbors
};
Particle.prototype.render = function() {
var pos = position(this.x, this.y, this.z),
r = ((this.z * particleSizeMultiplier) + particleSizeBase) * (sizeRatio() / 1000),
o = this.opacity;
context.fillStyle = this.color;
context.globalAlpha = o;
context.beginPath();
context.fill();
context.closePath();
if (renderParticleGlare) {
context.globalAlpha = o * glareOpacityMultiplier;
context.ellipse(pos.x, pos.y, r * 100, r, (glareAngle - ((nPos.x - 0.5) * noiseStrength * motion)) * (Math.PI / 180), 0, 2 * Math.PI, false);
context.fill();
context.closePath();
}
context.globalAlpha = 1;
};
// Flare class
// Link class
var Link = function(startVertex, numPoints) {
this.length = numPoints;
this.verts = [startVertex];
this.stage = 0;
this.linked = [startVertex];
this.distances = [];
this.traveled = 0;
this.fade = 0;
this.finished = false;
};
// Utils
function noisePoint(i) {
var a = nAngle * i,
cosA = Math.cos(a),
sinA = Math.sin(a),
rad = nRad;
return {
x: rad * cosA,
y: rad * sinA
};
}
function position(x, y, z) {
return {
x: (x * canvas.width) + ((((canvas.width / 2) - mouse.x + ((nPos.x - 0.5) * noiseStrength)) * z) * motion),
y: (y * canvas.height) + ((((canvas.height / 2) - mouse.y + ((nPos.y - 0.5) * noiseStrength)) * z) * motion)
};
}
function sizeRatio() {
return canvas.width >= canvas.height ? canvas.width : canvas.height;
}
function random(min, max, float) {
return float ?
Math.random() * (max - min) + min :
Math.floor(Math.random() * (max - min + 1)) + min;
}
// init
if (canvas) init();
html,
body {
margin: 0;
padding: 0;
height: 100%;
}
body {
background: #000;
background-image: linear-gradient(-180deg, rgba(0, 0, 0, 0.00) 0%, #000000 100%);
}
#stars {
display: block;
position: relative;
width: 100%;
height: 100%;
z-index: 1;
position: absolute;
}
<script src="https://rawgit.com/ironwallaby/delaunay/master/delaunay.js"></script>
<script src="http://requirejs.org/docs/release/2.1.15/minified/require.js"></script>
<canvas id="stars" width="300" height="300"></canvas>
id="identifier" is unique
class="identifier" could be shared by a list of items
As you mention using class could be an option but you'll need to change your code to select all elements by that class before:
$(".identifier").each(function(a,b)
{
// Actions for each element
}
With javascript:
var elementList = document.getElementsByClassName("identifier");
var elementListSize=elementList.length;
for(var i=0;i<elementListSize;i++) {
// Actions for each element (elementList[i])
}
I'm currently working on a particle system where the particles move around and create pictures with some seconds in between (almost like a slide). I know where to put the color code to change the color on the particles forming the pictures bur for some reason it doesn't work. I therefore suspect that the problem is somewhere else in the script but the question is where...
You can see the code below (tried to make a codepen but it didn't work):
var dispersed = false;
var firstDone = false;
var secondDone = false;
var thirdDone = false;
var fRgba = []; // first img rgba data
var sRgba = []; // second img rgba data
var tRgba = []; // third img rgba data
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.01,
FAR = 10000;
var $container = $("#container");
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR);
var scene = new THREE.Scene();
scene.add(camera);
camera.position.z = 900;
renderer.setSize(WIDTH, HEIGHT);
$container.append(renderer.domElement);
var particleCount = 5200,
particles = new THREE.Geometry();
var pMaterial = new THREE.PointsMaterial({
size: 6,
map: createCircleTexture('#CACACA', 256),
transparent: true,
depthWrite: false
});
function createCircleTexture(color, size) {
var matCanvas = document.createElement('canvas');
matCanvas.width = matCanvas.height = size;
var matContext = matCanvas.getContext('2d');
var texture = new THREE.Texture(matCanvas);
var center = size / 2;
matContext.beginPath();
matContext.arc(center, center, size/2, 0, 2 * Math.PI, false);
matContext.closePath();
matContext.fillStyle = color;
matContext.fill();
texture.needsUpdate = true;
return texture;
}
for (var i = 0; i < particleCount; i++) {
var x = Math.random() * 1600 - 800;
var y = getRandomInt(600, 1500)
var z = Math.random() * 30 - 15;
var particle = new THREE.Vector3(x, y, z);
particle.updated = 0;
particles.vertices.push(particle);
};
var particleSystem = new THREE.Points(particles, pMaterial);
particleSystem.sortParticles = true;
scene.add(particleSystem);
function drawImage(imageObj, array) {
var canvas = $("#canvas")[0];
var context = canvas.getContext("2d");
var imageX = 0;
var imageY = 0;
var imageWidth = imageObj.width;
var imageHeight = imageObj.height;
context.drawImage(imageObj, imageX, imageY);
var imageData = context.getImageData(imageX, imageY, imageWidth,
imageHeight);
var data = imageData.data;
for(var y = 0; y < imageHeight; y+= 4) {
for(var x = 0; x < imageWidth; x+= 4) {
var red = data[((imageWidth * y) + x) * 4];
var green = data[((imageWidth * y) + x) * 4 + 1];
var blue = data[((imageWidth * y) + x) * 4 + 2];
var alpha = data[((imageWidth * y) + x) * 4 + 3];
if (red < 100) {
var pX = (x % 500) - 249;
var pY = 249 - y;
array.push([pX, pY, red, green, blue, alpha]);
}
}
}
};
var addDestination = function(particle, x, y, z) {
var dest = new THREE.Vector3(x, y, z);
particle.destination = dest;
};
var addVelocity = function(particle) {
var xDiff = (particle.destination.x - particle.x) / 180;
var yDiff = (particle.destination.y - particle.y) / 180;
var zDiff = (particle.destination.z - particle.z) / 180;
var vel = new THREE.Vector3(xDiff, yDiff, zDiff);
particle.velocity = vel;
};
var move = function(particle) {
particle.x += particle.velocity.x;
particle.y += particle.velocity.y;
particle.z += particle.velocity.z;
particle.updated += 1;
};
var slowDown = function(particle) {
particle.velocity.x -= (particle.velocity.x / 300)
particle.velocity.y -= (particle.velocity.y / 300)
particle.velocity.z -= (particle.velocity.z / 160)
};
var resetProperties = function() {
var pCount = particleCount;
while (pCount--) {
var particle = particles.vertices[pCount];
particle.destination = null
particle.updated = 0;
};
};
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
};
var distributedZ = function(level) {
var z;
if (level === 1) {
z = getRandomInt(50, 100);
} else if (level === 2) {
z = getRandomInt(350, 400);
} else {
z = getRandomInt(650, 700);
}
return z;
};
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
};
var disperse = function() {
pCount = particleCount;
for (var i = 0; i < pCount; i++) {
var particle = particles.vertices[i];
if (typeof(particle.destination) === "undefined") {
var nums = [-1, 1];
var x = particle.x + nums[Math.round(Math.random())];
var y = particle.y - 1000;
var z = Math.random() * 30 - 15;
addDestination(particle, x, y, z);
particle.velocity = new THREE.Vector3(x - particle.x, -3, z -
particle.z);
}
if (particle.updated <= 300) {
move(particle);
} else {
particles.vertices = shuffle(particles.vertices);
resetProperties();
dispersed = true;
return;
}
}
}
var morphImageParticles = function(imageParticles, rgba) {
for (var i = 0; i < imageParticles.length; i++) {
var particle = imageParticles[i]
if (particle.destination === null) {
var pixelData = rgba[i];
var x = pixelData[0];
var y = pixelData[1];
var z = Math.random() * 15 - 7;
addDestination(particle, x, y, z);
addVelocity(particle);
}
if (particle.updated <= 180) {
move(particle);
}
}
};
var morphOuterParticles = function(outerParticles, ord) {
for (var i = 0; i < outerParticles.length; i++) {
var nums = [-1, 1];
var particle = outerParticles[i];
if (particle.destination === null) {
var x = Math.random() * 1000 - 500;
var y = Math.random() * 1000 - 500;
var z;
if (i <= Math.round(outerParticles.length * 0.6)) {
z = distributedZ(1)
} else if (i > Math.round(outerParticles.length * 0.6) && i <
Math.round(outerParticles.length * 0.9)) {
z = distributedZ(2)
} else {
z = distributedZ(3);
}
addDestination(particle, x, y, z);
addVelocity(particle);
}
if (particle.updated <= 600) {
move(particle);
slowDown(particle);
} else {
particles.vertices = shuffle(particles.vertices);
resetProperties();
if (ord === 1) {
firstDone = true;
} else if (ord === 2) {
secondDone = true;
} else {
thirdDone = true;
}
return;
}
}
};
var makeImg = function(rgba, ord) {
var pCount = particleCount;
var imagePs = particles.vertices.slice(0, rgba.length);
var outerPs = particles.vertices.slice(rgba.length, pCount);
morphImageParticles(imagePs, rgba);
morphOuterParticles(outerPs, ord);
};
var update = function() {
if (thirdDone) {
} else if (secondDone) {
makeImg(tRgba, 3);
} else if (firstDone) {
makeImg(sRgba, 2);
} else if (dispersed) {
makeImg(fRgba, 1);
} else {
disperse();
}
particleSystem.geometry.verticesNeedUpdate = true;
renderer.render(scene, camera);
requestAnimationFrame(update);
TWEEN.update();
};
var rotXScale = d3.scale.linear().domain([0, window.innerHeight]).range([15,
-15]);
var rotYScale = d3.scale.linear().domain([0, window.innerWidth]).range([25,
-25]);
d3.select("body").on("mousemove", function() {
var scaledX = rotXScale(d3.mouse(this)[1]) * Math.PI / 180;
var scaledY = rotYScale(d3.mouse(this)[0]) * Math.PI / 180;
var tween = new TWEEN.Tween(particleSystem.rotation).to({ x: scaledX, y:
scaledY, z: 0 });
tween.easing( TWEEN.Easing.Quartic.Out);
tween.start();
transparency: true
});
var img1 = new Image();
var img2 = new Image();
var img3 = new Image();
img1.onload = function() {
drawImage(this, fRgba);
img2.onload = function() {
drawImage(this, sRgba);
img3.onload = function() {
drawImage(this, tRgba);
}
img3.src = "images/p1.png";
}
img2.src = "images/p2.png";
update();
}
img1.src = "images/p3.png";
update();
I thought I only need to add the code below, for example ['0xffffff'], that's how it should work at least but it didn't. Therefore I guess the problem is somewhere else in the script.
var fRgba = []; // first img rgba data
var sRgba = []; // second img rgba data
var tRgba = []; // third img rgba data
Hi I want to make a blur effect particle like this:
Can I use shadowBlur and shadowOffsetX/shadowOffsetY to do this? The actual shine will glow and fade a little bit repeatedly, so if I have to write some kind of animation how can I achieve this?
I have tried this code (jsfiddle example) but it doesn't look like the effect. So I wonder how to blur and glow the particle at the same time?
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const ra = window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.mozRequestAnimationFrame
|| window.oRequestAnimationFrame
|| window.msRequestAnimationFrame
|| function(callback) {
window.setTimeout(callback, 1000 / 60);
};
class Particle {
constructor(options) {
this.ctx = options.context;
this.x = options.x;
this.y = options.y;
this.radius = options.radius;
this.lightSize = this.radius;
this.color = options.color;
this.lightDirection = true;
}
glow() {
const lightSpeed = 0.5;
this.lightSize += this.lightDirection ? lightSpeed : -lightSpeed;
if (this.lightSize > this.radius || this.lightSize < this.radius) {
this.lightDirection = !this.lightDirection;
}
}
render() {
this.ctx.clearRect(0, 0, canvas.width, canvas.height);
this.glow();
this.ctx.globalAlpha = 0.5;
this.ctx.fillStyle = this.color;
this.ctx.beginPath();
this.ctx.arc(this.x, this.y, this.lightSize,
0, Math.PI * 2
);
this.ctx.fill();
this.ctx.globalAlpha = 0.62;
this.ctx.beginPath();
this.ctx.arc(this.x, this.y, this.radius * 0.7, 0, Math.PI * 2);
this.ctx.shadowColor = this.color;
this.ctx.shadowBlur = 6;
this.ctx.shadowOffsetX = 0;
this.ctx.shadowOffsetY = 0;
this.ctx.fill();
}
}
var particle = new Particle({
context: ctx,
x: 60,
y: 80,
radius: 12,
color: '#4d88ff'
});
function run() {
particle.render();
ra(run);
}
run();
<canvas id='canvas'></canvas>
There are several ways to do this. For a particle system my option is to pre render the blur using a blur filter. A common filter is the convolution filter. It uses a small array to determine the amount neighboring pixels contribute to each pixel of the image. You are best to look up convolution functions to understand it.
Wiki Convolution and Wiki Gaussian blur for more info.
I am not much of a fan of the standard Gaussian blur or the convolution filter used so in the demo snippet below you can find my version that I think creates a much better blur. The convolution blur filter is procedurally created and is in the imageTools object.
To use create a filter pass an object with properties size the blur amount in pixels and power is the strength. Lower powers is less spread on the blur.
// image must be loaded or created
var blurFilter = imageTools.createBlurConvolutionArray({size:17,power:1}); // size must be greater than 2 and must be odd eg 3,5,7,9...
// apply the convolution filter on the image. The returned image may be a new
//image if the input image does not have a ctx property pointing to a 2d canvas context
image = imageTools.applyConvolutionFilter(image,blurFilter);
In the demo I create a image, draw a circle on it, copy it and pad it so that there is room for the blur. Then create a blur filter and apply it to the image.
When I render the particles I first draw all the unblurred images, then draw the blurred copies with the ctx.globalCompositeOperation = "screen"; so that they have a shine. To vary the amount of shine I use the ctx.globalAlpha to vary the intensity of the rendered blurred image. To improve the FX I have drawn the blur image twice, once with oscillating scale and next at fixed scale and alpha.
The demo is simple, image tools can be found at the top. Then there is some stuff to setup the canvas and handle resize event. Then there is the code that creates the images, and apply the filters. Then starts the render adds some particles and renders everything.
Look in the function drawParticles for how I draw everything.
imageTools has all the image functions you will need. The imageTools.applyConvolutionFilter will apply any filter (sharpen, outline, and many more) you just need to create the appropriate filter. The apply uses the photon count colour model so gives a very high quality result especially for blurs type effects. (though for sharpen you may want to get in and change the squaring of the RGB values, I personally like it other do not)
The blur filter is not fast so if you apply it to larger images It would be best that you break it up in so you do not block the page execution.
A cheap way to get a blur is to copy the image to blur to a smaller version of itself, eg 1/4 then render it scaled back to normal size, the canvas will apply bilinear filtering on the image give a blur effect. Not the best quality but for most situations it is indistinguishable from the more sophisticated blur that I have presented.
UPDATE
Change the code so that the particles have a bit of a 3dFX to show that the blur can work up to larger scales. The blue particles are 32 by 32 image and the blur is 9 pixels with the blur image being 50by 50 pixels.
var imageTools = (function () {
var tools = {
canvas : function (width, height) { // create a blank image (canvas)
var c = document.createElement("canvas");
c.width = width;
c.height = height;
return c;
},
createImage : function (width, height) {
var image = this.canvas(width, height);
image.ctx = image.getContext("2d");
return image;
},
image2Canvas : function (img) {
var image = this.canvas(img.width, img.height);
image.ctx = image.getContext("2d");
image.drawImage(img, 0, 0);
return image;
},
padImage : function(img,amount){
var image = this.canvas(img.width + amount * 2, img.height + amount * 2);
image.ctx = image.getContext("2d");
image.ctx.drawImage(img, amount, amount);
return image;
},
getImageData : function (image) {
return (image.ctx || (this.image2Canvas(image).ctx)).getImageData(0, 0, image.width, image.height);
},
putImageData : function (image, imgData){
(image.ctx || (this.image2Canvas(image).ctx)).putImageData(imgData,0, 0);
return image;
},
createBlurConvolutionArray : function(options){
var i, j, d; // misc vars
var filterArray = []; // the array to create
var size = options.size === undefined ? 3: options.size; // array size
var center = Math.floor(size / 2); // center of array
// the power ? needs descriptive UI options
var power = options.power === undefined ? 1: options.power;
// dist to corner
var maxDist = Math.sqrt(center * center + center * center);
var dist = 0; // distance sum
var sum = 0; // weight sum
var centerWeight; // center calculated weight
var totalDistance; // calculated total distance from center
// first pass get the total distance
for(i = 0; i < size; i++){
for(j = 0; j < size; j++){
d = (maxDist-Math.sqrt((center-i)*(center-i)+(center-j)*(center-j)));
d = Math.pow(d,power)
dist += d;
}
}
totalDistance = dist; // total distance to all points;
// second pass get the total weight of all but center
for(i = 0; i < size; i++){
for(j = 0; j < size; j++){
d = (maxDist-Math.sqrt((center-i)*(center-i)+(center-j)*(center-j)));
d = Math.pow(d,power)
d = d/totalDistance;
sum += d;
}
}
var scale = 1/sum;
sum = 0; // used to check
for(i = 0; i < size; i++){
for(j = 0; j < size; j++){
d = (maxDist-Math.sqrt((center-i)*(center-i)+(center-j)*(center-j)));
d = Math.pow(d,power)
d = d/totalDistance;
filterArray.push(d*scale);
}
}
return filterArray;
},
applyConvolutionFilter : function(image,filter){
imageData = this.getImageData(image);
imageDataResult = this.getImageData(image);
var w = imageData.width;
var h = imageData.height;
var data = imageData.data;
var data1 = imageDataResult.data;
var side = Math.round(Math.sqrt(filter.length));
var halfSide = Math.floor(side/2);
var r,g,b,a,c;
for(var y = 0; y < h; y++){
for(var x = 0; x < w; x++){
var ind = y*4*w+x*4;
r = 0;
g = 0;
b = 0;
a = 0;
for (var cy=0; cy<side; cy++) {
for (var cx=0; cx<side; cx++) {
var scy = y + cy - halfSide;
var scx = x + cx - halfSide;
if (scy >= 0 && scy < h && scx >= 0 && scx < w) {
var srcOff = (scy*w+scx)*4;
var wt = filter[cy*side+cx];
r += data[srcOff+0] * data[srcOff+0] * wt;
g += data[srcOff+1] * data[srcOff+1] * wt;
b += data[srcOff+2] * data[srcOff+2] * wt;
a += data[srcOff+3] * data[srcOff+3] * wt;
}
}
}
data1[ind+0] = Math.sqrt(Math.max(0,r));
data1[ind+1] = Math.sqrt(Math.max(0,g));
data1[ind+2] = Math.sqrt(Math.max(0,b));
data1[ind+3] = Math.sqrt(Math.max(0,a));
}
}
return this.putImageData(image,imageDataResult);
}
};
return tools;
})();
/** SimpleFullCanvasMouse.js begin **/
const CANVAS_ELEMENT_ID = "canv";
const U = undefined;
var w, h, cw, ch; // short cut vars
var canvas, ctx;
var globalTime = 0;
var createCanvas, resizeCanvas, setGlobals;
var L = typeof log === "function" ? log : function(d){ console.log(d); }
createCanvas = function () {
var c,cs;
cs = (c = document.createElement("canvas")).style;
c.id = CANVAS_ELEMENT_ID;
cs.position = "absolute";
cs.top = cs.left = "0px";
cs.zIndex = 1000;
document.body.appendChild(c);
return c;
}
resizeCanvas = function () {
if (canvas === U) { canvas = createCanvas(); }
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx = canvas.getContext("2d");
if (typeof setGlobals === "function") { setGlobals(); }
}
setGlobals = function(){
cw = (w = canvas.width) / 2; ch = (h = canvas.height) / 2;
if(particles && particles.length > 0){
particles.length = 0;
}
}
resizeCanvas(); // create and size canvas
window.addEventListener("resize",resizeCanvas); // add resize event
const IMAGE_SIZE = 32;
const IMAGE_SIZE_HALF = 16;
const GRAV = 2001;
const NUM_PARTICLES = 90;
var background = imageTools.createImage(8,8);
var grad = ctx.createLinearGradient(0,0,0,8);
grad.addColorStop(0,"#000");
grad.addColorStop(1,"#048");
background.ctx.fillStyle = grad;
background.ctx.fillRect(0,0,8,8);
var circle = imageTools.createImage(IMAGE_SIZE,IMAGE_SIZE);
circle.ctx.fillStyle = "#5BF";
circle.ctx.arc(IMAGE_SIZE_HALF, IMAGE_SIZE_HALF, IMAGE_SIZE_HALF -2,0, Math.PI * 2);
circle.ctx.fill();
var blurFilter = imageTools.createBlurConvolutionArray({size:9,power:1}); // size must be greater than 2 and must be odd eg 3,5,7,9...
var blurCircle = imageTools.padImage(circle,9);
blurCircle = imageTools.applyConvolutionFilter(blurCircle,blurFilter)
var sun = imageTools.createImage(64,64);
grad = ctx.createRadialGradient(32,32,0,32,32,32);
grad.addColorStop(0,"#FF0");
grad.addColorStop(1,"#A40");
sun.ctx.fillStyle = grad;
sun.ctx.arc(32,32,32 -2,0, Math.PI * 2);
sun.ctx.fill();
var sunBlur = imageTools.padImage(sun,17);
blurFilter = imageTools.createBlurConvolutionArray({size:17,power:1}); // size must be greater than 2 and must be odd eg 3,5,7,9...
sunBlur = imageTools.applyConvolutionFilter(sunBlur,blurFilter);
var particles = [];
var createParticle = function(x,y,dx,dy){
var dir = Math.atan2(y-ch,x-cw);
var dist = Math.sqrt(Math.pow(y-ch,2)+Math.pow(x-cw,2));
var v = Math.sqrt(GRAV / dist); // get apporox orbital speed
return {
x : x,
y : y,
dx : dx + Math.cos(dir + Math.PI/2) * v, // set orbit speed at tangent
dy : dy + Math.sin(dir + Math.PI/2) * v,
s : (Math.random() + Math.random() + Math.random())/4 + 0.5, // scale
v : (Math.random() + Math.random() + Math.random()) / 3 + 2, // glow vary rate
};
}
var depthSort = function(a,b){
return b.y - a.y;
}
var updateParticles = function(){
var i,p,f,dist,dir;
for(i = 0; i < particles.length; i ++){
p = particles[i];
dist = Math.sqrt(Math.pow(cw-p.x,2)+Math.pow(ch-p.y,2));
dir = Math.atan2(ch-p.y,cw-p.x);
f = GRAV * 1 / (dist * dist);
p.dx += Math.cos(dir) * f;
p.dy += Math.sin(dir) * f;
p.x += p.dx;
p.y += p.dy;
p.rx = ((p.x - cw ) / (p.y + h)) * h + cw;
p.ry = ((p.y - ch ) / (p.y + h)) * h * -0.051+ ch;
//p.ry = ((h-p.y) - ch) * 0.1 + ch;
p.rs = (p.s / (p.y + h)) * h
}
particles.sort(depthSort)
}
var drawParticles = function(){
var i,j,p,f,dist,dir;
// draw behind the sun
for(i = 0; i < particles.length; i ++){
p = particles[i];
if(p.y - ch < 0){
break;
}
ctx.setTransform(p.rs,0,0,p.rs,p.rx,p.ry);
ctx.drawImage(circle,-IMAGE_SIZE_HALF,-IMAGE_SIZE_HALF);
}
// draw glow for behind the sun
ctx.globalCompositeOperation = "screen";
var iw = -blurCircle.width/2;
for(j = 0; j < i; j ++){
p = particles[j];
ctx.globalAlpha = ((Math.sin(globalTime / (50 * p.v)) + 1) / 2) * 0.6 + 0.4;
var scale = (1-(Math.sin(globalTime / (50 * p.v)) + 1) / 2) * 0.6 + 0.6;
ctx.setTransform(p.rs * 1.5 * scale,0,0,p.rs * 1.5* scale,p.rx,p.ry);
ctx.drawImage(blurCircle,iw,iw);
// second pass to intensify the glow
ctx.globalAlpha = 0.7;
ctx.setTransform(p.rs * 1.1,0,0,p.rs * 1.1,p.rx,p.ry);
ctx.drawImage(blurCircle,iw,iw);
}
// draw the sun
ctx.globalCompositeOperation = "source-over";
ctx.globalAlpha = 1;
ctx.setTransform(1,0,0,1,cw,ch);
ctx.drawImage(sun,-sun.width/2,-sun.height/2);
ctx.globalAlpha = 1;
ctx.globalCompositeOperation = "screen";
ctx.setTransform(1,0,0,1,cw,ch);
ctx.drawImage(sunBlur,-sunBlur.width/2,-sunBlur.height/2);
var scale = Math.sin(globalTime / 100) *0.5 + 1;
ctx.globalAlpha = (Math.cos(globalTime / 100) + 1) * 0.2 + 0.4;;
ctx.setTransform(1 + scale,0,0,1 + scale,cw,ch);
ctx.drawImage(sunBlur,-sunBlur.width/2,-sunBlur.height/2);
ctx.globalAlpha = 1;
ctx.globalCompositeOperation = "source-over";
// draw in front the sun
for(j = i; j < particles.length; j ++){
p = particles[j];
if(p.y > -h){ // don't draw past the near view plane
ctx.setTransform(p.rs,0,0,p.rs,p.rx,p.ry);
ctx.drawImage(circle,-IMAGE_SIZE_HALF,-IMAGE_SIZE_HALF);
}
}
ctx.globalCompositeOperation = "screen";
var iw = -blurCircle.width/2;
for(j = i; j < particles.length; j ++){
p = particles[j];
if(p.y > -h){ // don't draw past the near view plane
ctx.globalAlpha = ((Math.sin(globalTime / (50 * p.v)) + 1) / 2) * 0.6 + 0.4;
var scale = (1-(Math.sin(globalTime / (50 * p.v)) + 1) / 2) * 0.6 + 0.6;
ctx.setTransform(p.rs * 1.5 * scale,0,0,p.rs * 1.5* scale,p.rx,p.ry);
ctx.drawImage(blurCircle,iw,iw);
// second pass to intensify the glow
ctx.globalAlpha = 0.7;
ctx.setTransform(p.rs * 1.1,0,0,p.rs * 1.1,p.rx,p.ry);
ctx.drawImage(blurCircle,iw,iw);
}
}
ctx.globalCompositeOperation = "source-over";
}
var addParticles = function(count){
var ww = (h-10)* 2;
var cx = cw - ww/2;
var cy = ch - ww/2;
for(var i = 0; i < count; i ++){
particles.push(createParticle(cx + Math.random() * ww,cy + Math.random() * ww, Math.random() - 0.5, Math.random() - 0.5));
}
}
function display(){ // put code in here
if(particles.length === 0){
addParticles(NUM_PARTICLES);
}
ctx.setTransform(1,0,0,1,0,0); // reset transform
ctx.globalAlpha = 1; // reset alpha
ctx.drawImage(background,0,0,w,h)
updateParticles();
drawParticles();
ctx.globalAlpha = 1;
ctx.globalCompositeOperation = "source-over";
}
function update(timer){ // Main update loop
globalTime = timer;
display(); // call demo code
requestAnimationFrame(update);
}
requestAnimationFrame(update);
/** SimpleFullCanvasMouse.js end **/
How can I draw around 50000 particles in a browser and then just stop, I know how to create unending animations of particles, but how can I create one that once its done drawing the particles it just stops.
Edit
So essintially I want to time the drawing of the particles, however when i attack a timer, it doesnt get the change because the animation doesnt stop.
var scene = new Scene(),
particles = [],
len = 40000,
height = document.body.offsetHeight,
width = document.body.offsetWidth;
function Particle() {
this.x = 0;
this.y = 0;
this.size = 0;
this.depth = 0;
this.vy = 0;
}
Particle.prototype = {
constructor: Particle,
update: function (width, height) {
if (this.y > height) {
this.y = 1 - this.size;
}
this.y += this.vy;
}
};
for (var i = 0; i < len; i++) {
var particle = new Particle();
particle.x = Math.random() * width;
particle.y = Math.random() * height;
particle.depth = Math.random() * 10 | 0;
particle.size = (particle.depth + 1) / 8;
particle.vy = (particle.depth * .25) + 1 / Math.random();
particles.push(particle);
}
function falling_particles(scene) {
for (var i = 0, l = particles.length; i < l; i++) {
var particle = particles[i];
for (var w = 0; w < particle.size; w++) {
for (var h = 0; h < particle.size; h++) {
var pData = (~~(particle.x + w) + (~~(particle.y + h) * scene.width)) * 4;
scene.idata.data[pData] = 255;
scene.idata.data[pData + 1] = 255;
scene.idata.data[pData + 2] = 255;
scene.idata.data[pData + 3] = 255;
}
}
particle.update(scene.width, scene.height);
}
return scene.idata;
}
scene.setup(document.getElementById('canvas'), falling_particles, width, height, !0);
scene.animate();
window.onresize = function () {
height = scene.height = scene.canvas.height = document.body.offsetHeight;
width = scene.width = scene.canvas.width = document.body.offsetWidth;
};
link here: http://jsfiddle.net/MdSP4/
I'm not sure, what exactly you want to do, but if you add
setTimeout(function(){
scene.paused = true;
},1000);
Then all the drawing will stop after a second.