I want know how to figure out if the puzzle is solved.
I am creating an app for creating custom 6-piece puzzle.
Here's the code:
function approved(){
// Get the canvas and context
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// Load the image
var img = new Image();
img.src = document.getElementById('puzzleprieview').src;
img.onload = function() {
// Set the canvas size
canvas.width = img.width;
canvas.height = img.height;
// Draw the image on the canvas
ctx.drawImage(img, 0, 0);
// Split the image into parts
var w = img.width / 3;
var h = img.height / 2;
for (var i = 0; i < 7; i++) {
var x = (i % 3) * w;
var y = Math.floor(i / 3) * h;
// Create a new canvas for each part
var partCanvas = document.createElement("canvas");
partCanvas.draggable="true";
partCanvas.className="sampcanvas"
$(".sampcanvas").draggable({snap: true});
partCanvas.width = w;
partCanvas.height = h;
var partCtx = partCanvas.getContext("2d");
// Draw the part of the image on the new canvas
partCtx.drawImage(canvas, x, y, w, h, 0, 0, w, h);
var number=Math.floor(Math.random() * 100);
// Do something with each part, such as append it to the document
const getRandom = (min, max) => Math.floor(Math.random()*(max-min+1)+min);
partCanvas.style.left= getRandom(0, 300 - 200)+'px'; // 👈🏼 Horizontally
partCanvas.style.top = getRandom(0, 300 - 200)+'px'; // 👈🏼 Vertically
document.getElementById('pieces').appendChild(partCanvas);
}
}
}
That code is used to create puzzle pieces and append them.
What I need to do is somehow compare the puzzle piece solving to the canvas that is created
Well, great task in general and question in particular !
To achieve this purpose you could, f.e. put into each puzzlePart block it's initial position using "data-" attributes:
var x = (i % 3) * w;
var y = Math.floor(i / 3) * h;
// Create a new canvas for each part
let partCanvas = document.createElement('canvas');
partCanvas.dataset.xx = x;
partCanvas.dataset.yy = y;
Next, whenever needed, you are able to compare current position of puzzle parts with their initial ones. I took initial position from .dataset and current using .getBoundingClientRect():
var canvasOffsets = canvas.getBoundingClientRect();
var elementScreenOffsets = partCanvas.getBoundingClientRect();
var elementOffsets = {
x: elementScreenOffsets.left - canvasOffsets.left,
y: elementScreenOffsets.top - canvasOffsets.top,
};
var initialOffsets = {
x: partCanvas.dataset.xx,
y: partCanvas.dataset.yy,
};
As an option, you could for example "freeze" puzzle parts on the screen when they're moreless in their initial position:
var FREEZE_DISTASNCE = 30;
if (
Math.abs(elementOffsets.x - initialOffsets.x) <
FREEZE_DISTASNCE &&
Math.abs(elementOffsets.y - initialOffsets.y) <
FREEZE_DISTASNCE
) {
makeNotDraggable(partCanvas);
partCanvas.style.left = partCanvas.dataset.xx;
partCanvas.style.top = partCanvas.dataset.yy;
partCanvas.style.zIndex = -1;
}
So eventually I decided to modify initial question's code to make it fully working using my ideas above. Plus I decided to implement this POC with "generic" image which you could pick
For drag-n-drop implementation I referenced this article: https://www.w3schools.com/howto/howto_js_draggable.asp
File inputs Api: https://developer.mozilla.org/ru/docs/Web/HTML/Element/Input/file
document
.querySelector('.js-puzzle-image')
.addEventListener('change', function () {
document.querySelector('.js-puzzle-image').style.display = 'none';
document.querySelector('#pieces').style.display = 'inline-block';
var imageSrc = window.URL.createObjectURL(this.files[0]);
approved(imageSrc);
});
function approved(imageSrc) {
const el_wrap = document.querySelector('#pieces');
// Get the canvas and context
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// Load the image
var img = new Image();
img.src = imageSrc;
img.onload = function () {
// Set the canvas size
canvas.width = img.width;
canvas.height = img.height;
el_wrap.style.width = `${img.width}px`;
el_wrap.style.height = `${img.height}px`;
// Draw the image on the canvas
ctx.drawImage(img, 0, 0);
// Split the image into parts
var w = img.width / 3;
var h = img.height / 2;
for (var i = 0; i < 6; i++) {
var x = (i % 3) * w;
var y = Math.floor(i / 3) * h;
// Create a new canvas for each part
let partCanvas = document.createElement('canvas');
partCanvas.dataset.xx = x;
partCanvas.dataset.yy = y;
partCanvas.draggable = 'true';
partCanvas.className = 'sampcanvas';
//$('.sampcanvas').draggable({ snap: true });
partCanvas.width = w;
partCanvas.height = h;
var partCtx = partCanvas.getContext('2d');
// Draw the part of the image on the new canvas
partCtx.drawImage(canvas, x, y, w, h, 0, 0, w, h);
// Do something with each part, such as append it to the document
const getRandom = (min, max) =>
Math.floor(Math.random() * (max - min + 1) + min);
partCanvas.style.left = getRandom(0, img.width - w) + 'px'; // 👈🏼 Horizontally
partCanvas.style.top = getRandom(0, img.height - h) + 'px'; // 👈🏼 Vertically
document.getElementById('pieces').appendChild(partCanvas);
// making elements "draggable", but "freeze" them when they're on the correct position
makeDraggable(partCanvas, () => {
var canvasOffsets = canvas.getBoundingClientRect();
var elementScreenOffsets = partCanvas.getBoundingClientRect();
var elementOffsets = {
x: elementScreenOffsets.left - canvasOffsets.left,
y: elementScreenOffsets.top - canvasOffsets.top,
};
var initialOffsets = {
x: partCanvas.dataset.xx,
y: partCanvas.dataset.yy,
};
var FREEZE_DISTASNCE = 30;
if (
Math.abs(elementOffsets.x - initialOffsets.x) <
FREEZE_DISTASNCE &&
Math.abs(elementOffsets.y - initialOffsets.y) <
FREEZE_DISTASNCE
) {
makeNotDraggable(partCanvas);
partCanvas.style.left = partCanvas.dataset.xx + 'px';
partCanvas.style.top = partCanvas.dataset.yy + 'px';
partCanvas.style.zIndex = -1;
}
});
}
canvas.style.display = 'none';
};
}
// https://www.w3schools.com/howto/howto_js_draggable.asp
var zIndexTracker = 0;
function makeNotDraggable(elmnt) {
elmnt.onmousedown = undefined;
}
function makeDraggable(elmnt, onDrop) {
var pos1 = 0,
pos2 = 0,
pos3 = 0,
pos4 = 0;
elmnt.onmousedown = dragMouseDown;
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
// get the mouse cursor position at startup:
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
// call a function whenever the cursor moves:
document.onmousemove = elementDrag;
elmnt.style.zIndex = ++zIndexTracker;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
// calculate the new cursor position:
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
// set the element's new position:
elmnt.style.top = elmnt.offsetTop - pos2 + 'px';
elmnt.style.left = elmnt.offsetLeft - pos1 + 'px';
}
function closeDragElement() {
// stop moving when mouse button is released:
document.onmouseup = null;
document.onmousemove = null;
onDrop();
}
}
#pieces {
position: relative;
border: 1px dashed red;
display: inline-block;
}
.sampcanvas {
position: absolute;
}
<input type="file" accept=".png, .jpg, .jpeg" class="js-puzzle-image" />
<div id="pieces" style="display: none">
<canvas id="canvas"></canvas>
</div>
Of course, this code snippet is "not ideal" from code quality perspective and should be re-worked to be more object-oriented, to have better code responsibility splitting, etc... But for demostration purposes, I believe, that's a good start
Try adding this
partCanvas.dataset.index = i;
and then you can in your drop function do something like this
const finished = () => {
const indexes = document.querySelectorAll('.sampcanvas')
.map(imgPart => imgPart.dataset.index)
.join('');
console.log(indexes);
return indexes === '0123456';
}
Related
Can't figure out how to get this in place. I have the right function firing but am lost when it comes to why the logic isn't working my script. I have a console.log to show the variables are updating but the animation width doesn't update with it.
Javascript
$( document ).ready(function() {
var imgTag = new Image();
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var x = canvas.width;
var y = 0;
imgTag.onload = animate;
imgTag.src = "http://foodhall.hellogriptest.com/hh/assets/medallion-bounce.png";
var h = window.innerHeight;
var w = window.innerWidth;
canvas.height = h;
canvas.width = w;
//moving image
var mover = {
x: 0,
y: 0,
width: 100,
height: 100,
color: '#000',
down: true,
right: true
}
function animate() {
clear();
render();
rID = requestAnimationFrame(animate);
}
function clear() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
function render() {
//set direction
if (mover.down && mover.y >= h - mover.height)
mover.down = false;
if (!mover.down && mover.y <= 0)
mover.down = true;
if (mover.right && mover.x >= w - mover.width)
mover.right = false;
if (!mover.right && mover.x <= 0)
mover.right = true;
//make move
if (mover.right)
mover.x += 6;
else
mover.x -= 6;
if (mover.down)
mover.y += 6;
else
mover.y -= 6;
//drawRectangle(mover);
drawImage(mover);
}
function drawImage(mover) {
context.drawImage(imgTag, mover.x, mover.y); // draw image at current position
}
window.onresize = function() {
W = window.innerWidth;
H = window.innerHeight;
canvas.width = W;
canvas.height = H;
x = W;
console.log(x);
clear();
render();
drawImage(mover);
}
});//ready
Codepen
—
https://codepen.io/alcoven/pen/KROPrK
This is a simple fix. In the beginning of your script, you are setting lowercase w and lowercase h to the width and height of the window, but in you resize function, you set W = window.innerWidth. The capital W variable is then created and assigned the innerWidth. The lowercase w variable still exists as the original width, and that is what your render is using.
I am creating a smudging tool with HTML5 canvas. Now I have to shift the pixel color at the point of mouse pointer to the next position where mouse pointer moves. Is it possible to do with javascript?
<canvas id="canvas"><canvas>
var canvas = document.getElementById("canvas");
var context = canvas.getContext('2d');
var url = 'download.jpg';
var imgObj = new Image();
imgObj.src = url;
imgObj.onload = function(e) {
context.drawImage(imgObj, 0, 0);
}
function findPos(obj) {
var curleft = 0,
curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return {
x: curleft,
y: curtop
};
}
return undefined;
}
function rgbToHex(r, g, b) {
if (r > 255 || g > 255 || b > 255)
throw "Invalid color component";
return ((r << 16) | (g << 8) | b).toString(16);
}
$('#canvas').mousemove(function(e) {
var pos = findPos(this);
var x = e.pageX - pos.x;
var y = e.pageY - pos.y;
console.log(x, y);
var c = this.getContext('2d');
var p = c.getImageData(x, y, 1, 1).data;
var hex = "#" + ("000000" + rgbToHex(p[0], p[1], p[2])).slice(-6);
console.log(hex)
});
I am very short on time ATM so code only.
Uses an offscreen canvas brush to get a copy of the background canvas background where the mouse was last frame. Then use a radial gradient to feather the brush using ctx.globalCompositeOperation = "destination-in". Then draw the updated brush at the next mouse position.
The main canvas is use just to display, the canvas being smeared is called background You can put whatever content you want on that canvas (eg image) and it can be any size, and you can zoom, pan, rotate the background though you will have to convert the mouse coordinates to match the background coordinates
Click drag mouse to smear colours.
const ctx = canvas.getContext("2d");
const background = createCanvas(canvas.width,canvas.height);
const brushSize = 64;
const bs = brushSize;
const bsh = bs / 2;
const smudgeAmount = 0.25; // values from 0 none to 1 full
// helpers
const doFor = (count, cb) => { var i = 0; while (i < count && cb(i++) !== true); }; // the ; after while loop is important don't remove
const randI = (min, max = min + (min = 0)) => (Math.random() * (max - min) + min) | 0;
// simple mouse
const mouse = {x : 0, y : 0, button : false}
function mouseEvents(e){
mouse.x = e.pageX;
mouse.y = e.pageY;
mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;
}
["down","up","move"].forEach(name => document.addEventListener("mouse"+name,mouseEvents));
// brush gradient for feather
const grad = ctx.createRadialGradient(bsh,bsh,0,bsh,bsh,bsh);
grad.addColorStop(0,"black");
grad.addColorStop(1,"rgba(0,0,0,0)");
const brush = createCanvas(brushSize)
// creates an offscreen canvas
function createCanvas(w,h = w){
var c = document.createElement("canvas");
c.width = w;
c.height = h;
c.ctx = c.getContext("2d");
return c;
}
// get the brush from source ctx at x,y
function brushFrom(ctx,x,y){
brush.ctx.globalCompositeOperation = "source-over";
brush.ctx.globalAlpha = 1;
brush.ctx.drawImage(ctx.canvas,-(x - bsh),-(y - bsh));
brush.ctx.globalCompositeOperation = "destination-in";
brush.ctx.globalAlpha = 1;
brush.ctx.fillStyle = grad;
brush.ctx.fillRect(0,0,bs,bs);
}
// short cut vars
var w = canvas.width;
var h = canvas.height;
var cw = w / 2; // center
var ch = h / 2;
var globalTime;
var lastX;
var lastY;
// update background is size changed
function createBackground(){
background.width = w;
background.height = h;
background.ctx.fillStyle = "white";
background.ctx.fillRect(0,0,w,h);
doFor(64,()=>{
background.ctx.fillStyle = `rgb(${randI(255)},${randI(255)},${randI(255)}`;
background.ctx.fillRect(randI(w),randI(h),randI(10,100),randI(10,100));
});
}
// main update function
function update(timer){
globalTime = timer;
ctx.setTransform(1,0,0,1,0,0); // reset transform
ctx.globalAlpha = 1; // reset alpha
if(w !== innerWidth || h !== innerHeight){
cw = (w = canvas.width = innerWidth) / 2;
ch = (h = canvas.height = innerHeight) / 2;
createBackground();
}else{
ctx.clearRect(0,0,w,h);
}
ctx.drawImage(background,0,0);
// if mouse down then do the smudge for all pixels between last mouse and mouse now
if(mouse.button){
brush.ctx.globalAlpha = smudgeAmount;
var dx = mouse.x - lastX;
var dy = mouse.y - lastY;
var dist = Math.sqrt(dx*dx+dy*dy);
for(var i = 0;i < dist; i += 1){
var ni = i / dist;
brushFrom(background.ctx,lastX + dx * ni,lastY + dy * ni);
ni = (i+1) / dist;
background.ctx.drawImage(brush,lastX + dx * ni - bsh,lastY + dy * ni - bsh);
}
}else{
brush.ctx.clearRect(0,0,bs,bs); /// clear brush if not used
}
lastX = mouse.x;
lastY = mouse.y;
requestAnimationFrame(update);
}
requestAnimationFrame(update);
canvas { position : absolute; top : 0px; left : 0px; }
<canvas id="canvas"></canvas>
I'm trying to build an html canvas pad that will allow a user to drag and drop a dot on the pad, which will then return two values (one for Y axis, and one for Y axis), which I can use to trigger effects using the web audio API.
I've already sorted out the web Audio API portion of the problem.
The User:
Clicks and drags the dot to anywhere on the X/Y grid
On Drop we will have an X & Y value (perhaps in hidden range inputs), that trigger eventListeners.
The X value eventListener affects the wet/dry of the delay effect
The Y value eventListener affects the delay_time of the delay effect
so far I've been able to create and render the canvas and circle, and add event listeners on the svg element and the window. With the idea being that I can detect when an event occurs inside the canvas and when that click event leaves the canvas.
// Draw SVG pad
function drawDelayPad() {
var canvas = document.getElementById('delayPad');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var rectangle = new Path2D();
rectangle.rect(1, 1, 200, 200);
var circle = new Path2D();
circle.moveTo(150, 150);
circle.arc(100, 35, 10, 0 , 2 * Math.PI);
ctx.stroke(rectangle);
ctx.fill(circle);
}
}
// Listener on canvas
var canvas = document.getElementById('delayPad');
canvas.addEventListener("mousedown", function(){
console.log("click inside our canvas")
})
// Listener on document to check if we're outside the canvas
window.addEventListener("mouseup", function(){
console.log("outside our canvas")
});
So I think what I need to determine now is that when a click event does occur inside of the canvas, how far it is from the cirle, and if it does fall within the bounds of the circle, I should redraw it as long as the mousedown event is active.
Any help would be greatly appreciated.
I've found a nice little solution that kind of confirms my suspicions surrounding a hit counter! All credit really goes to rectangleWorld since I was for the most part just able to modify the example they had available.
Here's a codepen
// Draw SVG pad
function canvasApp(canvasID) {
var theCanvas = document.getElementById(canvasID);
var context = theCanvas.getContext("2d");
init();
var numShapes;
var shapes;
var dragIndex;
var dragging;
var mouseX;
var mouseY;
var dragHoldX;
var dragHoldY;
function init() {
numShapes = 1;
shapes = [];
makeShapes();
drawScreen();
theCanvas.addEventListener("mousedown", mouseDownListener, false);
}
function makeShapes() {
var i;
var tempX;
var tempY;
var tempRad;
var tempR;
var tempG;
var tempB;
var tempColor;
var tempShape;
for (i = 0; i < numShapes; i++) {
// My canvas element is 240x240
tempRad = 10;
tempX = 0 + tempRad;
tempY = 240 - tempRad;
tempR = Math.floor(Math.random() * 255);
tempG = Math.floor(Math.random() * 255);
tempB = Math.floor(Math.random() * 255);
tempColor = "rgb(" + tempR + "," + tempG + "," + tempB + ")";
tempShape = {
x: tempX,
y: tempY,
rad: tempRad,
color: tempColor
};
shapes.push(tempShape);
}
}
function mouseDownListener(evt) {
var i;
//We are going to pay attention to the layering order of the objects so that if a mouse down occurs over more than object,
//only the topmost one will be dragged.
var highestIndex = -1;
//getting mouse position correctly, being mindful of resizing that may have occured in the browser:
var bRect = theCanvas.getBoundingClientRect();
mouseX = (evt.clientX - bRect.left) * (theCanvas.width / bRect.width);
mouseY = (evt.clientY - bRect.top) * (theCanvas.height / bRect.height);
//find which shape was clicked
for (i = 0; i < numShapes; i++) {
if (hitTest(shapes[i], mouseX, mouseY)) {
dragging = true;
if (i > highestIndex) {
//We will pay attention to the point on the object where the mouse is "holding" the object:
dragHoldX = mouseX - shapes[i].x;
dragHoldY = mouseY - shapes[i].y;
highestIndex = i;
dragIndex = i;
}
}
}
if (dragging) {
window.addEventListener("mousemove", mouseMoveListener, false);
}
theCanvas.removeEventListener("mousedown", mouseDownListener, false);
window.addEventListener("mouseup", mouseUpListener, false);
//code below prevents the mouse down from having an effect on the main browser window:
if (evt.preventDefault) {
evt.preventDefault();
} //standard
else if (evt.returnValue) {
evt.returnValue = false;
} //older IE
return false;
}
function mouseUpListener(evt) {
theCanvas.addEventListener("mousedown", mouseDownListener, false);
window.removeEventListener("mouseup", mouseUpListener, false);
if (dragging) {
dragging = false;
window.removeEventListener("mousemove", mouseMoveListener, false);
}
}
function mouseMoveListener(evt) {
var posX;
var posY;
var shapeRad = shapes[dragIndex].rad;
var minX = shapeRad;
var maxX = theCanvas.width - shapeRad;
var minY = shapeRad;
var maxY = theCanvas.height - shapeRad;
//getting mouse position correctly
var bRect = theCanvas.getBoundingClientRect();
mouseX = (evt.clientX - bRect.left) * (theCanvas.width / bRect.width);
mouseY = (evt.clientY - bRect.top) * (theCanvas.height / bRect.height);
// Divide by width of canvas and multiply to get percentage out of 100
var DelayTime = ((mouseX / 240) * 100);
// Invert returned value to get percentage out of 100
var DelayFeedback = (100 - (mouseY / 240) * 100);
// Set delay time as a portion of 2seconds
delayEffect.delayTime.value = DelayTime / 100 * 2.0;
// set delay feedback gain as value of random number
delayFeedback.gain.value = (DelayFeedback / 100 * 1.0);
//clamp x and y positions to prevent object from dragging outside of canvas
posX = mouseX - dragHoldX;
posX = (posX < minX) ? minX : ((posX > maxX) ? maxX : posX);
posY = mouseY - dragHoldY;
posY = (posY < minY) ? minY : ((posY > maxY) ? maxY : posY);
shapes[dragIndex].x = posX;
shapes[dragIndex].y = posY;
drawScreen();
}
function hitTest(shape, mx, my) {
var dx;
var dy;
dx = mx - shape.x;
dy = my - shape.y;
//a "hit" will be registered if the distance away from the center is less than the radius of the circular object
return (dx * dx + dy * dy < shape.rad * shape.rad);
}
function drawShapes() {
var i;
for (i = 0; i < numShapes; i++) {
context.fillStyle = shapes[i].color;
context.beginPath();
context.arc(shapes[i].x, shapes[i].y, shapes[i].rad, 0, 2 * Math.PI, false);
context.closePath();
context.fill();
}
}
function drawScreen() {
context.fillStyle = "#000000";
context.fillRect(0, 0, theCanvas.width, theCanvas.height);
drawShapes();
}
}
window.addEventListener("load", windowLoadHandler, false);
function windowLoadHandler() {
canvasApp('delayPad');
}
There are still a few shortcomings, for instance the mouseMoveListener, although constricting the movement of the circle, will continue to increase your x & y values. Meaning you'll either have to use your existing listeners to check when the drag event has exited the circle, or much more simply, you could set an upper limit to your X and Y values.
You'll have to create an object which will store your x and y values.
In below example I called it pad.
This object will serve both your canvas visualization, and your audio processing.
These are both outputs (respectively visual and audio), while the input will be user gesture (e.g mousemove).
The inputs update the pad object, while outputs read it.
[Note]: This example will only work in newest Chrome and Firefox since it uses MediaElement.captureStream() which is not yet widely implemented.
const viz_out = canvas.getContext('2d');
let aud_out, mainVolume;
// our pad object holding the coordinates
const pad = {
x: 0,
y: 0,
down: false,
rad: 10
};
let canvRect = canvas.getBoundingClientRect();
function mousemove(event) {
if (!aud_out || !pad.down) {
return;
}
pad.x = event.clientX - canvRect.left;
pad.y = canvRect.height - (event.clientY - canvRect.top); // inverts y axis
// all actions are splitted
updateViz();
updateAud();
updateLog();
}
viz_out.setTransform(1, 0, 0, -1, 0, 300) // invert y axis on the canvas too
// simply draws a circle where at our pad's coords
function updateViz() {
viz_out.clearRect(0, 0, canvas.width, canvas.height);
viz_out.beginPath();
viz_out.arc(pad.x, pad.y, pad.rad, 0, Math.PI * 2);
viz_out.fill();
}
// You'll do it as you wish, here it just modifies a biquadFilter
function updateAud() {
const default_freq = 350;
const max_freq = 6000;
const y_ratio = pad.y / 300;
aud_out.frequency.value = (default_freq + (max_freq * y_ratio)) - default_freq;
aud_out.Q.value = (pad.x / 300) * 10;
mainVolume.value = 1 + ((pad.y + pad.x) / 75);
}
function updateLog() {
log.textContent = `x:${~~pad.x} y:${~~pad.y}`;
}
canvas.addEventListener('mousedown', e => pad.down = true);
canvas.addEventListener('mouseup', e => pad.down = false);
canvas.addEventListener('mousemove', mousemove);
btn.onclick = e => {
btn.textContent = 'stop';
startLoadingAudio();
btn.onclick = e => {
mainVolume.value = 0;
}
}
window.onscroll = window.onresize = e => canvRect = canvas.getBoundingClientRect();
function startLoadingAudio() {
const audio = new Audio();
audio.loop = true;
audio.muted = true;
audio.onloadedmetadata = e => {
audio.play();
const stream = audio.captureStream ? audio.captureStream() : audio.mozCaptureStream();
initAudioProcessor(stream);
updateLog();
window.onscroll();
updateViz();
}
// FF will "taint" the stream, even if the media is served with correct CORS...
fetch("https://dl.dropboxusercontent.com/s/8c9m92u1euqnkaz/GershwinWhiteman-RhapsodyInBluePart1.mp3").then(resp => resp.blob()).then(b => audio.src = URL.createObjectURL(b));
function initAudioProcessor(stream) {
var a_ctx = new AudioContext();
var gainNode = a_ctx.createGain();
var biquadFilter = a_ctx.createBiquadFilter();
var source = a_ctx.createMediaStreamSource(stream);
source.connect(biquadFilter);
biquadFilter.connect(gainNode);
gainNode.connect(a_ctx.destination);
aud_out = biquadFilter;
mainVolume = gainNode.gain;
biquadFilter.type = "bandpass";
}
}
canvas {
border: 1px solid;
}
<button id="btn">
start
</button>
<pre id="log"></pre>
<canvas id="canvas" width="300" height="300"></canvas>
How to set on click event in moving object in canvas? Also how to move the object bottom to top in canvas.I am newly in javascript i am going to develop the sample like when the page open, objects like square and circle randomly come from bottom of the page and move to top automatically.
You need to establish an array that will have your moving objects in it. When the onclick handler fires, check to see if the coordinates of the click are inside any of the objects in the array.
On each animation frame, move your objects up by subtracting some of the y coordinate from each object.
//width and height of canvas...
var rW = 400;
var rH = 500;
var coinImage = getCoinImage();
var coinsOnScreen = [];
var risingSpeed = 100; //pixels per second...
var coinSize = 75;
var lastAnimationTime = 0;
var howLongUntilNextCoin = 1000;
var nextCoinOnScreen = 0;
function doDraw() {
var can = document.getElementById("myCanvas");
can.width = rW;
can.height = rH;
var context = can.getContext("2d");
//Erase the canvas
context.fillStyle = "#FFFFFF";
context.fillRect(0, 0, rW, rH);
if (new Date().getTime() - nextCoinOnScreen > 0) {
var newX = Math.floor(Math.random() * rW) + 1;
var newY = rH + 50;
var newCoin = {
x: newX,
y: newY
};
coinsOnScreen.push(newCoin);
nextCoinOnScreen = new Date().getTime() + howLongUntilNextCoin;
}
//Now draw the coins
if (lastAnimationTime != 0) {
var deltaTime = new Date().getTime() - lastAnimationTime;
var coinRisePixels = Math.floor((deltaTime * risingSpeed) / 1000);
var survivingCoins = [];
for (var i = 0; i < coinsOnScreen.length; i++) {
var coin = coinsOnScreen[i];
coin.y = coin.y - coinRisePixels;
//the stl variable controlls the alpha of the image
if (coin.y + 50 > 0) {
context.drawImage(coinImage, coin.x, coin.y);
//this coin is still on the screen, so promote it to the new array...
survivingCoins.push(coin);
}
}
coinsOnScreen = survivingCoins;
}
lastAnimationTime = new Date().getTime();
//Wait, and then call this function again to animate:
setTimeout(function() {
doDraw();
}, 30);
}
function setupClickHandler() {
var can = document.getElementById("myCanvas");
//Here is the onclick handler
can.onclick = function(e) {
var x = e.clientX;
var y = e.clientY;
var survivingCoins = [];
for (var i = 0; i < coinsOnScreen.length; i++) {
var coin = coinsOnScreen[i];
//check to see if this coin has been clicked...
if (x > coin.x && x < coin.x + coinSize && y > coin.y && y < coin.y + coinSize) {
//ths coin will disappear because it is not inserted into the new array...
console.log("Coin was clicked!! " + x + " " + y);
} else {
survivingCoins.push(coin);
}
}
coinsOnScreen = survivingCoins;
};
}
doDraw();
setupClickHandler();
function getCoinImage() {
var image = new Image(50, 50);
image.src = "data:image/png;base64,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";
return image;
}
<canvas id="myCanvas"></canvas>
I made this (run snippet below)
var Canvas = document.getElementById('c');
var ctx = Canvas.getContext('2d');
var resize = function() {
Canvas.width = Canvas.clientWidth;
Canvas.height = Canvas.clientHeight;
};
window.addEventListener('resize', resize);
resize();
var elements = [];
var presets = {};
presets.shard = function (x, y, s, random, color) {
return {
x: x,
y: y,
draw: function(ctx, t) {
this.x += 0;
this.y += 0;
var posX = this.x + + Math.sin((50 + x + (t / 10)) / 100) * 5;
var posy = this.y + + Math.sin((55 + x + (t / 10)) / 100) * 7;
ctx.beginPath();
ctx.fillStyle = color;
ctx.moveTo(posX, posy);
ctx.lineTo(posX+random,posy+random);
ctx.lineTo(posX+random,posy+random);
ctx.lineTo(posX+0,posy+50);
ctx.closePath();
ctx.fill();
}
}
};
for(var x = 0; x < Canvas.width; x++) {
for(var y = 0; y < Canvas.height; y++) {
if(Math.round(Math.random() * 60000) == 1) {
var s = ((Math.random() * 5) + 1) / 10;
if(Math.round(Math.random()) == 1){
var random = Math.floor(Math.random() * 100) + 10;
var colorRanges = ['#8c8886', '#9c9995'];
var color = colorRanges[Math.floor(Math.random() * colorRanges.length)];
elements.push(presets.shard(x, y, s, random, color));
}
}
}
}
setInterval(function() {
ctx.clearRect(0, 0, Canvas.width, Canvas.height);
var time = new Date().getTime();
for (var e in elements)
elements[e].draw(ctx, time);
}, 10);
<canvas id="c" width="1000" height="1000"\>
I just need to add one feature to be able to use it on the site I'm building it for. Some of the floating shards need to be blurred to give a sense of depth.
Can Canvas do this, and if so, how?
context.filter = 'blur(10px)';
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter
I used this few months ago, maybe it could work for you as well :
var canvas = document.getElementById("heroCanvas");
var canvasContext = canvas.getContext("2d");
var canvasBackground = new Image();
canvasBackground.src = "image.jpg";
var drawBlur = function() {
// Store the width and height of the canvas for below
var w = canvas.width;
var h = canvas.height;
// This draws the image we just loaded to our canvas
canvasContext.drawImage(canvasBackground, 0, 0, w, h);
// This blurs the contents of the entire canvas
stackBlurCanvasRGBA("heroCanvas", 0, 0, w, h, 100);
}
canvasBackground.onload = function() {
drawBlur();
}
Here the source : http://zurb.com/playground/image-blur-texture