3-D semi-circle with canvas - javascript

I have a library of shapes with indicies and vertices that are functions and want to create a 3-D semi-sphere. But I am Having trouble with this. See below of sample 3-D sphere function. How can I create a 3-D semi-sphere function the same way? Please help!
sphere: function (spherical) {
var radius = 0.5,
theta = Math.PI,
phi = 2 * Math.PI,
latLines = 30,
longLines = 30,
currentLat,
currentLong,
currentVertex,
currentIndex,
vertices = [],
indices = [],
finalResult = {},
i,
j,
t,
m;
for (i = 0; i < (latLines + 1); i += 1) {
currentLat = i * theta / latLines;
for (j = 0; j < (longLines + 1); j += 1) {
currentVertex = latLines * i + j;
vertices[currentVertex] = [];
currentLong = j * phi / longLines;
vertices[currentVertex][0] = radius * Math.sin(currentLat) * Math.cos(currentLong);
vertices[currentVertex][1] = radius * Math.cos(currentLat);
vertices[currentVertex][2] = radius * Math.sin(currentLat) * Math.sin(currentLong);
if (spherical) {
vertices[currentVertex][0] *= (currentLat * spherical);
vertices[currentVertex][2] *= (currentLat * spherical);
}
}
}
for (t = 0; t < (latLines + 1); t += 1) {
for (m = 0; m < (longLines + 1); m += 1) {
currentIndex = 2 * ((latLines + 1) * t + m);
indices[2 * ((latLines + 1) * t + m)] = [];
indices[2 * ((latLines + 1) * t + m) + 1] = [];
indices[currentIndex][0] = longLines * t + m;
indices[currentIndex][1] = longLines * t + m + 1;
indices[currentIndex][2] = longLines * (t + 1) + m;
currentIndex += 1;
indices[currentIndex][0] = longLines * (t + 1) + m;
indices[currentIndex][1] = longLines * (t + 1) + m + 1;
indices[currentIndex][2] = longLines * t + m + 1;
}
}
finalResult.vertices = vertices;
finalResult.indices = indices;
return finalResult;
},

Related

p5.js replace let url to local link

Im noob with p5j and i need help from someone please! :-(
On the website i must upload it , they not allow the external links.
and i need to change the "let url" to a png/jpg local link ( not external link ).
i dont know what the solution is ( maybe something similar with: "loadImage" or something.... please help me :-) )
Thank you so much and have a blessed week!
Here is the code:
//let url = "https://coolors.co/3a2e39-1e555c-f4d8cd-edb183-f15152";
let url = "https://blog.logrocket.com/wp-content/uploads/2022/03/Creating-animations-p5-js.png";
let palette;
let font;
function preload() {
font = loadFont("https://openprocessing.org/sketch/1359269/files/Happy Monsters.ttf");
}
function setup() {
createCanvas(1112, 834);
colorMode(HSB, 360, 100, 100, 100);
angleMode(DEGREES);
palette = createPalette(url);
background(10);
}
function draw() {
//background(0, 0, 90);
let offset = 100//width / 100;
let margin = 0; //offset / 5;
let cells = 1//int(random(2, 8));
let d = (width - offset * 2 - margin * (cells - 1)) / cells;
for (let j = 0; j < cells; j++) {
for (let i = 0; i < cells; i++) {
let x = offset + i * (d + margin) + d / 2;
let y = offset + j * (d + margin) + d / 2;
drawFancyShape(x, y, d, palette.concat());
}
}
frameRate(0.5);
noLoop();
}
function drawFancyShape(x, y, d, colors, char = String.fromCodePoint(65 + int(random(26)))) {
let g = createGraphics(d, d);
let g2 = createGraphics(d, d);
colors = shuffle(colors);
let c0 = colors[0];
colors.splice(0, 1);
let ratio = 0.2;
let xStep, yStep;
for (let y = 0; y < g.height; y += yStep) {
yStep = random(ratio, 1 - ratio) * g.height / 2;
if (y + yStep > g.height) yStep = g.height - y;
if (g.height - y - yStep < g.height / 100) yStep = g.height - y;
for (let x = 0; x < g.width; x += xStep) {
xStep = random(ratio, 1 - ratio) * g.width / 2;
if (x + xStep > g.width) xStep = g.width - x;
if (g.width - x - xStep < g.width / 100) xStep = g.width - x;
let r = [];
for (let i = 0; i < 4; i++) {
r.push(int(random(5)) * max(xStep, yStep) / 4);
}
g.rectMode(CENTER);
g.fill(random(colors));
g.noStroke();
g.rect(x + xStep / 2, y + yStep / 2, xStep - 2, yStep - 2, r[0], r[1], r[2], r[3]);
}
}
g2.textSize(g.width * 0.6);
g2.textAlign(CENTER, CENTER);
g2.textFont(font)
g2.textStyle(BOLD);
g2.fill(c0);
// g2.stroke(0);
g2.text(char, g.width / 2, g.height / 2 - g.height / 8);
let g_tmp = g.get();
let g2_tmp = g2.get();
g_tmp.mask(g2_tmp);
// g_tmp.mask(g2_tmp);
drawingContext.shadowColor = color(0, 0, 0, 33);
drawingContext.shadowBlur = d / 10;
push();
translate(x, y);
imageMode(CENTER);
// image(g, 0, 0);
let scl = 1.1;
image(g2, 0, 0, g2.width * scl, g2.height * scl);
image(g_tmp, 0, 0, g_tmp.width * scl, g_tmp.height * scl);
pop();
}
function createPalette(_url) {
let slash_index = _url.lastIndexOf('/');
let pallate_str = _url.slice(slash_index + 1);
let arr = pallate_str.split('-');
for (let i = 0; i < arr.length; i++) {
arr[i] = color('#' + arr[i]);
}
return arr;
}
// save jpg
let lapse = 0; // mouse timer
function mousePressed(){
// prevents mouse press from registering twice
if (millis() - lapse > 400){
save("img_" + month() + '-' + day() + '_' + hour() + '-' + minute() + '-' + second() + ".jpg");
lapse = millis();
}
}

