JavaScript canvas throws an Error, but works anyway - javascript

I am making this background for a page drawing random lines. The lines are being drawn and it looks as it was supposed to but when I look into the console I get about ~10 errors every second. It says it cannot read startX and starY. When I change it to x and why it does not draw the lines anymore.
var sandbox = document.getElementById('sandbox');
ctx = sandbox.getContext('2d');
var referencePoint = function(x, y) {
this.startX = x;
this.startY = y;
};
const progressPoints = [];
for (let i = 0; i < 15; i++) {
let x = Math.floor(Math.random() * sandbox.width);
let y = Math.floor(Math.random() * sandbox.height);
progressPoints.push(new referencePoint(x, y));
};
ctx.strokeStyle= "grey";
ctx.moveTo(progressPoints[0].x, progressPoints[0].y);
It supposedly cannot read those startX and startY:
var counter = 1,
interval = setInterval(function() {
var point = progressPoints[counter];
ctx.lineTo(point.startX, point.startY);
//alert(point.startX, point.startY)
ctx.stroke();
if(counter >= progressPoints.lenght){
clearInterval(interval);
};
counter++
}, 140);
(function() {
var contentBox = $('div.content-box'),
activeContent = contentBox.find('div.active-content'),
pageTransitionOverlay = contentBox.find('div.page-transition-overlay'),
navBtn = $('a.nav-btn'),
hiddenContent = $('div.hidden-content');
navBtn.on('click', function(e) {
var self = $(this),
moveToActive = hiddenContent.find('div.' + self.data('target-class'));
contentBox.addClass('transitionEffect');
pageTransitionOverlay.fadeIn(300, function() {
// Change content
self.closest('div.content-wrapper').appendTo(hiddenContent);
moveToActive.appendTo(activeContent);
// Transition transitionEffect
contentBox.removeClass('transitionEffect');
pageTransitionOverlay.fadeOut(300);
});
e.preventDefault();
});
})();

