Issues with multiple p5.image - javascript

I'm playing around with creating some optical art with p5 and I'm running into issues with the image function. This is mt sketch.js file:
import Tile from "./Tile.js";
new p5(p5 => {
const rows = 14;
const columns = 14;
const dimension = 40
const height = rows * dimension;
const width = columns * dimension;
const framerate = 1;
const tiles = [];
p5.setup = () => {
p5.createCanvas(width, height);
p5.frameRate(framerate);
for (let r = 0; r < rows; r++) {
for (let c = 0; c < columns; c++) {
tiles.push(new Tile(p5, c * dimension, r * dimension, dimension, r, c));
}
}
};
p5.draw = () => {
p5.background(200);
tiles.forEach((tile) => {
console.log(tile);
p5.image(tile.update(), tile.x, tile.y);
});
};
});
And this is Tile.js:
export default class Tile {
constructor(p5, x, y, dimension, row, column) {
this.p5 = p5;
this.x = x;
this.y = y;
this.dimension = dimension;
this.row = row;
this.column = column;
this.onFirst = true;
this.on = p5.color(255, 184, 0);
this.off = p5.color(26, 17, 16);
this.diameter = Math.sqrt(Math.pow(dimension, 2) * 2)
this.pg = this.p5.createGraphics(dimension, dimension)
this.pg.noStroke();
}
update() {
if (this.diameter < 0) {
this.diameter = Math.sqrt(Math.pow(this.dimension, 2) * 2);
this.onFirst = !this.onFirst
}
else {
this.diameter -= 1;
}
return this.draw();
}
draw() {
this.pg.fill(this.onFirst ? this.off : this.on);
this.pg.rect(this.x, this.y, this.dimension, this.dimension);
this.pg.fill(this.onFirst ? this.on : this.off);
this.pg.circle(this.x + this.dimension / 2, this.y + this.dimension / 2, this.diameter);
return this.pg;
}
}
While I starting out I just had the one image and that was displayed on the top left as I wanted... subsequent images are not though, artefacts appear in odd places though (as you can see here: https://jsfiddle.net/annoyingmouse/Lbs9v8f4/). I've tried all sorts of things like exporting the image as a Base64 image and using loadImage but I think I might've been barking up the wrong tree.
Any help would be greatly appreciated :-)