How to make this cube a Sphere in P5.js?

I've been developing a procedural cube, which is built in three steps.
Setting up the vectors
Drawing the triangles needed
Normalizing to convert to sphere
My problem regards to the last step, when I normalize the vectors it only shows a quarter of a sphere. Could anyone help me out with this?
let world;
function setup() {
createCanvas(500, 500, WEBGL);
world = new cube(9, 80); // Testing values
}
function draw() {
background(200);
world.createVertices();
//world.drawPoints();
world.createTriangles();
world.drawTriangles();
}
class cube {
constructor(resolution,scale,vertices, triangles, roundness, normals) {
this.resolution = resolution;
this.vertices = vertices;
this.scale = scale;
this.triangles = triangles;
this.normals = normals;
}
createVertices() {
let cornerVertices = 8;
let edgeVertices = ((this.resolution * 3) - 3) * 4;
let faceVertices = ((this.resolution - 1) * (this.resolution - 1) +(this.resolution - 1) * (this.resolution - 1) +(this.resolution- 1) * (this.resolution - 1)) * 2;
let totalVertices = cornerVertices + edgeVertices + faceVertices // For checking purposes only
this.vertices = []
this.normals = []
let v = 0;
for (let y = 0; y <= this.resolution; y++) {
for (let x = 0; x <= this.resolution; x++) {
this.SetVertex(v++, x, y, 0);
}
for (let z = 1; z <= this.resolution; z++) {
this.SetVertex(v++, this.resolution, y, z);
}
for (let x = this.resolution - 1; x >= 0; x--) {
this.SetVertex(v++, x, y, this.resolution)
}
for (let z = this.resolution - 1; z > 0; z--) {
this.SetVertex(v++, 0, y, z);
}
}
for (let z = 1; z < this.resolution; z++) {
for (let x = 1; x < this.resolution; x++) {
this.SetVertex(v++, x, this.resolution, z);
}
}
for (let z = 1; z < this.resolution; z++) {
for (let x = 1; x < this.resolution; x++) {
this.SetVertex(v++, x, 0, z);
}
}
console.log(this.vertices)
console.log(totalVertices)
}
createTriangles() {
let quads = (this.resolution * this.resolution + this.resolution * this.resolution + this.resolution * this.resolution) * 2; // For checking purposes only
this.triangles = [];
let ring = (this.resolution * 2) * 2;
let t = 0
let v = 0;
for (let y = 0; y < this.resolution; y++, v++) {
for (let q = 0; q < ring - 1; q++, v++) {
t = this.SetQuad(this.triangles, t, v, v + 1, v + ring, v + ring + 1);
}
t = this.SetQuad(this.triangles, t, v, v - ring + 1, v + ring, v + 1);
}
t = this.CreateTopFace(this.triangles, t, ring);
t = this.CreateBottomFace(t, ring);
console.log(this.triangles)
}
drawPoints() {
strokeWeight(1);
let angleX = 200
let angleY = 500
let angleZ = 100
beginShape(POINTS);
for(let i = 0; i < this.vertices.length; i++) {
vertex(this.vertices[i].x * this.scale,this.vertices[i].y * -this.scale,this.vertices[i].z * this.scale)
rotateX(angleX)
rotateY(angleY)
rotateZ(angleZ)
}
endShape();
}
drawTriangles(){
let coordinates = [];
for(let i = 0; i < this.triangles.length; i++){
coordinates.push(this.vertices[this.triangles[i]])
}
console.log(coordinates)
for(let i = 0; i < coordinates.length; i = i + 3) {
beginShape(TRIANGLES);
vertex(coordinates[i].x * this.scale,coordinates[i].y * -this.scale,coordinates[i].z * this.scale)
vertex(coordinates[i + 1].x * this.scale,coordinates[i + 1].y * -this.scale,coordinates[i + 1].z * this.scale)
vertex(coordinates[i + 2].x * this.scale,coordinates[i + 2].y * -this.scale,coordinates[i + 2].z * this.scale)
endShape();
}
}
// Define vertex order.
SetQuad (triangles, i, v00, v10, v01, v11) {
triangles[i] = v00;
triangles[i + 1] = triangles[i + 4] = v01;
triangles[i + 2] = triangles[i + 3] = v10;
triangles[i + 5] = v11;
return i + 6;
}
CreateTopFace(triangles,t, ring) {
let v = ring * this.resolution;
for (let x = 0; x < this.resolution - 1; x++, v++) {
t = this.SetQuad(triangles, t, v, v + 1, v + ring - 1, v + ring);
}
t = this.SetQuad(triangles, t, v, v + 1, v + ring - 1, v + 2);
let vMin = ring * (this.resolution + 1) - 1;
let vMid = vMin + 1;
let vMax = v + 2;
for (let z = 1; z < this.resolution - 1; z++, vMin--, vMid++, vMax++) {
t = this.SetQuad(triangles, t, vMin, vMid, vMin - 1, vMid + this.resolution- 1);
for (let x = 1; x < this.resolution - 1; x++, vMid++) {
t = this.SetQuad(triangles, t, vMid, vMid + 1, vMid + this.resolution - 1, vMid + this.resolution);
}
t = this.SetQuad(triangles, t, vMid, vMax, vMid + this.resolution - 1, vMax + 1);
}
let vTop = vMin - 2;
t = this.SetQuad(triangles, t, vMin, vMid, vTop + 1, vTop);
for (let x = 1; x < this.resolution - 1; x++, vTop--, vMid++) {
t = this.SetQuad(triangles, t, vMid, vMid + 1, vTop, vTop - 1);
}
t = this.SetQuad(triangles, t, vMid, vTop - 2, vTop, vTop - 1);
return t;
}
CreateBottomFace (triangles, t, ring) {
let v = 1;
let vMid = this.vertices.length - (this.resolution - 1) * (this.resolution - 1);
t = this.SetQuad(triangles, t, ring - 1, vMid, 0, 1);
for (let x = 1; x < this.resolution - 1; x++, v++, vMid++) {
t = this.SetQuad(triangles, t, vMid, vMid + 1, v, v + 1);
}
t = this.SetQuad(triangles, t, vMid, v + 2, v, v + 1);
let vMin = ring - 2;
vMid -= this.resolution - 2;
let vMax = v + 2;
for (let z = 1; z < this.resolution - 1; z++, vMin--, vMid++, vMax++) {
t = this.SetQuad(triangles, t, vMin, vMid + this.resolution - 1, vMin + 1, vMid);
for (let x = 1; x < this.resolution - 1; x++, vMid++) {
t = this.SetQuad(triangles, t,vMid + this.resolution - 1, vMid + this.resolution, vMid, vMid + 1);
}
t = this.SetQuad(triangles, t, vMid + this.resolution - 1, vMax + 1, vMid, vMax);
}
let vTop = vMin - 1;
t = this.SetQuad(triangles, t, vTop + 1, vTop, vTop + 2, vMid);
for (let x = 1; x < this.resolution - 1; x++, vTop--, vMid++) {
t = this.SetQuad(triangles, t, vTop, vTop - 1, vMid, vMid + 1);
}
t = this.SetQuad(triangles, t, vTop, vTop - 1, vMid, vTop - 2);
return t;
}
SetVertex (i, x, y, z) {
let v = createVector(x, y, z)
v = v.mult(2)
v = v.div(this.resolution - 1)
this.normals[i] = v.normalize();
this.vertices[i] = this.normals[i];
}
}