So it seems that length is too much, try 1 less
if (counter >= progressPoints.length - 1) { ... }
var sandbox = document.getElementById('sandbox');
ctx = sandbox.getContext('2d');
var referencePoint = function(x, y) {
this.startX = x;
this.startY = y;
};
const progressPoints = [];
for (let i = 0; i < 15; i++) {
let x = Math.floor(Math.random() * sandbox.width);
let y = Math.floor(Math.random() * sandbox.height);
progressPoints.push(new referencePoint(x, y));
};
ctx.strokeStyle = "grey";
ctx.moveTo(progressPoints[0].x, progressPoints[0].y);
var counter = 1,
interval = setInterval(function() {
var point = progressPoints[counter];
ctx.lineTo(point.startX, point.startY);
//alert(point.startX, point.startY)
ctx.stroke();
if (counter >= progressPoints.length - 1) {
clearInterval(interval);
};
counter++
}, 140);
(function() {
var contentBox = $('div.content-box'),
activeContent = contentBox.find('div.active-content'),
pageTransitionOverlay = contentBox.find('div.page-transition-overlay'),
navBtn = $('a.nav-btn'),
hiddenContent = $('div.hidden-content');
navBtn.on('click', function(e) {
var self = $(this),
moveToActive = hiddenContent.find('div.' + self.data('target-class'));
contentBox.addClass('transitionEffect');
pageTransitionOverlay.fadeIn(300, function() {
// Change content
self.closest('div.content-wrapper').appendTo(hiddenContent);
moveToActive.appendTo(activeContent);
// Transition transitionEffect
contentBox.removeClass('transitionEffect');
pageTransitionOverlay.fadeOut(300);
});
e.preventDefault();
});
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<canvas id="sandbox"></canvas>

Related

Problem with adding multiple images to the elements (javascript loop Issue)

I would like to add multiple photos from the Array in this code to the elements, but it adds just one photo from the Array to the first Element.
I tried adding for loop, but I dont know where to start and where to end the loop. Could you please take a look to the code using the link (codepen)?
thank you
let zoomLevel = 1;
const images = [
{
thumb: 'http://localhost:8080/links/works/Print/001.webp',
hires: 'http://localhost:8080/links/works/Print/001.webp'
},
{
thumb: 'https://tasvir-graphic.de/links/works/digital/unterwelt.webp',
hires: 'https://tasvir-graphic.de/links/works/digital/unterwelt.webp'
}
]
// set to random image
let img = images[Math.floor(Math.random() * images.length)];
image.getElementsByTagName('a')[0].setAttribute('href', img.hires);
image.getElementsByTagName('img')[0].setAttribute('src', img.thumb);
const preloadImage = url => {
let img = new Image();
img.src = url;
}
preloadImage(img.hires);
const enterImage = function(e) {
zoom.classList.add('show', 'loading');
clearTimeout(clearSrc);
let posX, posY, touch = false;
if (e.touches) {
posX = e.touches[0].clientX;
posY = e.touches[0].clientY;
touch = true;
} else {
posX = e.clientX;
posY = e.clientY;
}
You can check this better using Codepen HERE.
const image = document.querySelectorAll('.image');
/* Store the number of all elements with css class 'image' */
let imageElementsCount = image.length;
for (index = 0; index < imageElementsCount; index++)
{
let arrayElementPos = Math.floor(Math.random() * images.length);
/* Receive the requested element from array with image objects */
let imageObject = images[arrayElementPos];
preloadImage(imageObject.hires);
/* Assign received image properties to your html element */
image[index].getElementsByTagName('a')[0].setAttribute('href', imageObject.hires);
image[index].getElementsByTagName('img')[0].setAttribute('src', imageObject.thumb);
image[index].addEventListener('mouseover', enterImage);
image[index].addEventListener('touchstart', enterImage);
image[index].addEventListener('mouseout', leaveImage);
image[index].addEventListener('touchend', leaveImage);
image[index].addEventListener('mousemove', move);
image[index].addEventListener('touchmove', move);
image[index].addEventListener('wheel', e =>
{
e.preventDefault();
e.deltaY > 0 ? zoomLevel-- : zoomLevel++;
if (zoomLevel < 1) zoomLevel = 1;
if (zoomLevel > 5) zoomLevel = 5;
console.log(`zoom level: ${zoomLevel}`);
zoom.style.transform = `scale(${zoomLevel})`;
});
}
The loop is working until all founded divs got an assignment.
ToDos:
Remove in line
const image = document.querySelectorAll('.image')[0];
the [0].
Next step: Take a look into the body of for loop. Remove your lines of code in your original code
Thank you #Reporter, but I've allready done this editing my code for two days. :)
const zoo = document.querySelectorAll('.zoom');
const zooImg = document.querySelectorAll('.zoom-image');
const pic = document.querySelectorAll(".image");
let clearSrc;
let zoomLevel = 1;
const digiImgs = [{
thumb: 'https://tasvir-graphic.de/links/works/digital/MuZe.webp',
hires: 'https://tasvir-graphic.de/links/works/digital/MuZe.webp'
},
{
thumb: 'https://tasvir-graphic.de/links/works/digital/unterwelt.webp',
hires: 'https://tasvir-graphic.de/links/works/digital/unterwelt.webp'
},
{
thumb: 'https://tasvir-graphic.de/links/works/digital/takeCare.webp',
hires: 'https://tasvir-graphic.de/links/works/digital/takeCare.webp'
},
]
// set to random image
for (var i = 0; i < pic.length; i++) {
let img = digiImgs[i];
pic[i].getElementsByTagName('a')[0].setAttribute('href', img.hires);
pic[i].getElementsByTagName('img')[0].setAttribute('src', img.thumb);
const preloadImage = url => {
let img = new Image();
img.src = url;
}
preloadImage(img.hires);
const enterImage = function (e) {
var zoo = this.parentNode.childNodes[3];
zoo.classList.add('show', 'loading');
clearTimeout(clearSrc);
let posX, posY, touch = false;
if (e.touches) {
posX = e.touches[0].clientX;
posY = e.touches[0].clientY;
touch = true;
} else {
posX = e.clientX;
posY = e.clientY;
}
touch
?
zoo.style.top = `${posY - zoo.offsetHeight / 1.25}px` :
zoo.style.top = `${posY - zoo.offsetHeight / 2}px`;
zoo.style.left = `${posX - zoo.offsetWidth / 2}px`;
let originalImage = this.getElementsByTagName('a')[0].getAttribute('href');
var zoImg = this.parentNode.childNodes[3].childNodes[1];
zoImg.setAttribute('src', originalImage);
// remove the loading class
zoImg.onload = function () {
setTimeout(() => {
zoo.classList.remove('loading');
}, 500);
}
}
const leaveImage = function () {
// remove scaling to prevent non-transition
var zoImg = this.parentNode.childNodes[3].childNodes[1];
var zoo = this.parentNode.childNodes[3];
zoo.style.transform = null;
zoomLevel = 1;
zoo.classList.remove('show');
clearSrc = setTimeout(() => {
zoImg.setAttribute('src', '');
}, 250);
}
const move = function (e) {
e.preventDefault();
var zoImg = this.parentNode.childNodes[3].childNodes[1];
var zoo = this.parentNode.childNodes[3];
let posX, posY, touch = false;
if (e.touches) {
posX = e.touches[0].clientX;
posY = e.touches[0].clientY;
touch = true;
} else {
posX = e.clientX;
posY = e.clientY;
}
// move the zoom a little bit up on mobile (because of your fat fingers :<)
touch ?
zoo.style.top = `${posY - zoo.offsetHeight / 1.25}px` :
zoo.style.top = `${posY - zoo.offsetHeight / 2}px`;
zoo.style.left = `${posX - zoo.offsetWidth / 2}px`;
let percX = (posX - this.offsetLeft) / this.offsetWidth,
percY = (posY - this.offsetTop) / this.offsetHeight;
let zoomLeft = -percX * zoImg.offsetWidth + (zoo.offsetWidth / 2),
zoomTop = -percY * zoImg.offsetHeight + (zoo.offsetHeight / 2);
zoImg.style.left = `${zoomLeft}px`;
zoImg.style.top = `${zoomTop}px`;
}
pic[i].addEventListener('mouseover', enterImage);
pic[i].addEventListener('touchstart', enterImage);
pic[i].addEventListener('mouseout', leaveImage);
pic[i].addEventListener('touchend', leaveImage);
pic[i].addEventListener('mousemove', move);
pic[i].addEventListener('touchmove', move);
pic[i].addEventListener('wheel', e => {
var zoo = e.target.parentNode.parentNode.parentNode.childNodes[3];
console.log(zoo);
e.preventDefault();
e.deltaY > 0 ? zoomLevel-- : zoomLevel++;
if (zoomLevel < 1) zoomLevel = 1;
if (zoomLevel > 3) zoomLevel = 3;
console.log(`zoom level: ${zoomLevel}`);
zoo.style.transform = `scale(${zoomLevel})`;
});
}
but there is a problem with the touch. When I touch using mobile, the photo works like a link and opens the photo. How to use preventDefault Touch?

mxGraph straight parallel edges?

Is there any solution for this? We need parallel edges, but not that way how ParallelEdgeLayout makes that.
I tried to rewrite the layout function of parallel layout to move the edges, but edges has no usable geometry: x, y, width, height are 0. There I couldn't move them anywhere.
Tried to use setStyle, but did not do anything:
var s = model.getStyle(parallels[i]) + 'entryX='+x0+';exitX='+x0+';'
console.log(s)
model.setStyle(parallels[i], s);
Oh my God! Here is a solution. Not the dream edges, but almost... Maybe there are more beautiful solutions (post one), but this is mine for showing real parallel edges:
var spx = 1 / 22;
var spy = 1 / 8;
var x0 = 0.5;
var y0 = 0.5;
for (var i = 0; i < parallels.length; i++) {
var source = view.getVisibleTerminal(parallels[i], true);
var target = view.getVisibleTerminal(parallels[i], false);
var src = model.getGeometry(source);
var trg = model.getGeometry(target);
var srcx = src.x, srcy = src.y, trgx = trg.x, trgy = trg.y;
if (parallels[i].getParent() != source.getParent()) {
var pGeo = model.getGeometry(source.getParent());
srcx = src.x + pGeo.x;
srcy = src.y + pGeo.y;
}
if (parallels[i].getParent() != target.getParent()) {
var pGeo = model.getGeometry(target.getParent());
trgx = trg.x + pGeo.x;
trgy = trg.y + pGeo.y;
}
var scx = srcx + src.width; // source element right
var scy = srcy + src.height; // source element bottom
var tcx = trgx + trg.width; // target element right
var tcy = trgy + trg.height; // target element bottom
var dx = tcx - scx; // len x
var dy = tcy - scy; // len y
var sourcePointX, sourcePointY, targetPointX, targetPointY;
if (Math.abs(dx) > Math.abs(dy)) { // horizontal
sourcePointY = y0;
targetPointY = y0;
if (srcx < trgx) { // left to right
sourcePointX = 1;
targetPointX = 0;
} else {
sourcePointX = 0;
targetPointX = 1;
}
} else {
sourcePointX = x0;
targetPointX = x0;
if (srcy < trgy) { // top to bottom
sourcePointY = 1;
targetPointY = 0;
} else {
sourcePointY = 0;
targetPointY = 1;
}
}
this.graph.setConnectionConstraint(parallels[i], parallels[i].source, true, new mxConnectionConstraint(new mxPoint(sourcePointX, sourcePointY), true));
this.graph.setConnectionConstraint(parallels[i], parallels[i].target, false, new mxConnectionConstraint(new mxPoint(targetPointX, targetPointY), true));
if (i % 2) {
x0 += spx * (i + 1);
y0 += spy * (i + 1);
} else {
x0 -= spx * (i + 1);
y0 -= spy * (i + 1);
}
}

javascript image slider start

I'm trying to understand javascript before going to jQuery and I made a simple image slider.
I ended up with the following code working well when I manually start it on browser console, and I can't figure out how to start it and if using Promise would do, and how.
Reduced code:
/*some variable declarations and value assignations*/
function cut(p1){
for (var i = 0; i < cuts; i++){
/*canvas working with path pattern and fill*/
slice[p1][i] = new Image();
slice[p1][i].src = canvas.toDataURL();
}
}
function slider(){
/*time based image selection and canvas clear*/
for (var i = 0; i < 10; i++){
y = /*timebased calc*/;
if(y<0){y=0;}
ctx.drawImage(slice[im][i], 0, y);
}
window.requestAnimationFrame(slider);
}
img[0].onload = function() {cut(0);};
img[1].onload = function() {cut(1);};
Full code:
var height = 500, width = 707, cuts = 10, cW = Math.ceil(width/cuts);
var img = [new Image(), new Image()];
var slice = [];
for (var i = 0; i < img.length; i++){
slice[i] = [];
}
var x = [];
for (var i=0; i<cuts; i++){
x[i]=Math.ceil(((i+1)*width)/cuts);
}
function cut(p1){
for (var i = 0; i < cuts; i++){
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
var context = canvas.getContext('2d');
var pat = context.createPattern( img[p1], 'no-repeat' );
context.fillStyle = pat;
context.beginPath();
context.moveTo(x[i], 0);
context.lineTo(x[i], height);
context.lineTo(x[i]-cW, height);
context.lineTo(x[i]-cW, 0);
context.closePath();
context.fill();
slice[p1][i] = new Image();
slice[p1][i].src = canvas.toDataURL();
}
}
var canv = document.createElement('canvas');
document.body.appendChild(canv);
canv.width = width;
canv.height = height;
var ctx = canv.getContext('2d');
var sTime= 0;
function slider(){
var t = (performance.now() - sTime) % 10000;
if(t%5000 === 2000){
ctx.clear();
}
var im = 0;
if(t >= 5000){
im = 1;
} else {
im = 0;
}
for (var i = 0; i < 10; i++){
t = t%5000;
y = 2000-((t)+(i*100));
if(y<0){y=0;}
ctx.drawImage(slice[im][i], 0, y);
}
window.requestAnimationFrame(slider);
}
CanvasRenderingContext2D.prototype.clear = function () {this.clearRect(0, 0, this.canvas.width, this.canvas.height);}
img[0].onload = function() {cut(0);};
img[1].onload = function() {cut(1);};
img[0].src = 'mountain.jpg';
img[1].src = 'beach.jpg';
Haven't tested this but it might come close:
function imageLoader(imagePaths, onLoad, onFinished) {
var images = [];
var arrayLength = imagePaths.length;
function callback() {
if(--arrayLength === 0) onFinished();
}
imagePaths.forEach(function(imagePath, index) {
var image = new Image();
image.onload(onLoad(index, callback));
image.src = imagePath;
images[index] = image;
});
return images;
}
modify cut() to:
function cut(p1, cb){
//.
//.
//.
cb();
}
replace
img[0].onload = function() {cut(0);};
img[1].onload = function() {cut(1);};
img[0].src = 'mountain.jpg';
img[1].src = 'beach.jpg';
with:
img = imageLoader(['mountain.jpg', 'beach.jpg'], cut, slider);

HTML5 & javascript - drawImage seems to trigger after animation completed

I'm trying to create the following animation:
- when the page loads, I load the 2 components of my logo and draw them onto the canvas
- after clicking the animate button, both images should smoothly move up to the top of the page and shrink
However, it seems that the drawImage() only takes place somewhere after the entire animation has been completed even though I can see it being executed at the right time in the console. Commenting out the clearRect function also shows me that every frame is actually drawn onto the screen, but sadly they all appear together after the animation should be completed.
I'm pretty new to canvases and relevant tutorials on such animations are scarce and don't get me much further.
Here's the relevant script:
<script type="text/javascript">
var logoCanvas;
var logoContext;
var direction = 1;
var logoAnimationDuration = 2000; //millisec
var frameSpeed = 30/1000; //frames per second
var logoImageRatio = 0;
var logoTextRatio = 0;
var initialLogoImageHeight = 0;
var initialLogoTextHeight = 0;
var initialLogoImageTop = 0;
var initialLogoImageLeft = 0;
var initialLogoTextTop = 0;
var initialLogoTextLeft = 0;
var newLogoImageLeft = 0;
var logoImageWidth = 0;
var logoImageHeight = 0;
var logoTextWidth = 0;
var logoTextHeight = 0;
var logoImageTop = 0;
var logoImageLeft = 0;
var logoTextTop = 0;
var logoTextLeft = 0;
var logoImageLoaded = false;
var logoTextLoaded = false;
var logoImage = new Image();
var logoText = new Image();
function AnimateFrontPageCanvas() {
if(logoCanvas.height <= $('#Page_0').height()) {
logoCanvas.height = $('#Page_0').height();
return;
}
if(logoImageHeight <= $('#Page_0').height() - 4) {
return;
}
if(logoImageTop <= 2) {
return;
}
//logoCanvas.height = parseFloat(logoCanvas.height) - (parseFloat(window.innerHeight) - parseFloat($('#Page_0').height())) * 1/frameSpeed * 1/logoAnimationDuration;
logoContext.clearRect(0, 0, logoCanvas.width, logoCanvas.height);
AnimateLogo();
setTimeout(AnimateFrontPageCanvas(), 1/frameSpeed);
}
function AnimateLogo() {
AnimateLogoImage();
AnimateLogoText();
}
function AnimateLogoImage() {
logoImageHeight = logoImageHeight - (initialLogoImageHeight - $('#Page_0').height() + 4) * (1/frameSpeed) * (1/logoAnimationDuration);
logoImageWidth = logoImageHeight*logoImageRatio;
logoImageTop = logoImageTop - (initialLogoImageTop - 2)*(1/frameSpeed) * (1/logoAnimationDuration);
logoImageLeft = logoImageLeft - (initialLogoImageLeft - newLogoImageLeft) * (1/frameSpeed) * (1/logoAnimationDuration);
logoContext.drawImage(logoImage, logoImageLeft, logoImageTop, logoImageWidth, logoImageHeight);
var time = new Date();
time = time.getTime();
console.log('logoimage drawn: ' + time);
}
function AnimateLogoText() {
logoTextHeight = logoTextHeight - (initialLogoTextHeight - $('#Page_0').height() + 4) * (1/frameSpeed) * (1/logoAnimationDuration);
logoTextWidth = logoTextHeight*logoTextRatio;
logoTextTop = logoTextTop - (initialLogoTextTop - 2) * (1/frameSpeed)*(1/logoAnimationDuration);
logoTextLeft = logoTextLeft - (initialLogoTextLeft - newLogoTextLeft)*(1/frameSpeed)*(1/logoAnimationDuration);
logoContext.drawImage(logoText, logoTextLeft, logoTextTop, logoTextWidth, logoTextHeight);
var time = new Date();
time = time.getTime();
console.log('logotext drawn: ' + time);
}
function InitiateFrontPageCanvas() {
logoImage.onload = function() {
logoImageLoaded = true;
AfterImagesLoadedActions();
}
logoImage.src = '/site_mats/images/logo_image.png';
logoText.onload = function() {
logoTextLoaded = true;
AfterImagesLoadedActions();
}
logoText.src = '/site_mats/images/logo_text.png';
}
function AfterImagesLoadedActions() {
if(logoImageLoaded && logoTextLoaded) {
logoImageRatio = logoImage.width/logoImage.height;
logoTextRatio = logoText.width/logoText.height;
if(logoImage.width > 0.8*logoCanvas.width) {
logoImage.width = 0.8*logoCanvas.width;
logoImage.height = logoImage.width/logoImageRatio;
}
if(logoText.width > 0.8*logoCanvas.width) {
logoText.width = 0.8*logoCanvas.width;
logoText.height = logoText.width/logoTextRatio;
}
if(parseFloat(logoImage.height) + parseFloat(logoText.height) > 0.66*logoCanvas.height) {
var x = (0.66*logoCanvas.height)/(parseFloat(logoImage.height) + parseFloat(logoText.height));
logoImage.height = x*logoImage.height;
logoImage.width = logoImage.height*logoImageRatio;
logoText.height = x*logoText.height;
logoText.width = logoText.height*logoTextRatio;
}
initialLogoImageHeight = logoImage.height;
initialLogoTextHeight = logoText.height;
logoImageHeight = logoImage.height;
logoImageWidth = logoImage.width;
logoTextHeight = logoText.height;
logoTextWidth = logoText.width;
initialLogoImageTop = parseFloat((logoCanvas.height-(parseFloat(logoImageHeight)+parseFloat(logoTextHeight)))/2);
initialLogoImageLeft = parseFloat((logoCanvas.width-logoImageWidth)/2);
initialLogoTextTop = parseFloat(((logoCanvas.height-(parseFloat(logoImageHeight)+parseFloat(logoTextHeight)))/2)+parseFloat(logoImageHeight));
initialLogoTextLeft = parseFloat((logoCanvas.width-logoImageWidth)/2);
logoImageTop = initialLogoImageTop;
logoImageLeft = initialLogoImageLeft;
logoTextTop = initialLogoTextTop;
logoTextLeft = initialLogoTextLeft;
newLogoImageLeft = parseFloat(2);
newLogoTextLeft = parseFloat((logoCanvas.width-$('#Page_0').height()*logoTextRatio)/2);;
logoContext.drawImage(logoText, logoTextLeft, logoTextTop, logoTextWidth, logoTextHeight);
logoContext.drawImage(logoImage, logoImageLeft, logoImageTop, logoImageWidth, logoImageHeight);
//remove onload from image objects
logoImage.onload = null;
logoText.onload = null;
}
}
function SetFrontPageCanvas() {
logoCanvas = document.getElementById('LogoCanvas');
logoContext = logoCanvas.getContext('2d');
logoCanvas.width = window.innerWidth;
logoCanvas.height = window.innerHeight;
logoContext.clearRect(0, 0, logoCanvas.width, logoCanvas.height);
InitiateFrontPageCanvas();
}
window.onload = function() {
SetFrontPageCanvas();
};
$(document).ready(function() {
windowWidth = $(window).width();
windowHeight = $(window).height();
});
$(window).resize(function() {
//alert($(window).width() + ' - ' + $(window).height());
logoImageLoaded = false;
logoTextLoaded = false;
SetFrontPageCanvas();
windowWidth = $(window).width();
windowHeight = $(window).height();
});
</script>
And here's the relevant html:
<canvas id="LogoCanvas" style="position:absolute;top:0;left:0;z-index:1;"></canvas>
<div id="Page_0" style="position:absolute;top:0;left:0;z-index:5;width:100%;height:90px;">
<div align="center" style="position:fixed;bottom:5px;z-index:100;width:100%;">
<input type="button" onClick="AnimateFrontPageCanvas()" value="Animate">
</div>
If desired, the code can also be seen in action here: http://villa-gloria-katouna.com/site_mats/animation.php

Creating a bouncing box animation on canvas

I need to create an animation of dropping box, which supposed to bounce 10 times when it reaches a certain Y point on canvas, each time twice lower that the previous. So I have the animation of the dropping box, but I can't make the bounce work. Here are the functions that I wrote:
function dropBox(y, width, height) {
var img_box = new Image();
img_box.src = 'images/gift_box_small.png';
var box_y_pos = y;
if(y==0)
box_y_pos = y-img_box.naturalHeight;
img_box.onload = function(){
ctx_overlay.save();
ctx_overlay.clearRect(0,0,width,height);
ctx_overlay.drawImage(img_box, (width/2)-(img_box.naturalWidth/2), box_y_pos);
ctx_overlay.restore();
}
box_y_pos += 3;
var box_bottom_position = box_y_pos - img_box.naturalHeight;
if(box_y_pos+img_box.naturalHeight<height-25)
var loopTimer = setTimeout(function() {dropBox(box_y_pos, width, height)},24);
else
bounceBox(img_box, box_y_pos, box_y_pos, (height/2)-(img_box.naturalHeight/2), "up");
}
function bounceBox(img, img_final_pos, y, midway_pos, direction){
var midway = midway_pos;
var direction = direction;
var img_y_pos = y;
img.onload = function(){
ctx_overlay.save();
ctx_overlay.clearRect(0,0,docWidth,docHeight);
ctx_overlay.drawImage(img, (docWidth/2)-(img.naturalWidth/2), img_y_pos);
ctx_overlay.restore();
}
for(var i = 0; i < 10; i++){
if(direction=="up"){
//going up
if(img_y_pos>midway_){
img_y_pos -= 3;
var loopTimer = setTimeout(function() {bounceBox(img, img_final_pos, img_y_pos, midway_pos, "up")},24);
} else {
img_y_pos += 3;
midway = Math.floor(midway /= 2);
if(midway%2>0)
midway += 1;
var loopTimer = setTimeout(function() {bounceBox(img, img_final_pos, img_y_pos, midway_pos, "down")},24);
}
} else {
//going down
if(img_y_pos < img_final_pos){
img_y_pos += 3;
var loopTimer = setTimeout(function() {bounceBox(img, img_final_pos, img_y_pos, midway_pos, "down")},24);
}
}
}
}
JSFiddle: http://jsfiddle.net/n2derqgw/3/
Why isn't it working and how can I make it work?
To avoid getting a headache, you've better handle the animation within a single function called with a setInterval.
And keep all animation-related data in one object.
So the code below does not exactly what you want, but should get you started :
http://jsfiddle.net/n2derqgw/4/
Setup :
var canvas_overlay, ctx_overlay, docWidth, docHeight;
var img_box = new Image();
img_box.src = 'http://corkeynet.com/test/images/gift_box_small.png';
var mustBeReadyCount = 2; // must load image and window
img_box.onload = launchWhenReady;
window.onload = launchWhenReady;
var animationStep = '';
var boxAnimationData = {
animationStep: '',
y: 0,
maxY: 0,
bounceCount: 6,
direction: -1,
bounceHeight: 0
};
function launchWhenReady() {
mustBeReadyCount--;
if (mustBeReadyCount) return;
docWidth = window.innerWidth;
docHeight = window.innerHeight;
canvas_overlay = document.getElementById('canvas_overlay');
ctx_overlay = canvas_overlay.getContext('2d');
resizeCanvas(docWidth, docHeight);
boxAnimationData.animationStep = 'falling';
boxAnimationData.bounceHeight = docHeight / 2 - img_box.height;
setInterval(animateBox, 30);
};
More interesting code is here :
function animateBox() {
if (boxAnimationData.animationStep == 'falling') dropBox();
else if (boxAnimationData.animationStep == 'bouncing') bounceBox();
}
function dropBox() {
ctx_overlay.clearRect(0, 0, docWidth, docHeight);
boxAnimationData.y += 3;
if (boxAnimationData.y + img_box.height > docHeight) {
boxAnimationData.animationStep = 'bouncing';
}
ctx_overlay.drawImage(img_box, (docWidth / 2) - (img_box.width / 2), boxAnimationData.y);
}
function bounceBox() {
ctx_overlay.clearRect(0, 0, docWidth, docHeight);
boxAnimationData.y += boxAnimationData.direction * 3;
if (boxAnimationData.y + img_box.height > docHeight) {
// reached floor ? swap direction
boxAnimationData.direction *= -1;
// and reduce jump height
boxAnimationData.bounceHeight *= 3 / 2;
boxAnimationData.bounceCount--;
if (!boxAnimationData.bounceCount) boxAnimationData.animationStep = '';
} else if (boxAnimationData.y < boxAnimationData.bounceHeight) {
boxAnimationData.direction *= -1;
}
ctx_overlay.drawImage(img_box, (docWidth / 2) - (img_box.width / 2), boxAnimationData.y);
}

Categories

Resources