Note, the method Tile.draw draws to an image (.pg) with a size of (.dimension, .dimension) rather than the canvas.
So the the origin has to be (0, 0) rather than (.x, .y), because the final image (.pg) is placed on the canvas at (.x, .y).
Change the code as follows, to solve the issue:
draw() {
this.pg.fill(this.onFirst ? this.off : this.on);
// this.pg.rect(this.x, this.y, this.dimension, this.dimension);
this.pg.rect(0, 0, this.dimension, this.dimension);
this.pg.fill(this.onFirst ? this.on : this.off);
// this.pg.circle(this.x + this.dimension / 2, this.y + this.dimension / 2, this.diameter);
this.pg.circle(this.dimension / 2, this.dimension / 2, this.diameter);
return this.pg;
}
See the example:
new p5(p5 => {
const rows = 14;
const columns = 14;
const dimension = 40
const height = rows * dimension;
const width = columns * dimension;
const framerate = 60;
const tiles = [];
p5.setup = () => {
p5.createCanvas(width, height);
p5.frameRate(framerate);
for (let r = 0; r < rows; r++) {
for (let c = 0; c < columns; c++) {
tiles.push(new Tile(p5, c * dimension, r * dimension, dimension, r, c));
}
}
};
p5.draw = () => {
p5.background(200);
tiles.forEach((tile) => {
console.log(tile);
p5.image(tile.update(), tile.x, tile.y);
});
};
});
class Tile {
constructor(p5, x, y, dimension, row, column) {
this.p5 = p5;
this.x = x;
this.y = y;
this.dimension = dimension;
this.row = row;
this.column = column;
this.onFirst = true;
this.on = p5.color(255, 184, 0);
this.off = p5.color(26, 17, 16);
this.diameter = Math.sqrt(Math.pow(dimension, 2) * 2)
this.pg = this.p5.createGraphics(dimension, dimension)
this.pg.noStroke();
}
update() {
if (this.diameter < 0) {
this.diameter = Math.sqrt(Math.pow(this.dimension, 2) * 2);
this.onFirst = !this.onFirst
}
else {
this.diameter -= 1;
}
return this.draw();
}
draw() {
this.pg.fill(this.onFirst ? this.off : this.on);
this.pg.rect(0, 0, this.dimension, this.dimension);
this.pg.fill(this.onFirst ? this.on : this.off);
this.pg.circle(this.dimension / 2, this.dimension / 2, this.diameter);
return this.pg;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.js"></script>

Related

Small issues with an interactive project in p5.js / javascript

I need help with an interactive project in p5.js.
Here are the things that are still missing:
the clock hands should rotate
when the puzzle is solved "won" should be displayed and the timer should stop (Here I have a code part in my program but it doesn´t work)
the "moves" don´t count up when you click somewhere - only at the specific field
at "Game Over" the picture and the clock should stop
Here is a picture of the puzzle: Slide Puzzle
I hope someone can help me. Thank you very much.
Here is the code:
let w = window.innerWidth/2;
let h = window.innerHeight/1.5;
let ground;
let plate = [];
let tiles = [];
let col = 4;
let row = 4;
let bubbles = [];
let timerValue = 160;
let moves = 0;
function setup() {
canvas = createCanvas(w, h);
ground = createGraphics(w, h);
w = width / col;
h = height / row;
textAlign(CENTER, CENTER);
setInterval(timeIt, 1000);
imag = loadImage('Mauszeiger.png');
for (let i = 0; i < col; i++) {
for (let j = 0; j < row; j++) {
let img = createImage(w, h);
let index = i + j * col;
plate.push(index);
let teil = new Tile(index, img);
tiles[index] = teil;
}
}
tiles.pop();
plate.pop();
plate.push(-1);
startViz();
simpleShuffle(plate);
}
function draw() {
background(100);
push();
scale(1, 0.9);
drawViz();
updateTiles();
for (let i = 0; i < col; i++) {
for (let j = 0; j < row; j++) {
let index = i + j * col;
let x = i * w;
let y = j * h;
let teileIndex = plate[index];
if (teileIndex > -1) {
let img = tiles[teileIndex].img;
image(img, x, y, w, h);
}
strokeWeight(5);
noFill();
rect(x, y, w, h);
}
}
pop();
if (isSolved()) {
console.log('SOLVED');
timerValue = 0;
text('Won', width/2, height/2);
}
if (timerValue < 10 || timerValue >= 10) {
textSize(15);
fill(255);
text(timerValue, width-30, height*0.95);
}
textSize(45);
if (timerValue == 0) {
text('Game Over', width/2, height/2);
draw = function(){}
}
textSize(15);
text('moves: ' + moves, width/2, height*0.95);
push();
noFill();
stroke(255);
ellipse(27, height*0.95, 40, 40);
imageMode(CENTER);
image(imag, 30, height*0.95, imag.width / 100, imag.height / 100);
pop();
}
function mousePressed() {
let i = floor(mouseX / w);
let j = floor(mouseY / h);
move(i, j, plate);
if (mousePressed) {
moves++;
}
}
function windowResized() {
w = window.innerWidth/2;
h = window.innerHeight/1.5;
resizeCanvas(w, h);
}
function timeIt() {
if (timerValue > 0) {
timerValue--;
}
}
function isSolved() {
for (let i = 0; i < plate.length - 1; i++) {
if (plate[i] !== tiles[i].index) {
return false;
}
}
return true;
}
function updateTiles() {
for (let i = 0; i < col; i++) {
for (let j = 0; j < row; j++) {
let x = j * w;
let y = i * h;
let index = i + j * col;
if (tiles[index]) tiles[index].img.copy(ground, x, y, w, h, 0, 0, w, h);
}
}
}
function swap(i, j, arr) {
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
function randomMove(arr) {
let r1 = floor(random(col));
let r2 = floor(random(row));
move(r1, r2, arr);
}
function simpleShuffle(arr) {
for (let i = 0; i < 1000; i++) {
randomMove(arr);
}
}
function move(i, j, arr) {
let blank = findBlank();
let blankCol = blank % col;
let blankRow = floor(blank / row);
if (isNeighbor(i, j, blankCol, blankRow)) {
swap(blank, i + j * col, arr);
}
}
function isNeighbor(i, j, x, y) {
if (i !== x && j !== y) {
return false;
}
if (abs(i - x) == 1 || abs(j - y) == 1) {
return true;
}
return false;
}
function findBlank() {
for (let i = 0; i < plate.length; i++) {
if (plate[i] == -1) return i;
}
}
function startViz() {
for (let i = 0; i < 5; i++) {
bubbles.push(new Bubble());
}
}
function drawViz() {
ground.background(30);
for (let b of bubbles) {
b.update();
b.show();
b.show1();
}
}
class Bubble {
constructor() {
this.r = random(50, 80);
this.x = random(this.r, width - this.r);
this.y = random(this.r, height - this.r);
this.vx = random(-1 * (w*0.005), 3 * (w*0.005));
this.vy = random(-1 * (w*0.005), 3 * (w*0.005));
this.color = color(random(255), random(255), random(255));
}
show() {
ground.noFill();
ground.stroke(255);
ground.fill(this.color);
ground.strokeWeight(3);
ground.circle(this.x, this.y, this.r * 2 * (w*0.005));
}
show1() {
ground.line(this.x, this.y, this.x + this.r / 2 * (w*0.005), this.y + this.r / 2 * (w*0.005));
ground.line(this.x, this.y, this.x - this.r / 2 * (w*0.005), this.y + this.r / 2 * (w*0.005));
}
update() {
this.x += this.vx;
this.y += this.vy;
if (this.x > width - this.r || this.x < this.r) {
this.vx *= -1;
}
if (this.y > height - this.r || this.y < this.r) {
this.vy *= -1;
}
}
}
class Tile {
constructor(i, img) {
this.index = i;
this.img = img;
}
}

How to remove black background from this JS coding?

I'm trying to make this particle text be on a transparent background to add onto a slideshow. Can someone assist? I cannot seem to find where it is stated within the code.
Here is the JS code. Sorry I can't seem to get it to fit properly within the code section of the post.
class Particles { constructor(x, y, texture, size) {
this.x = x;
this.y = y;
this.sprite = new PIXI.Sprite(new PIXI.Texture.from(texture));
this.sprite.texture.frame = new PIXI.Rectangle(x, y, size, size);
this.sprite.x = x;
this.sprite.y = y;
this.speedX = 0;
this.speedY = 0;
this.radius = 100;
this.gravity = 0.1;
this.maxGravity = 0.01 + Math.random() * 0.03;
this.friction = 0.9;
this.dirX = Math.random() - 0.5;
this.dirY = Math.random() - 0.5; }
update(mouse) {
const distanceX = mouse.x - this.sprite.x;
const distanceY = mouse.y - this.sprite.y;
const distanceSqrd = distanceX * distanceX + distanceY * distanceY;
if (distanceSqrd < this.radius * this.radius && distanceSqrd > 0) {
const distance = Math.sqrt(distanceSqrd);
let normalX = distanceX / distance;
let normalY = distanceY / distance;
this.speedX -= normalX;
this.speedY -= normalY;
this.gravity *= this.friction;
} else {
this.gravity += 0.1 * (this.maxGravity - this.gravity);
}
let oDistX = this.x - this.sprite.x;
let oDistY = this.y - this.sprite.y;
this.speedX += oDistX * this.gravity;
this.speedY += oDistY * this.gravity;
this.speedX *= this.friction;
this.speedY *= this.friction;
this.sprite.x += this.speedX;
this.sprite.y += this.speedY; } }
class ParticlesText { constructor({ text, size }) {
this.app = new PIXI.Application({ width: innerWidth, height: innerHeight });
document.querySelector("#content-canvas").append(this.app.view);
this.text = text;
this.size = size;
this.cols = 500;
this.rows = 200;
this.pSize = 2;
this.particles = [];
this.mouse = {x: 0, y: 0}
this.container = new PIXI.particles.ParticleContainer(50000);
this.app.stage.addChild(this.container);
this.onResize = this.onResize.bind(this); }
init() {
const that = this;
opentype.load(
"https://raw.githack.com/AlainBarrios/Fonts/master/LeagueSpartan-Bold.otf",
function(err, font) {
if (err) {
alert("Font could not be loaded: " + err);
} else {
const canvas = document.createElement("canvas");
// Now let's display it on a canvas with id "canvas"
const ctx = canvas.getContext("2d");
// Construct a Path object containing the letter shapes of the given text.
// The other parameters are x, y and fontSize.
// Note that y is the position of the baseline.
const path = font.getPath(that.text, 0, that.size, that.size);
const width = font.getAdvanceWidth(that.text, that.size);
that.cols = width;
that.rows = that.size;
canvas.width = width;
canvas.height = that.size;
path.fill = "rgba(255,255,255,1)";
// If you just want to draw the text you can also use font.draw(ctx, text, x, y, fontSize).
path.draw(ctx);
that.addObjects(canvas, ctx);
}
}
); }
isEmpty(x, y, ctx) {
const image = ctx.getImageData(x, y, this.pSize, this.pSize);
let emptyCounter = 0;
for (let i = 0; (length = image.data.length), i < length; i += 4) {
if (image.data[i + 3] !== 0) {
continue;
}
emptyCounter++;
}
return emptyCounter === this.pSize * this.pSize; }
addObjects(canvas, ctx) {
this.container.x = this.app.renderer.width / 2 - this.cols / 2;
this.container.y = this.app.renderer.height / 2 - this.rows / 2;
for (let i = 0; i < this.cols; i += 1) {
for (let j = 0; j < this.rows; j += 1) {
const x = i * this.pSize;
const y = j * this.pSize;
if (this.isEmpty(x, y, ctx)) continue;
const p = new Particles(x, y, canvas, this.pSize);
this.particles.push(p);
this.container.addChild(p.sprite);
}
}
this.container.interactive = true;
this.onResize();
window.addEventListener("resize", this.onResize);
this.container.on("mousemove", e => {
this.mouse = e.data.getLocalPosition(this.container);
});
this.animate(); }
onResize() {
const { innerWidth, innerHeight } = window;
const size = [innerWidth, innerHeight];
const ratio = size[0] / size[1];
if (innerWidth / innerHeight >= ratio) {
var w = innerHeight * ratio;
var h = innerHeight;
} else {
var w = innerWidth;
var h = innerWidth / ratio;
}
//this.app.renderer.view.style.width = w + "px";
//this.app.renderer.view.style.height = h + "px"; }
animate() {
this.app.ticker.add(() => {
stats.begin();
this.particles.forEach(p => {
p.update(this.mouse);
});
stats.end();
}); } }
const particles = new ParticlesText({ text: "KILL THE ROBOTS", size:
150 }); particles.init();

Having trouble using instance mode

I am getting errors when I used instance mode in my code. My mini game isn't showing up I am not sure where the error is coming from. It works fine without the instance mode but I need to use the instance mode so that I can reference this code in another file. I'm using this link as a reference. http://p5js.org/examples/instance-mode-instantiation.html
let sketch = function(p) {
let blob;
let blobs = [];
let zoom = 1;
let timer = 20;
let hits = false;
let score = 0;
p.setup = function() {
p.createCanvas(600, 600);
blob = new Blob(0, 0, 64);
for (let i = 0; i < 300; i++) {
let x = p.random(-p.width,p.width);
let y = p.random(-p.height,p.height);
blobs[i] = new Blob(x, y, 15);
}
};
p.draw = function() {
p.background(0);
p.translate(width/2, height/2);
let newzoom = 64 / blob.r;
p.zoom = p.lerp(zoom, newzoom, 0.1);
p.scale(zoom);
p.translate(-blob.pos.x, -blob.pos.y);
for (var i = blobs.length-1; i >=0; i--) {
blobs[i].show();
if (blob.eats(blobs[i])) {
blobs.splice(i, 1);
}
}
if (frameCount % 60 == 0 && timer > 0) { // if the frameCount is divisible by 60, then a second has passed. it will stop at 0
p.timer --;
}
if (timer == 0 && score >=250) {
p.text("You Win", 0, 0);
p.noLoop();
}
if (blob.eats){
p.console.log("hit");
}
if (timer == 0 && score <= 250){
p.text("You Lose", 0, 0);
p.textSize(200);
p.noLoop();
}
blob.show();
blob.update();
};
};
let myp5 = new p5(sketch);
class Blob {
constructor(x, y, r) {
this.pos = createVector(x, y);
this.r = r;
this.vel = createVector(0,0);
}
show(p) {
p.ellipse(this.pos.x, this.pos.y, this.r, this.r);
}
eats(other) {
let d = p5.Vector.dist(this.pos, other.pos);
if (d < this.r + other.r) {
let sum = PI * this.r * this.r + PI * other.r * other.r;
score ++;
this.r = sqrt(sum / PI);
//this.r += other.r;
return true;
} else {
return false;
}
}
While width, height and frameCount are properties of the canvas, console is it not.
p.translate(width/2, height/2);
p.translate(p.width/2, p.height/2);
if (frameCount % 60 == 0 && timer > 0) {
if (p.frameCount % 60 == 0 && timer > 0) {
console.log("hit");
console.log("hit");
I don't know the implementation of Blob. but you have to passe the canvas object (p) to the show method and the let constructor.
The variable score can't be accessed in the class Blob
See the example, where I applied the suggested changes to your original code:
class Blob {
constructor(p, x, y, r) {
this.pos = p.createVector(x, y);
this.r = r;
this.vel = p.createVector(0,0);
}
show(p) {
p.ellipse(this.pos.x, this.pos.y, this.r, this.r);
}
eats(other) {
let d = this.pos.dist(other.pos);
if (d < this.r + other.r) {
let sum = Math.pi * this.r * this.r + Math.pi * other.r * other.r;
this.r = Math.sqrt(sum / Math.pi);
//this.r += other.r;
return true;
} else {
return false;
}
}
update() {
// ...
}
}
let sketch = function(p) {
let blob;
let blobs = [];
let zoom = 1;
let timer = 20;
let hits = false;
let score = 0;
p.setup = function() {
p.createCanvas(600, 600);
blob = new Blob(p, 0, 0, 64);
for (let i = 0; i < 300; i++) {
let x = p.random(-p.width,p.width);
let y = p.random(-p.height,p.height);
blobs[i] = new Blob(p, x, y, 15);
}
};
p.draw = function() {
p.background(0);
p.translate(p.width/2, p.height/2);
let newzoom = 64 / blob.r;
p.zoom = p.lerp(zoom, newzoom, 0.1);
p.scale(zoom);
p.translate(-blob.pos.x, -blob.pos.y);
for (var i = blobs.length-1; i >=0; i--) {
blobs[i].show(p);
if (blob.eats(blobs[i])) {
score ++;
blobs.splice(i, 1);
}
}
if (p.frameCount % 60 == 0 && timer > 0) {
p.timer --;
}
if (timer == 0 && score >=250) {
p.text("You Win", 0, 0);
p.noLoop();
}
if (blob.eats){
console.log("hit");
}
if (timer == 0 && score <= 250){
p.text("You Lose", 0, 0);
p.textSize(200);
p.noLoop();
}
blob.show(p);
blob.update();
};
};
let myp5 = new p5(sketch)
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.js"></script>

how to fill particles inside rectangle?

I'm looking to draw a rectangle basically text but just for clearing insight I'm working it with rectangle with small particles inside rectangle the basic I idea I got from https://yalantis.com/ but in my attempt I'm stuck here with solid filled rectangle with a color I have specified for particles. Please help me.. :)
Thanks here is my code:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Off Screen Canvas</title>
<script>
function createOffscreenCanvas() {
var offScreenCanvas = document.createElement('canvas');
offScreenCanvas.width = '1360';
offScreenCanvas.height = '400';
var context = offScreenCanvas.getContext("2d");
var W=200;
var H=200;
particleCount = 200;
particles = []; //this is an array which will hold our particles Object/Class
function Particle() {
this.x = Math.random() * W;
this.y = Math.random() * H;
this.direction ={"x": -1 + Math.random()*2, "y": -1 + Math.random()*2};
this.vx = 2 * Math.random() + 4 ;
this.vy = 2 * Math.random() + 4;
this.radius = .9 * Math.random() + 1;
this.move = function(){
this.x += this.vx * this.direction.x;
this.y += this.vy * this.direction.y;
};
this.changeDirection = function(axis){
this.direction[axis] *= -1;
};
this.draw = function() {
context.beginPath();
context.fillStyle = "#0097a7";
context.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
context.fill();
};
this.boundaryCheck = function(){
if(this.x >= W){
this.x = W;
this.changeDirection("x");
}
else if(this.x <= 0){
this.x = 0;
this.changeDirection("x");
}
if(this.y >= H){
this.y = H;
this.changeDirection("y");
}
else if(this.y <= 0){
this.y = 0;
this.changeDirection("y");
}
};
}
function createParticles(){
for (var i = particleCount-1; i >= 0; i--) {
p = new Particle();
particles.push(p);
}
}// end createParticles
function drawParticles(){
for (var i = particleCount-1; i >= 0; i--){
p = particles[i];
p.draw();
}
} //end drawParticles
function updateParticles(){
for(var i = particles.length - 1; i >=0; i--){
p = particles[i];
p.move();
p.boundaryCheck();
}
}//end updateParticle
createParticles();
var part=drawParticles();
context.fillStyle=part;
context.fillRect(W-190, H-190, W, H);
context.fill();
return offScreenCanvas;
}
function copyToOnScreen(offScreenCanvas) {
var onScreenContext=document.getElementById('onScreen').getContext('2d');
var offScreenContext = offScreenCanvas.getContext('2d');
var image=offScreenContext.getImageData(10,10,200,200);
onScreenContext.putImageData(image,offScreenCanvas.width/2,offScreenCanvas.height/4);
}
function main() {
copyToOnScreen(createOffscreenCanvas());
}
</script>
<style>
canvas {
border: 1px solid red;
}
</style>
</head>
<body onload="main()">
<canvas id="onScreen" width="1360" height="400"></canvas>
</body>
</html>
I see you have not found what you are looking for yet. Below is something quick to get you on your way. There is a whole range of stuff being used from canvas,mouse,particles, etc most of which is without comments. There is no load balancing or compliance testing and because it uses babel to be compatible with IE11 I have no clue how it runs on those browsers.
I will add to this answer some other time but for now I am a little over it.
const textList = ["1","2","3","Testing","text","to","particles"];
var textPos = 0;
function createParticles(text){
createTextMap(
text, // text to display
40, // font size
"Arial", // font
{ // style fot rendering font
fillStyle : "#6AF",
strokeStyle : "#F80",
lineWidth : 2,
lineJoin : "round",
},{ // bounding box to find a best fit for
top : 0,
left : 0,
width : canvas.width,
height : canvas.height,
}
)
}
// This function starts the animations
var started = false;
function startIt(){
started = true;
const next = ()=>{
var text = textList[(textPos++ ) % textList.length];
particles.mouseFX.dist = canvas.height / 8;
createParticles(text);
setTimeout(moveOut,text.length * 100 + 3000);
}
const moveOut = ()=>{
particles.moveOut();
setTimeout(next,2000);
}
setTimeout(next,0);
}
function setStyle(ctx,style){
Object.keys(style).forEach(key => ctx[key] = style[key]);
}
// the following function create the particles from text using a canvas
// the canvas used is dsplayed on the main canvas top left fro referance.
var tCan = createImage(100, 100); // canvas used to draw text
function createTextMap(text,size,font,style,fit){
// function to conver to colour hex value
const hex = (v)=> (v < 16 ? "0" : "") + v.toString(16);
// set up font so we can find the size.
tCan.ctx.font = size + "px " + font;
// get size of text
var width = Math.ceil(tCan.ctx.measureText(text).width + size);
// resize the canvas to fit the text
tCan.width = width;
tCan.height = Math.ceil(size *1.2);
// c is alias for context
var c = tCan.ctx;
// set up font
c.font = size + "px " + font;
c.textAlign = "center";
c.textBaseline = "middle";
// set style
setStyle(c,style);
// only do stroke and fill if they are set in styles object
if(style.strokeStyle){
c.strokeText(text, width / 2, tCan.height / 2);
}
if(style.fillStyle){
c.fillText(text, width / 2, tCan.height/ 2);
}
// prep the particles
particles.empty();
// get the pixel data
var data = c.getImageData(0,0,width,tCan.height).data;
var x,y,ind,rgb,a;
// find pixels with alpha > 128
for(y = 0; y < tCan.height; y += 1){
for(x = 0; x < width; x += 1){
ind = (y * width + x) << 2; // << 2 is equiv to * 4
if(data[ind + 3] > 128){ // is alpha above half
rgb = `#${hex(data[ind ++])}${hex(data[ind ++])}${hex(data[ind ++])}`;
// add the particle
particles.add(Vec(x, y), Vec(x, y), rgb);
}
}
}
// scale the particles to fit bounding box
var scale = Math.min(fit.width / width, fit.height / tCan.height);
particles.each(p=>{
p.home.x = ((fit.left + fit.width) / 2) + (p.home.x - (width / 2)) * scale;
p.home.y = ((fit.top + fit.height) / 2) + (p.home.y - (tCan.height / 2)) * scale;
})
.findCenter() // get center used to move particles on and off of screen
.moveOffscreen() // moves particles off the screen
.moveIn(); // set the particles to move into view.
}
// vector object a quick copy from other code.
function Vec(x,y){ // because I dont like typing in new
return new _Vec(x,y);
}
function _Vec(x = 0,y = 0){
this.x = x;
this.y = y;
return this;
}
_Vec.prototype = {
setAs(vec){
this.x = vec.x;
this.y = vec.y;
},
toString(){
return `vec : { x : ${this.x}, y : ${this.y} );`
}
}
// basic particle
const particle = {
pos : null,
delta : null,
home : null,
col : "black",
}
// array of particles
const particles = {
items : [], // actual array of particles
mouseFX : { // mouse FX
power : 20,
dist : 100,
curve : 3, // polynomial power
on : true,
},
fx : {
speed : 0.4,
drag : 0.15,
size : 4,
jiggle : 8,
},
// direction 1 move in -1 move out
direction : 1,
moveOut(){this.direction = -1; return this},
moveIn(){this.direction = 1; return this},
length : 0, // Dont touch this from outside particles.
each(callback){ // custom iteration
for(var i = 0; i < this.length; i++){
callback(this.items[i],i);
}
return this;
},
empty(){ // empty but dont dereference
this.length = 0;
return this;
},
deRef(){ // call to clear memory
this.items.length = 0;
this.length = 0;
},
add(pos,home,col){ // adds a particle
var p;
if(this.length < this.items.length){
p = this.items[this.length++];
// p.pos.setAs(pos);
p.home.setAs(home);
p.delta.x = 0;
p.delta.y = 0;
p.col = col;
}else{
this.items.push(
Object.assign(
{},
particle,
{
pos,
home,
col,
delta : Vec()
}
)
);
this.length = this.items.length
}
return this;
},
draw(){ // draws all
var p, size, sizeh;
sizeh = (size = this.fx.size) / 2;
for(var i = 0; i < this.length; i++){
p = this.items[i];
ctx.fillStyle = p.col;
ctx.fillRect(p.pos.x - sizeh, p.pos.y - sizeh, size, size);
}
},
update(){ // update all particles
var p,x,y,d;
var mP = this.mouseFX.power;
var mD = this.mouseFX.dist;
var mC = this.mouseFX.curve;
var fxJ = this.fx.jiggle;
var fxD = this.fx.drag;
var fxS = this.fx.speed;
for(var i = 0; i < this.length; i++){
p = this.items[i];
p.delta.x += (p.home.x - p.pos.x ) * fxS + (Math.random() - 0.5) * fxJ;
p.delta.y += (p.home.y - p.pos.y ) * fxS + (Math.random() - 0.5) * fxJ;
p.delta.x *= fxD;
p.delta.y *= fxD;
p.pos.x += p.delta.x * this.direction;
p.pos.y += p.delta.y * this.direction;
if(this.mouseFX.on){
x = p.pos.x - mouse.x;
y = p.pos.y - mouse.y;
d = Math.sqrt(x * x + y * y);
if(d < mD){
x /= d;
y /= d;
d /= mD;
d = (1-Math.pow(d,mC)) * mP;
p.pos.x += x * d;
p.pos.y += y * d;
}
}
}
return this;
},
findCenter(){ // find the center of particles maybe could do without
var x,y;
y = x = 0;
this.each(p => {
x += p.home.x;
y += p.home.y;
});
this.center = Vec(x / this.length, y / this.length);
return this;
},
moveOffscreen(){ // move start pos offscreen
var dist,x,y;
dist = Math.sqrt(this.center.x * this.center.x + this.center.y * this.center.y);
this.each(p => {
var d;
x = p.home.x - this.center.x;
y = p.home.y - this.center.y;
d = Math.max(0.0001,Math.sqrt(x * x + y * y)); // max to make sure no zeros
p.pos.x = p.home.x + (x / d) * dist;
p.pos.y = p.home.y + (y / d) * dist;
});
return this;
},
}
function onResize(){ // called from boilerplate
if(!started){
startIt();
}
}
/** SimpleFullCanvasMouse.js begin **/
// the following globals are available
// w, h, cw, ch, width height centerWidth centerHeight of canvas
// canvas, ctx, mouse, globalTime
//MAIN animation loop
function display() { // call once per frame
ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform
ctx.globalAlpha = 1; // reset alpha
ctx.clearRect(0, 0, w, h);
if(tCan){
// ctx.drawImage(tCan,0,0);
}
particles.update();
particles.draw();
}
/******************************************************************************
The code from here down is generic full page mouse and canvas boiler plate
code. As I do many examples which all require the same mouse and canvas
functionality I have created this code to keep a consistent interface. The
Code may or may not be part of the answer.
This code may or may not have ES6 only sections so will require a transpiler
such as babel.js to run on legacy browsers.
*****************************************************************************/
// V2.0 ES6 version for Stackoverflow and Groover QuickRun
var w, h, cw, ch, canvas, ctx, mouse, globalTime = 0;
// You can declare onResize (Note the capital R) as a callback that is also
// called once at start up. Warning on first call canvas may not be at full
// size.
;(function(){
const RESIZE_DEBOUNCE_TIME = 100;
var resizeTimeoutHandle;
var firstRun = true;
function createCanvas () {
var c,cs;
cs = (c = document.createElement("canvas")).style;
cs.position = "absolute";
cs.top = cs.left = "0px";
cs.zIndex = 1000;
document.body.appendChild(c);
return c;
}
function resizeCanvas () {
if (canvas === undefined) { canvas = createCanvas() }
canvas.width = innerWidth;
canvas.height = innerHeight;
ctx = canvas.getContext("2d");
if (typeof setGlobals === "function") { setGlobals() }
if (typeof onResize === "function") {
clearTimeout(resizeTimeoutHandle);
if (firstRun) { onResize() }
else { resizeTimeoutHandle = setTimeout(onResize, RESIZE_DEBOUNCE_TIME) }
firstRun = false;
}
}
function setGlobals () {
cw = (w = canvas.width) / 2;
ch = (h = canvas.height) / 2;
}
mouse = (function () {
function preventDefault(e) { e.preventDefault() }
var m; // alias for mouse
var mouse = {
x : 0, y : 0, w : 0, // mouse position and wheel
alt : false, shift : false, ctrl : false, // mouse modifiers
buttonRaw : 0,
over : false, // true if mouse over the element
buttonOnMasks : [0b1, 0b10, 0b100], // mouse button on masks
buttonOffMasks : [0b110, 0b101, 0b011], // mouse button off masks
active : false,
bounds : null,
eventNames : "mousemove,mousedown,mouseup,mouseout,mouseover,mousewheel,DOMMouseScroll".split(","),
event(e) {
var t = e.type;
m.bounds = m.element.getBoundingClientRect();
m.x = e.pageX - m.bounds.left - scrollX;
m.y = e.pageY - m.bounds.top - scrollY;
m.alt = e.altKey;
m.shift = e.shiftKey;
m.ctrl = e.ctrlKey;
if (t === "mousedown") { m.buttonRaw |= m.buttonOnMasks[e.which - 1] }
else if (t === "mouseup") { m.buttonRaw &= m.buttonOffMasks[e.which - 1] }
else if (t === "mouseout") { m.over = false }
else if (t === "mouseover") { m.over = true }
else if (t === "mousewheel") {m.w = e.wheelDelta }
else if (t === "DOMMouseScroll") { m.w = -e.detail }
if (m.callbacks) { m.callbacks.forEach(c => c(e)) }
if ((m.buttonRaw & 2) && m.crashRecover !== null) {
if (typeof m.crashRecover === "function") { setTimeout(m.crashRecover, 0) }
}
e.preventDefault();
},
addCallback(callback) {
if (typeof callback === "function") {
if (m.callbacks === undefined) { m.callbacks = [callback] }
else { m.callbacks.push(callback) }
}
},
start(element) {
if (m.element !== undefined) { m.remove() }
m.element = element === undefined ? document : element;
m.eventNames.forEach(name => document.addEventListener(name, mouse.event) );
document.addEventListener("contextmenu", preventDefault, false);
m.active = true;
},
remove() {
if (m.element !== undefined) {
m.eventNames.forEach(name => document.removeEventListener(name, mouse.event) );
document.removeEventListener("contextmenu", preventDefault);
m.element = m.callbacks = undefined;
m.active = false;
}
}
}
m = mouse;
return mouse;
})();
function done() { // Clean up. Used where the IDE is on the same page.
window.removeEventListener("resize", resizeCanvas)
mouse.remove();
document.body.removeChild(canvas);
canvas = ctx = mouse = undefined;
}
function update(timer) { // Main update loop
if(ctx === undefined){ return }
globalTime = timer;
display(); // call demo code
requestAnimationFrame(update);
}
setTimeout(function(){
canvas = createCanvas();
mouse.start(canvas, true);
resizeCanvas();
if(typeof Groover !== "undefined" && Groover.ide){ mouse.crashRecover = done }; // Requires Ace.js and GrooverDev.js. Prevents
window.addEventListener("resize", resizeCanvas);
requestAnimationFrame(update);
},0);
})();
/** SimpleFullCanvasMouse.js end **/
/** CreateImage.js begin **/
// creates a blank image with 2d context
function createImage(w,h){var i=document.createElement("canvas");i.width=w;i.height=h;i.ctx=i.getContext("2d");return i;}
/** CreateImage.js end **/
canvas {
background : black;
}
well after all the attempts like hell I finally got my answer thanks to moáois answer to my post using particle slider. here is the code. Thanks everyone for your help :)

createPattern on canvas issue

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

Categories

Resources