I have the following problem:
I create a Raphael canvas in a div. This happens as soon as the page is loaded and the initRadar() function is called:
var r;
var paper;
var c;
function initRadar(){
r = $( "#circ" );
paper = Raphael("circ", r.width(), r.height());
c = paper.circle(r.width()/2, r.height()/2, r.height()/2-2);
$(window).on("orientationchange",function(){
//redraw(); // <--- the way I wanted it
setTimeout(function(){ redraw(); }, 300); // <--- *yuck*
});
}
This functions perfectly so far. My problem starts when the orientation of the viewport changes. I thought I could add an event handle to the window, which fires, when the orientation changes and redraw the content. And it works... kind of. I wanted to call the second function:
function redraw(){
c.remove();
c = paper.circle(r.width()/2, r.height()/2, r.height()/2-2);
}
Whenever the orientation changes, this function redraws the content. And this also works... almost. The problem is, I have a race condition. Even though the orientation change event fired, the #circ div still has the old size and position. This leads to the strange effect, that when the viewport is in portrait mode, the landscape circle is drawn and vice versa.
My current solution is to use the timeout function (yuck), to wait a few ms so that the layout is done before I draw the circle. It works, but it is ugly and I don't want to have such a hack in my code.
Can someone point me in the direction how to solve this problem correctly?
Related
I made a simple canvas animation using a function which clears and redraws the canvas, and the calling requestAnimationFrame, It works awesome but when the window is blurred for long, say 10 secs, then the canvas clears itself and nothing's drawn. May anybody give an Idea why it's happening and how to solve it?
The structure of function is like :-
function drawFrame(time){
//clear and redraw to be understood as working functions in prototype ...
canvas.clear();
canvas.redraw();
requestAnimationFrame(drawFrame);
}
requestAnimationFrame(drawFrame);
I am adding a canvas to the DOM, and then using CreateJS to build a game. I am initialising a CreateJS ticker, and adding animations and graphics.
Everything works fine, but only once. If I remove the canvas and the game code, I can't add it again later on - the canvas just doesn't show anything anymore.
My question: how do I properly clear all CreateJS functions from memory, and start anew with a new canvas? It seems that CreateJS keeps holding on to old listeners and elements, even though I removed everything.
This is my code:
// remove canvas and then restart - this causes buggy behavior
this.removeAndRestart = function() {
document.getElementById("gamecontainer").innerHTML = '';
createjs.Ticker.removeAllEventListeners();
setTimeout(this.showGame, 1000);
}
// simply start the game - this works only the first time
this.showGame = function() {
document.getElementById("gamecontainer").innerHTML = '<canvas id="gamecanvas" width="900" height="400"></canvas>';
this.stage = new createjs.Stage("gamecanvas");
// create the ticker and update the stage
createjs.Ticker.setFPS(30);
createjs.Ticker.addEventListener("tick", tickHandler);
}
If you are changing canvases, or resetting the stage, make sure to remove the DOM events from the stage. From the docs:
enableDomEvents(Boolean enable)
Enables or disables the event listeners that stage adds to DOM elements (window, document and canvas). It is good practice to disable events when disposing of a Stage instance, otherwise the stage will continue to receive events from the page.
When changing the canvas property you must disable the events on the old canvas, and enable events on the new canvas or mouse events will not work as expected. For example:
myStage.enableDOMEvents(false);
myStage.canvas = anotherCanvas;
myStage.enableDOMEvents(true);
http://www.createjs.com/Docs/EaselJS/classes/Stage.html#method_enableDOMEvents
I am not sure if this will solve your problem, but it could help.
i recommend you to use this
//create listener tick
createjs.Ticker.addEventListener('tick',tick);
//remove listener tick
createjs.Ticker.removeEventListener('tick',tick);
//exemple stopped object moves in Y axe if it exceeds heigth of canvas
createjs.Ticker.addEventListener('tick',tick);
function tick(){
console.log( myBitmap.x +" "+myCanvas.width);
if (myBitmap.y < myCanvas.height){
myBitmap.y=myBitmap.y+10;
}else{
createjs.Ticker.removeEventListener('tick',tick);
}
scene.update();
}
Using canvas and mousemove I create a masking effect.
Example: FIDDLE
The masking effect works but on fast scrolling performance isn't ideal.
How can I improve the framerate?
I fixed it simply by using the window mouse coordinates, instead of the listener on the canvas (assuming you want the picture to just be black).
http://jsfiddle.net/gfZ5C/166/
I also changed to requestAnimationFrame, you'll notice a complete FPS difference in the movement of the circle, instead of it moving according to the listener.
window.onmousemove = function (e) {
circle.posX = e.pageX-can.offsetLeft;
circle.posY = e.pageY-can.offsetTop;
circle.hide = (circle.posX >= 550 || circle.posY >= 550) ? true : false;
}
if (!circle.hide) ctx.arc(circle.posX, circle.posY, 70, 0, Math.PI * 2, true);
I left it at 550, so that you could see it actually disappear, you can change it to a big number if you want the circle to just drag right off the canvas.
Also there is no lag on the circle following the mouse now.
Update:
Fixed the fiddle so that the circle adjusts for window offset too.
The offset is relevant to its parent element, so depending on how far deep your canvas is, you will have to subtract each elements offset that it is inside.
Update:
Switched to handle 'onmouse' events, this will work much better on a real site, because mousing over the iFrame doesn't work well, but it still works. Will work 100% as intended on a real site.
I'm working in a tool to draw in a canvas using the framework Paper.js
I got an issue using iPad. When I'm drawing with one finger, that works. When I'm drawing with two fingers, one in the canvas and one outside the canvas, the second finger event is caught by the event onMouseDrag, and that put some stroke from the first finger to the second finger, not a good behaviour for me.
Example:
At the beginning, I start to draw with one finger. After I put the second finger outside the canvas and I continue to move my first finger. This is what happen.
Do you have any idea to avoid event when I'm outside the canvas?
Thanks.
If you don't want the finger outside to be detected, limit the target to your canvas.
var canvasElement = document.getElementById('canvasId') //or element
tool.onMouseDrag = function(event) {
if (event.event.target === canvasElement) { //my target canvas was nested like this
path.add(event.point);
path.smooth();
}
}
Well, you could test event.point.isInside(view.bounds). This will likely kill your performance if you test it while drawing, but you could cull the points after you're finished.
I've created a html5 web app to display data, and to mimmic swipe gestures I've used A Jquery plugin Called Wipetouch. When a wipe gesture is triggered, all I do is redraw all of my data with new numbers via a javascript function. I've realized that this isn't the optimal solution as the images are static, and are currently being loaded every time I swipe. Any ideas would be great.
edit
var img01 = new Image();
enter code here
img01.onload = function () {
ctx.drawImage(img01, x, y, img01.width * 2, img01.height * 2);
ctx.fillStyle = "white";
//draw text
ctx.font = "bold 28pt Calibri";
ctx.fillText(monthname[date.getMonth()], x+51, y+135);
ctx.fillText(d[1], x+47, y+37);
}
img01.src = 'images/retail_car.png';
I apologize for not making this clear earlier. I'm drawing the images on my canvas, and this code is triggered each time the wipetouch plugin registers a swipe. I'd like to make everything stay in the canvas, so the CSS fix that was mentioned won't work in my case.
You could put the images in your html and give them a class in css that has display:none;. Then when you call the function you could change the class of the displayed image to one with display: block; or however you need them displayed. Just be sure to change the class back after you swipe so that the new image appears and the old image is no longer visible. That way they are not being generated over again each time you call the swipe.