Why does this canvas animation occasionally scramble itself?

For a website I am creating, I coded a parallax background using HTML5 canvas. Running the snippet below will produce a 192x192 sample of the background animation.
function parallaxCipher(size, color, speed, grid, sector, seed){
var scr = document.getElementById("parallax" + sector);
var ctx = scr.getContext("2d");
ctx.fillStyle = "#000";
ctx.fillRect(0,0,scr.width,scr.height);
var xGridMax = Math.ceil(scr.width / grid);
var yGridMax = Math.ceil(scr.height / grid) + 1;
var seedList = prng(seed,yGridMax * 2);
for(var c = 0; c < yGridMax;c++){
seedList[c] += seedList[c + yGridMax] * 256;
}
seedList.length = yGridMax;
var rotation = Math.floor(Math.floor(Date.now() / speed) / grid) % yGridMax;
rotation = yGridMax - rotation - 1;
if(rotation > 0){
seedList = seedList.slice(seedList.length-rotation).concat(seedList.slice(0,seedList.length - rotation));
}
ctx.fillStyle = color;
for(var a = 0;a<yGridMax;a++){
var row = prng(seedList[a],Math.ceil((xGridMax + 1)/8));
var row2 = [];
for(var d = 0;d<row.length;d++){
row[d] = row[d].toString(2);
row[d] = "0".repeat(8 - row[d].length) + row[d];
row2 = row2.concat(row[d].split(''));
}
row2.length = xGridMax + 1;
var rotation2 = Math.floor(Math.floor(Date.now() / speed) / grid) % xGridMax;
if(rotation2 > 0){
row2 = row2.slice(row2.length-rotation2).concat(row2.slice(0,row2.length - rotation2));
}
for(var b = -1;b<xGridMax;b++){
ctx.font = size + "px monospace";
ctx.fillText(row2[b + 1],(b * grid) - (size * 11 / 30) + ((Date.now() / speed) % grid),(a * grid) + (size / 2) - ((Date.now() / speed) % grid));
}
}
}
function prng(seed, instances){
//PRNG takes a 16 bit seed
var primes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,1607,1609,1613,1619,1621,1627];
var res = [];
var j = seed % 256;
var k = Math.floor(seed / 256);
for(var a = 0;a < instances;a++){
res.push(((primes[j] * primes[k]) % 257) - 1);
if(primes.includes(res[res.length - 1]) || primes.includes(res[res.length - 1] + 1)){
j = (j + 1) % 257;
}else{
k = (k - 1);
if(k == -1){
k = 256;
}
}
if(res[res.length - 1] == undefined){
console.warn("PRNG error: " + j + ", " + k + ", " + primes[j] + ", " + primes[k]);
}
}
return res;
}
function animate(){
window.requestAnimationFrame(animate);
parallaxCipher(15,"#0f0",25,18,"1",9999);
}
window.requestAnimationFrame(animate);
<canvas width="192" height="192" style="border:2px solid black;" id="parallax1">Nope.</canvas>
You may notice that every 10 seconds or so, the bits scramble themselves, as if the seed value randomly changed, even though the seed in this example is fixed at 9999.
I think it may be a problem with the rotation/rotation2 values, but I am not entirely sure. In fact, the bug appears to not be in sync with the rotation cycle at all, leaving me at a complete loss as to how this problem is occuring.
Forgive my terrible code, but can anyone help pinpoint the problem? Any help is appreciated!
I figured it out!
rotation2 is supposed to be calculated modulo xGridMax + 1, not xGridMax.
Thus, the correct animation (large version) is:
function parallaxCipher(size, color, speed, grid, sector, seed){
var scr = document.getElementById("parallax" + sector);
var ctx = scr.getContext("2d");
ctx.fillStyle = "#000";
ctx.fillRect(0,0,scr.width,scr.height);
var xGridMax = Math.ceil(scr.width / grid);
var yGridMax = Math.ceil(scr.height / grid) + 1;
var seedList = prng(seed,yGridMax * 2);
for(var c = 0; c < yGridMax;c++){
seedList[c] += seedList[c + yGridMax] * 256;
}
seedList.length = yGridMax;
var rotation = Math.floor(Math.floor(Date.now() / speed) / grid) % yGridMax;
rotation = yGridMax - rotation - 1;
if(rotation > 0){
seedList = seedList.slice(seedList.length-rotation).concat(seedList.slice(0,seedList.length - rotation));
}
ctx.fillStyle = color;
for(var a = 0;a<yGridMax;a++){
var row = prng(seedList[a],Math.ceil((xGridMax + 1)/8));
var row2 = [];
for(var d = 0;d<row.length;d++){
row[d] = row[d].toString(2);
row[d] = "0".repeat(8 - row[d].length) + row[d];
row2 = row2.concat(row[d].split(''));
}
row2.length = xGridMax + 1;
var rotation2 = Math.floor(Math.floor(Date.now() / speed) / grid) % (xGridMax+1);
if(rotation2 > 0){
row2 = row2.slice(row2.length-rotation2).concat(row2.slice(0,row2.length - rotation2));
}
for(var b = -1;b<xGridMax;b++){
ctx.font = size + "px monospace";
ctx.fillText(row2[b + 1],(b * grid) - (size * 11 / 30) + ((Date.now() / speed) % grid),(a * grid) + (size / 2) - ((Date.now() / speed) % grid));
}
}
}
function prng(seed, instances){
//PRNG takes a 16 bit seed
var primes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,1607,1609,1613,1619,1621,1627];
var res = [];
var j = seed % 256;
var k = Math.floor(seed / 256);
for(var a = 0;a < instances;a++){
res.push(((primes[j] * primes[k]) % 257) - 1);
if(primes.includes(res[res.length - 1]) || primes.includes(res[res.length - 1] + 1)){
j = (j + 1) % 257;
}else{
k = (k - 1);
if(k == -1){
k = 256;
}
}
if(res[res.length - 1] == undefined){
console.warn("PRNG error: " + j + ", " + k + ", " + primes[j] + ", " + primes[k]);
}
}
return res;
}
function animate(){
window.requestAnimationFrame(animate);
parallaxCipher(15,"#0f0",25,18,"1",9999);
}
window.requestAnimationFrame(animate);
<canvas width="512" height="512" style="border:2px solid black;" id="parallax1">Nope.</canvas>

Ripples on image

How to achieve a similar effect on an image instead of raw canvas?
/**
* Water ripple effect.
* Original code (Java) by Neil Wallis
* #link http://www.neilwallis.com/java/water.html
*
* #author Sergey Chikuyonok (serge.che#gmail.com)
* #link http://chikuyonok.ru
*/
(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,
mapind,
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
* (see example here: http://media.chikuyonok.ru/ripple/)
* But I need to draw simple artwork to bypass 1k limitation
*/
with (ctx) {
fillStyle = '#a2ddf8';
fillRect(0, 0, width, height);
fillStyle = '#07b';
save();
rotate(-0.785);
for (var i = 0; i < count; i++) {
fillRect(-width, i * step, width * 3, line_width);
}
restore();
}
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] += 512;
}
}
}
/**
* Generates new ripples
*/
function newframe() {
var i, a, b, data, cur_pixel, new_pixel, old_data;
i = oldind;
oldind = newind;
newind = i;
i = 0;
mapind = oldind;
// create local copies of variables to decrease
// scope lookup time in Firefox
var _width = width,
_height = height,
_ripplemap = ripplemap,
_mapind = mapind,
_newind = newind,
_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++) {
data = (
_ripplemap[_mapind - _width] +
_ripplemap[_mapind + _width] +
_ripplemap[_mapind - 1] +
_ripplemap[_mapind + 1]) >> 1;
data -= _ripplemap[_newind + i];
data -= data >> 5;
_ripplemap[_newind + i] = 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];
}
++_mapind;
++i;
}
}
mapind = _mapind;
}
canvas.onmousemove = function(/* Event */ evt) {
disturb(evt.offsetX || evt.layerX, evt.offsetY || evt.layerY);
};
setInterval(run, delay);
// generate random ripples
var rnd = Math.random;
setInterval(function() {
disturb(rnd() * width, rnd() * height);
}, 700);
})();
<canvas id="c"></canvas>
Just look at this majestic unicorn: codepen. Data URI used to avoid CORS problems, it'll work with any number of images (all images by default).
JS:
window.addEventListener('load',()=>{
document.querySelectorAll('img').forEach((img)=>{
var cont = document.createElement('div');
cont.style.position = 'relative'
cont.style.display = 'inline-block'
img.parentNode.insertBefore(cont,img);
img.style.verticalAlign = 'top';
cont.appendChild(img)
console.dir(img)
var c = document.createElement('canvas');
c.width = img.clientWidth
c.height = img.clientHeight
c.style.position = 'absolute'
c.style.top = '0px'
c.style.left = '0px'
cont.appendChild(c)
console.log(c)
makeRipple(c,img)
})
})
function makeRipple(el,img){
var canvas = el,
/** #type {CanvasRenderingContext2D} */
ctx = canvas.getContext('2d'),
width = img.clientWidth,
height = img.clientHeight,
half_width = width >> 1,
half_height = height >> 1,
size = width * (height + 2) * 2,
delay = 30,
oldind = width,
newind = width * (height + 3),
riprad = 3,
mapind,
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
* (see example here: http://media.chikuyonok.ru/ripple/)
* But I need to draw simple artwork to bypass 1k limitation
*/
ctx.drawImage(img,0,0,img.clientWidth,img.clientHeight)
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() {
console.log('bbb')
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] += 512;
}
}
}
/**
* Generates new ripples
*/
function newframe() {
var i, a, b, data, cur_pixel, new_pixel, old_data;
i = oldind;
oldind = newind;
newind = i;
i = 0;
mapind = oldind;
// create local copies of variables to decrease
// scope lookup time in Firefox
var _width = width,
_height = height,
_ripplemap = ripplemap,
_mapind = mapind,
_newind = newind,
_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++) {
data = (
_ripplemap[_mapind - _width] +
_ripplemap[_mapind + _width] +
_ripplemap[_mapind - 1] +
_ripplemap[_mapind + 1]) >> 1;
data -= _ripplemap[_newind + i];
data -= data >> 5;
_ripplemap[_newind + i] = 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];
}
++_mapind;
++i;
}
}
mapind = _mapind;
}
canvas.onmousemove = function(/* Event */ evt) {
console.log('XXXX',evt.offsetX)
disturb(evt.offsetX || evt.layerX, evt.offsetY || evt.layerY);
};
setInterval(run, delay);
// generate random ripples
var rnd = Math.random;
setInterval(function() {
console.log('aaa')
disturb(rnd() * width, rnd() * height);
}, 700);
};

Overlay confetti jaravascript, without blocking clicks and such

I've been using a few different javascript tools to generate confetti and celebration effect. All of those are some kind of overlay graphics. which block clicks of buttons, links and so on. Is there any way to keep a layer in front but ignore the actual clicks on that element, or allow clicks through the animated layer.
Script example im trying to use now is: http://codepen.io/iprodev/full/azpWBr/
html example
<canvas height='1' id='confetti' width='1'></canvas>
css
html, body {
margin: 0;
padding: 0;
background: #000;
height: 100%;
width: 100%;
}
#confetti{
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
}
Javascript
var retina = window.devicePixelRatio,
// Math shorthands
PI = Math.PI,
sqrt = Math.sqrt,
round = Math.round,
random = Math.random,
cos = Math.cos,
sin = Math.sin,
// Local WindowAnimationTiming interface
rAF = window.requestAnimationFrame,
cAF = window.cancelAnimationFrame || window.cancelRequestAnimationFrame,
_now = Date.now || function () {return new Date().getTime();};
// Local WindowAnimationTiming interface polyfill
(function (w) {
/**
* Fallback implementation.
*/
var prev = _now();
function fallback(fn) {
var curr = _now();
var ms = Math.max(0, 16 - (curr - prev));
var req = setTimeout(fn, ms);
prev = curr;
return req;
}
/**
* Cancel.
*/
var cancel = w.cancelAnimationFrame
|| w.webkitCancelAnimationFrame
|| w.clearTimeout;
rAF = w.requestAnimationFrame
|| w.webkitRequestAnimationFrame
|| fallback;
cAF = function(id){
cancel.call(w, id);
};
}(window));
document.addEventListener("DOMContentLoaded", function() {
var speed = 50,
duration = (1.0 / speed),
confettiRibbonCount = 11,
ribbonPaperCount = 30,
ribbonPaperDist = 8.0,
ribbonPaperThick = 8.0,
confettiPaperCount = 95,
DEG_TO_RAD = PI / 180,
RAD_TO_DEG = 180 / PI,
colors = [
["#df0049", "#660671"],
["#00e857", "#005291"],
["#2bebbc", "#05798a"],
["#ffd200", "#b06c00"]
];
function Vector2(_x, _y) {
this.x = _x, this.y = _y;
this.Length = function() {
return sqrt(this.SqrLength());
}
this.SqrLength = function() {
return this.x * this.x + this.y * this.y;
}
this.Add = function(_vec) {
this.x += _vec.x;
this.y += _vec.y;
}
this.Sub = function(_vec) {
this.x -= _vec.x;
this.y -= _vec.y;
}
this.Div = function(_f) {
this.x /= _f;
this.y /= _f;
}
this.Mul = function(_f) {
this.x *= _f;
this.y *= _f;
}
this.Normalize = function() {
var sqrLen = this.SqrLength();
if (sqrLen != 0) {
var factor = 1.0 / sqrt(sqrLen);
this.x *= factor;
this.y *= factor;
}
}
this.Normalized = function() {
var sqrLen = this.SqrLength();
if (sqrLen != 0) {
var factor = 1.0 / sqrt(sqrLen);
return new Vector2(this.x * factor, this.y * factor);
}
return new Vector2(0, 0);
}
}
Vector2.Lerp = function(_vec0, _vec1, _t) {
return new Vector2((_vec1.x - _vec0.x) * _t + _vec0.x, (_vec1.y - _vec0.y) * _t + _vec0.y);
}
Vector2.Distance = function(_vec0, _vec1) {
return sqrt(Vector2.SqrDistance(_vec0, _vec1));
}
Vector2.SqrDistance = function(_vec0, _vec1) {
var x = _vec0.x - _vec1.x;
var y = _vec0.y - _vec1.y;
return (x * x + y * y + z * z);
}
Vector2.Scale = function(_vec0, _vec1) {
return new Vector2(_vec0.x * _vec1.x, _vec0.y * _vec1.y);
}
Vector2.Min = function(_vec0, _vec1) {
return new Vector2(Math.min(_vec0.x, _vec1.x), Math.min(_vec0.y, _vec1.y));
}
Vector2.Max = function(_vec0, _vec1) {
return new Vector2(Math.max(_vec0.x, _vec1.x), Math.max(_vec0.y, _vec1.y));
}
Vector2.ClampMagnitude = function(_vec0, _len) {
var vecNorm = _vec0.Normalized;
return new Vector2(vecNorm.x * _len, vecNorm.y * _len);
}
Vector2.Sub = function(_vec0, _vec1) {
return new Vector2(_vec0.x - _vec1.x, _vec0.y - _vec1.y, _vec0.z - _vec1.z);
}
function EulerMass(_x, _y, _mass, _drag) {
this.position = new Vector2(_x, _y);
this.mass = _mass;
this.drag = _drag;
this.force = new Vector2(0, 0);
this.velocity = new Vector2(0, 0);
this.AddForce = function(_f) {
this.force.Add(_f);
}
this.Integrate = function(_dt) {
var acc = this.CurrentForce(this.position);
acc.Div(this.mass);
var posDelta = new Vector2(this.velocity.x, this.velocity.y);
posDelta.Mul(_dt);
this.position.Add(posDelta);
acc.Mul(_dt);
this.velocity.Add(acc);
this.force = new Vector2(0, 0);
}
this.CurrentForce = function(_pos, _vel) {
var totalForce = new Vector2(this.force.x, this.force.y);
var speed = this.velocity.Length();
var dragVel = new Vector2(this.velocity.x, this.velocity.y);
dragVel.Mul(this.drag * this.mass * speed);
totalForce.Sub(dragVel);
return totalForce;
}
}
function ConfettiPaper(_x, _y) {
this.pos = new Vector2(_x, _y);
this.rotationSpeed = (random() * 600 + 800);
this.angle = DEG_TO_RAD * random() * 360;
this.rotation = DEG_TO_RAD * random() * 360;
this.cosA = 1.0;
this.size = 5.0;
this.oscillationSpeed = (random() * 1.5 + 0.5);
this.xSpeed = 40.0;
this.ySpeed = (random() * 60 + 50.0);
this.corners = new Array();
this.time = random();
var ci = round(random() * (colors.length - 1));
this.frontColor = colors[ci][0];
this.backColor = colors[ci][1];
for (var i = 0; i < 4; i++) {
var dx = cos(this.angle + DEG_TO_RAD * (i * 90 + 45));
var dy = sin(this.angle + DEG_TO_RAD * (i * 90 + 45));
this.corners[i] = new Vector2(dx, dy);
}
this.Update = function(_dt) {
this.time += _dt;
this.rotation += this.rotationSpeed * _dt;
this.cosA = cos(DEG_TO_RAD * this.rotation);
this.pos.x += cos(this.time * this.oscillationSpeed) * this.xSpeed * _dt
this.pos.y += this.ySpeed * _dt;
if (this.pos.y > ConfettiPaper.bounds.y) {
this.pos.x = random() * ConfettiPaper.bounds.x;
this.pos.y = 0;
}
}
this.Draw = function(_g) {
if (this.cosA > 0) {
_g.fillStyle = this.frontColor;
} else {
_g.fillStyle = this.backColor;
}
_g.beginPath();
_g.moveTo((this.pos.x + this.corners[0].x * this.size) * retina, (this.pos.y + this.corners[0].y * this.size * this.cosA) * retina);
for (var i = 1; i < 4; i++) {
_g.lineTo((this.pos.x + this.corners[i].x * this.size) * retina, (this.pos.y + this.corners[i].y * this.size * this.cosA) * retina);
}
_g.closePath();
_g.fill();
}
}
ConfettiPaper.bounds = new Vector2(0, 0);
function ConfettiRibbon(_x, _y, _count, _dist, _thickness, _angle, _mass, _drag) {
this.particleDist = _dist;
this.particleCount = _count;
this.particleMass = _mass;
this.particleDrag = _drag;
this.particles = new Array();
var ci = round(random() * (colors.length - 1));
this.frontColor = colors[ci][0];
this.backColor = colors[ci][1];
this.xOff = (cos(DEG_TO_RAD * _angle) * _thickness);
this.yOff = (sin(DEG_TO_RAD * _angle) * _thickness);
this.position = new Vector2(_x, _y);
this.prevPosition = new Vector2(_x, _y);
this.velocityInherit = (random() * 2 + 4);
this.time = random() * 100;
this.oscillationSpeed = (random() * 2 + 2);
this.oscillationDistance = (random() * 40 + 40);
this.ySpeed = (random() * 40 + 80);
for (var i = 0; i < this.particleCount; i++) {
this.particles[i] = new EulerMass(_x, _y - i * this.particleDist, this.particleMass, this.particleDrag);
}
this.Update = function(_dt) {
var i = 0;
this.time += _dt * this.oscillationSpeed;
this.position.y += this.ySpeed * _dt;
this.position.x += cos(this.time) * this.oscillationDistance * _dt;
this.particles[0].position = this.position;
var dX = this.prevPosition.x - this.position.x;
var dY = this.prevPosition.y - this.position.y;
var delta = sqrt(dX * dX + dY * dY);
this.prevPosition = new Vector2(this.position.x, this.position.y);
for (i = 1; i < this.particleCount; i++) {
var dirP = Vector2.Sub(this.particles[i - 1].position, this.particles[i].position);
dirP.Normalize();
dirP.Mul((delta / _dt) * this.velocityInherit);
this.particles[i].AddForce(dirP);
}
for (i = 1; i < this.particleCount; i++) {
this.particles[i].Integrate(_dt);
}
for (i = 1; i < this.particleCount; i++) {
var rp2 = new Vector2(this.particles[i].position.x, this.particles[i].position.y);
rp2.Sub(this.particles[i - 1].position);
rp2.Normalize();
rp2.Mul(this.particleDist);
rp2.Add(this.particles[i - 1].position);
this.particles[i].position = rp2;
}
if (this.position.y > ConfettiRibbon.bounds.y + this.particleDist * this.particleCount) {
this.Reset();
}
}
this.Reset = function() {
this.position.y = -random() * ConfettiRibbon.bounds.y;
this.position.x = random() * ConfettiRibbon.bounds.x;
this.prevPosition = new Vector2(this.position.x, this.position.y);
this.velocityInherit = random() * 2 + 4;
this.time = random() * 100;
this.oscillationSpeed = random() * 2.0 + 1.5;
this.oscillationDistance = (random() * 40 + 40);
this.ySpeed = random() * 40 + 80;
var ci = round(random() * (colors.length - 1));
this.frontColor = colors[ci][0];
this.backColor = colors[ci][1];
this.particles = new Array();
for (var i = 0; i < this.particleCount; i++) {
this.particles[i] = new EulerMass(this.position.x, this.position.y - i * this.particleDist, this.particleMass, this.particleDrag);
}
}
this.Draw = function(_g) {
for (var i = 0; i < this.particleCount - 1; i++) {
var p0 = new Vector2(this.particles[i].position.x + this.xOff, this.particles[i].position.y + this.yOff);
var p1 = new Vector2(this.particles[i + 1].position.x + this.xOff, this.particles[i + 1].position.y + this.yOff);
if (this.Side(this.particles[i].position.x, this.particles[i].position.y, this.particles[i + 1].position.x, this.particles[i + 1].position.y, p1.x, p1.y) < 0) {
_g.fillStyle = this.frontColor;
_g.strokeStyle = this.frontColor;
} else {
_g.fillStyle = this.backColor;
_g.strokeStyle = this.backColor;
}
if (i == 0) {
_g.beginPath();
_g.moveTo(this.particles[i].position.x * retina, this.particles[i].position.y * retina);
_g.lineTo(this.particles[i + 1].position.x * retina, this.particles[i + 1].position.y * retina);
_g.lineTo(((this.particles[i + 1].position.x + p1.x) * 0.5) * retina, ((this.particles[i + 1].position.y + p1.y) * 0.5) * retina);
_g.closePath();
_g.stroke();
_g.fill();
_g.beginPath();
_g.moveTo(p1.x * retina, p1.y * retina);
_g.lineTo(p0.x * retina, p0.y * retina);
_g.lineTo(((this.particles[i + 1].position.x + p1.x) * 0.5) * retina, ((this.particles[i + 1].position.y + p1.y) * 0.5) * retina);
_g.closePath();
_g.stroke();
_g.fill();
} else if (i == this.particleCount - 2) {
_g.beginPath();
_g.moveTo(this.particles[i].position.x * retina, this.particles[i].position.y * retina);
_g.lineTo(this.particles[i + 1].position.x * retina, this.particles[i + 1].position.y * retina);
_g.lineTo(((this.particles[i].position.x + p0.x) * 0.5) * retina, ((this.particles[i].position.y + p0.y) * 0.5) * retina);
_g.closePath();
_g.stroke();
_g.fill();
_g.beginPath();
_g.moveTo(p1.x * retina, p1.y * retina);
_g.lineTo(p0.x * retina, p0.y * retina);
_g.lineTo(((this.particles[i].position.x + p0.x) * 0.5) * retina, ((this.particles[i].position.y + p0.y) * 0.5) * retina);
_g.closePath();
_g.stroke();
_g.fill();
} else {
_g.beginPath();
_g.moveTo(this.particles[i].position.x * retina, this.particles[i].position.y * retina);
_g.lineTo(this.particles[i + 1].position.x * retina, this.particles[i + 1].position.y * retina);
_g.lineTo(p1.x * retina, p1.y * retina);
_g.lineTo(p0.x * retina, p0.y * retina);
_g.closePath();
_g.stroke();
_g.fill();
}
}
}
this.Side = function(x1, y1, x2, y2, x3, y3) {
return ((x1 - x2) * (y3 - y2) - (y1 - y2) * (x3 - x2));
}
}
ConfettiRibbon.bounds = new Vector2(0, 0);
confetti = {};
confetti.Context = function(id) {
var i = 0;
var canvas = document.getElementById(id);
var canvasParent = canvas.parentNode;
var canvasWidth = canvasParent.offsetWidth;
var canvasHeight = canvasParent.offsetHeight;
canvas.width = canvasWidth * retina;
canvas.height = canvasHeight * retina;
var context = canvas.getContext('2d');
var interval = null;
var confettiRibbons = new Array();
ConfettiRibbon.bounds = new Vector2(canvasWidth, canvasHeight);
for (i = 0; i < confettiRibbonCount; i++) {
confettiRibbons[i] = new ConfettiRibbon(random() * canvasWidth, -random() * canvasHeight * 2, ribbonPaperCount, ribbonPaperDist, ribbonPaperThick, 45, 1, 0.05);
}
var confettiPapers = new Array();
ConfettiPaper.bounds = new Vector2(canvasWidth, canvasHeight);
for (i = 0; i < confettiPaperCount; i++) {
confettiPapers[i] = new ConfettiPaper(random() * canvasWidth, random() * canvasHeight);
}
this.resize = function() {
canvasWidth = canvasParent.offsetWidth;
canvasHeight = canvasParent.offsetHeight;
canvas.width = canvasWidth * retina;
canvas.height = canvasHeight * retina;
ConfettiPaper.bounds = new Vector2(canvasWidth, canvasHeight);
ConfettiRibbon.bounds = new Vector2(canvasWidth, canvasHeight);
}
this.start = function() {
this.stop()
var context = this;
this.update();
}
this.stop = function() {
cAF(this.interval);
}
this.update = function() {
var i = 0;
context.clearRect(0, 0, canvas.width, canvas.height);
for (i = 0; i < confettiPaperCount; i++) {
confettiPapers[i].Update(duration);
confettiPapers[i].Draw(context);
}
for (i = 0; i < confettiRibbonCount; i++) {
confettiRibbons[i].Update(duration);
confettiRibbons[i].Draw(context);
}
this.interval = rAF(function() {
confetti.update();
});
}
}
var confetti = new confetti.Context('confetti');
confetti.start();
window.addEventListener('resize', function(event){
confetti.resize();
});
});
You can use the pointer-events css property, try:
pointer-events: none

Categories