"requestAnimationFrame" method is not working in the following example. Console doesn't show any error messsage. Then what is the error in this code?
html:
<body>
<div id="container">
<canvas id="canvas" width="1024" height="1024"></canvas>
</div>
<script type="text/javascript" src = "Jquery/easy.js"></script>
</body>
javascript:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var chop1 = new Image();
chop1.src = "img/chopper.png";
var chopperX = 0;
var chopperY = 0;
var ascent = 20;
function fly()
{
chopperY += ascent;
ctx.drawImage(chop1, chopperX, chopperY, 30, 80);
requestAnimationFrame(fly);
}
window.onload = function() {
init()
};
function init()
{
chop1.src = "img/chopper.png";
ctx.drawImage(chop1, 0, 0, 30, 80);
fly()
}
;
You probably want to scale the animation using the timestamp that's passed to the callback given to requestAnimationFrame. Use something like this:
var ascent = 20;
var limit = 5000;
var start = null;
function fly(timestamp) {
if (start === null) {
start = timestamp;
}
var progress = timestamp - start;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(chop1, 0, Math.min(progress / ascent, canvas.height),
chop1.width, chop1.height);
if (progress < limit) {
requestAnimationFrame(fly);
}
}
requestAnimationFrame(fly);
You can modify ascent and limit to increase/decrease the animation's speed and final position to taste.
As others have mentioned, be sure to use the correct requestAnimationFrame:
window.requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
More information:
https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame
You need to call your draw() from within the fly() here is how I got it working with comments to explain. You'll need to change your image's src to what it is in your own project since I didn't have your image.
Edit:
Added a way to draw image based on image size and made image turn around at edges of canvas. And here is a fiddle to show it in action:
Canvas Animation
JavaScript
/**
* Namespace to set up your animation
* #namespace
*/
var anim = (function() {
var exports = {};
// Make sure we use the right "requestAnimationFrame"
// For the right browser
window.requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
// Keep some variables for the namespace
var canvas = null, // The Canvas element to draw to
ctx = null, // The context of the canvas
chop1 = null, // The image that will get drawn
chopperX = 0, // The X position of the image
chopperY = 0, // The Y position of the image
ascent = 20; // How much to increment height by per anim
/**
* The function to get called by, and to perpetuate
* the requestAnimationFrame() function
* #returns {undefined}
*/
function fly() {
// Increment the height of the image
chopperY += ascent;
// Switch directions at bottom of canvas
if (chopperY > 1000) {
ascent = -ascent;
}
if (chopperY < 0) {
ascent = -ascent;
}
// Clear the canvas so the animation looks good
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw the image to the canvas
ctx.drawImage(chop1, chopperX, chopperY, chop1.width, chop1.height);
// Get ready to draw again on the next animation frame
requestAnimationFrame(fly);
}
/**
* Function to start the animation process
* #param {Canvas DOM Element} canvasElement The canvas to draw on
* #returns {undefined}
*/
exports.go = function(canvasElement) {
// Set the canvas we draw to
canvas = canvasElement;
// Get a context to draw to
ctx = canvas.getContext("2d");
// Create the image we want to draw
chop1 = new Image();
// Set the image's source
chop1.src = "../../img/dice.png";
// Start the animation process
window.requestAnimationFrame(fly);
};
// Let our functions get called from our namespace
return exports;
}());
/**
* Function that gives the canvas element to the namespace to animate
* #returns {undefined}
*/
function init() {
anim.go(document.getElementById("canvas"));
}
/**
* Function to start the initialization on a window load
* #returns {undefined}
*/
window.onload = init;
//init();
HTML
<body>
<div id="container">
<canvas id="canvas" width="1024" height="1024"></canvas>
</div>
</body>
Related
I want to build a UI with a joystick, To implement the joystick, I used the JoyStick js library: https://github.com/bobboteck/JoyStick
My code works in Firefox and Chrome on Windows 10, but on Android the joystick doesn't appear with the following error messages:
(index):1889 crbug/1173575, non-JS module files deprecated.
(anonymous) # (index):1889
chromewebdata/:1 Not allowed to load local resource: content://0#media/external/file/10769
My code:
controller.html
<!DOCTYPE html>
<html>
<head>
<title>drone controller</title>
<meta charset="utf-8">
<script src="joy.js"></script>
</head>
<body>
<!-- Example of FIXED or ABSOLUTE position -->
<div id="container" style="width:200px;height:200px;margin:50px;position:fixed;bottom:30px;left:500px;">
</div>
<div style="position:fixed;bottom:125px;left:750px;">
Posizione X:<input id="joy3PosizioneX" type="text"><br>
Posizione Y:<input id="joy3PosizioneY" type="text"><br>
Direzione:<input id="joy3Direzione" type="text"><br>
X :<input id="joy3X" type="text"><br>
Y :<input id="joy3Y" type="text">
</div>
<script>
var joy3 = new JoyStick('container');
// var joy3Param = { "title": "joystick3" };
// var Joy3 = new JoyStick('joy3Div', joy3Param);
var joy3IinputPosX = document.getElementById("joy3PosizioneX");
var joy3InputPosY = document.getElementById("joy3PosizioneY");
var joy3Direzione = document.getElementById("joy3Direzione");
var joy3X = document.getElementById("joy3X");
var joy3Y = document.getElementById("joy3Y");
setInterval(function(){ joy3IinputPosX.value=joy3.GetPosX(); }, 50);
setInterval(function(){ joy3InputPosY.value=joy3.GetPosY(); }, 50);
setInterval(function(){ joy3Direzione.value=joy3.GetDir(); }, 50);
setInterval(function(){ joy3X.value=joy3.GetX(); }, 50);
setInterval(function(){ joy3Y.value=joy3.GetY(); }, 50);
</script>
</body>
</html>
joy.js unmodified from github
var JoyStick = (function(container, parameters)
{
parameters = parameters || {};
var title = (typeof parameters.title === "undefined" ? "joystick" : parameters.title),
width = (typeof parameters.width === "undefined" ? 0 : parameters.width),
height = (typeof parameters.height === "undefined" ? 0 : parameters.height),
internalFillColor = (typeof parameters.internalFillColor === "undefined" ? "#00AA00" : parameters.internalFillColor),
internalLineWidth = (typeof parameters.internalLineWidth === "undefined" ? 2 : parameters.internalLineWidth),
internalStrokeColor = (typeof parameters.internalStrokeColor === "undefined" ? "#003300" : parameters.internalStrokeColor),
externalLineWidth = (typeof parameters.externalLineWidth === "undefined" ? 2 : parameters.externalLineWidth),
externalStrokeColor = (typeof parameters.externalStrokeColor === "undefined" ? "#008000" : parameters.externalStrokeColor),
autoReturnToCenter = (typeof parameters.autoReturnToCenter === "undefined" ? true : parameters.autoReturnToCenter);
// Create Canvas element and add it in the Container object
var objContainer = document.getElementById(container);
var canvas = document.createElement("canvas");
canvas.id = title;
if(width === 0) { width = objContainer.clientWidth; }
if(height === 0) { height = objContainer.clientHeight; }
canvas.width = width;
canvas.height = height;
objContainer.appendChild(canvas);
var context=canvas.getContext("2d");
var pressed = 0; // Bool - 1=Yes - 0=No
var circumference = 2 * Math.PI;
var internalRadius = (canvas.width-((canvas.width/2)+10))/2;
var maxMoveStick = internalRadius + 5;
var externalRadius = internalRadius + 30;
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var directionHorizontalLimitPos = canvas.width / 10;
var directionHorizontalLimitNeg = directionHorizontalLimitPos * -1;
var directionVerticalLimitPos = canvas.height / 10;
var directionVerticalLimitNeg = directionVerticalLimitPos * -1;
// Used to save current position of stick
var movedX=centerX;
var movedY=centerY;
// Check if the device support the touch or not
if("ontouchstart" in document.documentElement)
{
canvas.addEventListener("touchstart", onTouchStart, false);
canvas.addEventListener("touchmove", onTouchMove, false);
canvas.addEventListener("touchend", onTouchEnd, false);
}
else
{
canvas.addEventListener("mousedown", onMouseDown, false);
canvas.addEventListener("mousemove", onMouseMove, false);
canvas.addEventListener("mouseup", onMouseUp, false);
}
// Draw the object
drawExternal();
drawInternal();
/******************************************************
* Private methods
*****************************************************/
/**
* #desc Draw the external circle used as reference position
*/
function drawExternal()
{
context.beginPath();
context.arc(centerX, centerY, externalRadius, 0, circumference, false);
context.lineWidth = externalLineWidth;
context.strokeStyle = externalStrokeColor;
context.stroke();
}
/**
* #desc Draw the internal stick in the current position the user have moved it
*/
function drawInternal()
{
context.beginPath();
if(movedX<internalRadius) { movedX=maxMoveStick; }
if((movedX+internalRadius) > canvas.width) { movedX = canvas.width-(maxMoveStick); }
if(movedY<internalRadius) { movedY=maxMoveStick; }
if((movedY+internalRadius) > canvas.height) { movedY = canvas.height-(maxMoveStick); }
context.arc(movedX, movedY, internalRadius, 0, circumference, false);
// create radial gradient
var grd = context.createRadialGradient(centerX, centerY, 5, centerX, centerY, 200);
// Light color
grd.addColorStop(0, internalFillColor);
// Dark color
grd.addColorStop(1, internalStrokeColor);
context.fillStyle = grd;
context.fill();
context.lineWidth = internalLineWidth;
context.strokeStyle = internalStrokeColor;
context.stroke();
}
/**
* #desc Events for manage touch
*/
function onTouchStart(event)
{
pressed = 1;
}
function onTouchMove(event)
{
// Prevent the browser from doing its default thing (scroll, zoom)
event.preventDefault();
if(pressed === 1 && event.targetTouches[0].target === canvas)
{
movedX = event.targetTouches[0].pageX;
movedY = event.targetTouches[0].pageY;
// Manage offset
if(canvas.offsetParent.tagName.toUpperCase() === "BODY")
{
movedX -= canvas.offsetLeft;
movedY -= canvas.offsetTop;
}
else
{
movedX -= canvas.offsetParent.offsetLeft;
movedY -= canvas.offsetParent.offsetTop;
}
// Delete canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// Redraw object
drawExternal();
drawInternal();
}
}
function onTouchEnd(event)
{
pressed = 0;
// If required reset position store variable
if(autoReturnToCenter)
{
movedX = centerX;
movedY = centerY;
}
// Delete canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// Redraw object
drawExternal();
drawInternal();
//canvas.unbind('touchmove');
}
/**
* #desc Events for manage mouse
*/
function onMouseDown(event)
{
pressed = 1;
}
function onMouseMove(event)
{
if(pressed === 1)
{
movedX = event.pageX;
movedY = event.pageY;
// Manage offset
if(canvas.offsetParent.tagName.toUpperCase() === "BODY")
{
movedX -= canvas.offsetLeft;
movedY -= canvas.offsetTop;
}
else
{
movedX -= canvas.offsetParent.offsetLeft;
movedY -= canvas.offsetParent.offsetTop;
}
// Delete canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// Redraw object
drawExternal();
drawInternal();
}
}
function onMouseUp(event)
{
pressed = 0;
// If required reset position store variable
if(autoReturnToCenter)
{
movedX = centerX;
movedY = centerY;
}
// Delete canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// Redraw object
drawExternal();
drawInternal();
//canvas.unbind('mousemove');
}
/******************************************************
* Public methods
*****************************************************/
/**
* #desc The width of canvas
* #return Number of pixel width
*/
this.GetWidth = function ()
{
return canvas.width;
};
/**
* #desc The height of canvas
* #return Number of pixel height
*/
this.GetHeight = function ()
{
return canvas.height;
};
/**
* #desc The X position of the cursor relative to the canvas that contains it and to its dimensions
* #return Number that indicate relative position
*/
this.GetPosX = function ()
{
return movedX;
};
/**
* #desc The Y position of the cursor relative to the canvas that contains it and to its dimensions
* #return Number that indicate relative position
*/
this.GetPosY = function ()
{
return movedY;
};
/**
* #desc Normalizzed value of X move of stick
* #return Integer from -100 to +100
*/
this.GetX = function ()
{
return (100*((movedX - centerX)/maxMoveStick)).toFixed();
};
/**
* #desc Normalizzed value of Y move of stick
* #return Integer from -100 to +100
*/
this.GetY = function ()
{
return ((100*((movedY - centerY)/maxMoveStick))*-1).toFixed();
};
/**
* #desc Get the direction of the cursor as a string that indicates the cardinal points where this is oriented
* #return String of cardinal point N, NE, E, SE, S, SW, W, NW and C when it is placed in the center
*/
this.GetDir = function()
{
var result = "";
var orizontal = movedX - centerX;
var vertical = movedY - centerY;
if(vertical >= directionVerticalLimitNeg && vertical <= directionVerticalLimitPos)
{
result = "C";
}
if(vertical < directionVerticalLimitNeg)
{
result = "N";
}
if(vertical > directionVerticalLimitPos)
{
result = "S";
}
if(orizontal < directionHorizontalLimitNeg)
{
if(result === "C")
{
result = "W";
}
else
{
result += "W";
}
}
if(orizontal > directionHorizontalLimitPos)
{
if(result === "C")
{
result = "E";
}
else
{
result += "E";
}
}
return result;
};
});
Thanks for your help!
I take it you have copied the files to the phone's local storage, and are trying to open them from there in Chrome?
I suspect it not working is intentional. Access to local files can be quite restricted in web browsers in general (since it doesn't really work together with the origin-based security model), and access to local storage on Android is an equally complicated subject.
If you're planning to serve this on the web, and just want to test whether it works in Chrome on Android, the path of least resistance will probably be to just serve it over HTTP. How to do that is probably outside the scope of the question, but for example (as described near the end of this page) Python's http.server module can be used as a simple command-line web server for testing purposes, assuming you have a computer and a phone in the same local network (or use adb port forwarding).
Edit: I've just tested your files using the above method (with python3 -m http.server), and it does show the green joystick on Chrome 92 on Android.
Alternatively, if your end goal is to package this into an Android app, there are specific APIs (such as the WebViewAssetLoader) that allow you to serve the local HTTP and JS assets in a way that will not run into problems like this.
This gamepad API is relatively new and still now experimental. To my knowledge, only latest verson of Crome for android supports it. Update your crome browser on android and try. This should work.
I am new to HTML 5 and JavaScript. I plan to move a line automatically on my canvas until I hit the stop button. So far, I have found an example that shows how to move a line continuously. I tried to add stop button functionality to this example.
However, the line stopped moving automatically. Instead, it moves a little bit each time I press stop. In order to find the error, I checked my developer console. The console suggested that maximum call stack size has exceeded.
Additionally, I plan to have two buttons that can move the line up and down is it possible? If yes, should pass a different points array to draw function. For example, if somebody clicks left, should I pass a new array in which x coordinate is fixed but y is increasing?
I have the following code:
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<button type="button" id="stop">Stop</button>
<button type="button" id="left">Left</button>
<button type="button" id="right">Right</button>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
window.requestAnimFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function ( /* function */ callback, /* DOMElement */ element) {
window.setTimeout(callback, 1000 / 60);
};
})();
var canvas = document.getElementById("canvas"), ctx = canvas.getContext("2d");
canvas.width = 400;
canvas.height = 200;
var points = [],
currentPoint = 1,
nextTime = new Date().getTime() + 500,
pace = 150;
// make some points
for (var i = 0; i < 50; i++) {
points.push({
x: i * (canvas.width / 50),
y: 100
});
}
function draw(runAnimation) {
if (runAnimation.value) {
if (new Date().getTime() > nextTime) {
nextTime = new Date().getTime() + pace;
currentPoint++;
if (currentPoint > points.length) {
currentPoint = 0;
}
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
ctx.lineWidth = 2;
ctx.strokeStyle = '#2068A8';
ctx.fillStyle = '#2068A8';
for (var p = 1, plen = currentPoint; p < plen; p++) {
ctx.lineTo(points[p].x, points[p].y);
}
ctx.stroke();
requestAnimFrame(draw(runAnimation));
}
}
var stop = document.getElementById('stop');
var left = document.getElementById('left');
var right = document.getElementById('right');
/*
* define the runAnimation boolean as an obect
* so that it can be modified by reference
*/
var runAnimation = {
value: false
};
stop.addEventListener('click', function () {
runAnimation.value = !runAnimation.value;
if (runAnimation.value) {
requestAnimationFrame(draw(runAnimation));
}
});
left.addEventListener('click', function () {
});
right.addEventListener('click', function () {
});
</script>
</body>
</html>
Your problem is where you call requestAnimationFrame..
You have
requestAnimFrame(draw(runAnimation));
The draw(runAnimation) is calling and running the function draw, which then gets down the the same line and does the same thing, the function never gets a chance to exit and eventually the call stack overflows.
To fix change the line to
requestAnimationFrame(draw);
Now you are just passing the referance to the function draw.
As you want the runAnimation value to be passed, you can not do this with requestAnimationFrame as it already has an argument passed to the draw function. (the time)
For this case it is easier for you just to change the function declaration from
function draw(runAnimation) { // runAnimation holds the time as that
// is what requestAnimationFrame will
// pass as the first argument
Change it to
function draw(time){ // you can ignore the time as you don't need it
The variable runAnimation can still be seen inside the function as you have defined it in the same scope.
And the last change is to the stop event
stop.addEventListener('click', function () {
runAnimation.value = !runAnimation.value;
if (runAnimation.value) {
requestAnimationFrame(draw(runAnimation)); // You are calling
// draw, but you
// should just pass
// a reference.
}
});
To
stop.addEventListener('click', function () {
runAnimation.value = !runAnimation.value;
if (runAnimation.value) {
requestAnimationFrame(draw); // only the function reference is
// needed.
}
});
I have come across a very odd behavior that is causing issues in Chrome (only tested browser). I have a canvas that is being used to render an audio frequency spectrum visual. Whenever I define the CanvasRenderingContext2D variable
var canvasCtx;
canvasCtx = canvas.getContext("2d");
or define the ScriptProcessorNode variable
var scriptNode;
scriptNode = audioCtx.createScriptProcessor(2048, 1, 1);
and the variable definition is inside any closure or function, the visualization rendering will freeze if you switch tabs, change windows, or even change the window width size.
However, I found out that if the variable definition for those two types are defined at the global scope outside all functions, the canvas will continue to render even if the page is inactive.
Here is a JSFiddle demonstrating the bug:
http://jsfiddle.net/K8J26/541/
(Audio may not play in JSFiddle due to cross-origin safety, so a local file may be needed)
I am wondering, why is this happening?
Does the browser hold onto the state of variables and objects that are tied to the global scope even if the page is inactive? Or is it something completely unrelated to the location of variable definition, and instead something I just completely overlooked?
Thanks!
Your problem seems to be that you are calculating the new size and creating the gradient while the browser has not updated the size of your elements yet.
Pass the updateScale in a requestAnimationFrame call so the browser has the time to render the elements :
(function initVisualizer() {
var AudioContext = window.AudioContext || window.webkitAudioContext;
if (!AudioContext) {
return;
}
var PERCENT_HIGH_FREQ_TRIM = 0.3;
var PERCENT_HEIGHT_OF_WITDH = 0.25;
var SMOTHING_CONSTANT = 0.6;
var audioCtx = new AudioContext();
var canvas = document.getElementById("visualizer");
canvas.style.width = "100%";
// Defining canvasCtx here causes frozen canvas rendering when tab is inactive
var canvasCtx = canvas.getContext("2d");
// Defining scriptNode here causes frozen canvas rendering when tab is inactive
var scriptNode = audioCtx.createScriptProcessor(2048, 1, 1);
scriptNode.connect(audioCtx.destination);
var analyser = audioCtx.createAnalyser();
analyser.smoothingTimeConstant = SMOTHING_CONSTANT;
analyser.connect(scriptNode);
var widthMax;
var heightMax;
var dataCount;
var barWidth;
var barOffset;
var gradient;
scriptNode.onaudioprocess = function() {
var frequencyData = new Uint8Array(dataCount);
analyser.getByteFrequencyData(frequencyData);
canvasCtx.clearRect(0, 0, widthMax, heightMax);
canvasCtx.fillStyle = gradient;
var modifier = heightMax / 255;
for (var i = 0; i < dataCount; i++) {
var value = ~~(frequencyData[i] * modifier);
canvasCtx.fillRect(i * (barWidth + barOffset), heightMax - value, barWidth, heightMax);
}
};
window.addEventListener("resize", function() {
if (canvas.parentElement.offsetWidth !== widthMax) {
requestAnimationFrame(updateScale);
}
});
function updateScale() {
widthMax = canvas.offsetWidth;
heightMax = ~~(widthMax * PERCENT_HEIGHT_OF_WITDH);
var size = nearestPow2(~~(widthMax / 4));
dataCount = ~~((size / 2) * (1 - PERCENT_HIGH_FREQ_TRIM));
var rectWidth = widthMax / dataCount;
barOffset = rectWidth * 0.25;
barWidth = rectWidth - barOffset;
analyser.fftSize = size;
canvas.setAttribute("width", widthMax);
canvas.setAttribute("height", heightMax);
gradient = canvasCtx.createLinearGradient(0, 0, 0, heightMax);
gradient.addColorStop(1, "#ff6600");
gradient.addColorStop(0, "#ffff00");
}
function playAudio(audio) {
var sourceNode = audioCtx.createMediaElementSource(audio);
sourceNode.connect(analyser);
sourceNode.connect(audioCtx.destination);
console.log(audio.play());
setTimeout(function() {
audio.pause();
}, 30000);
}
function nearestPow2(size) {
return Math.pow(2, Math.round(Math.log(size) / Math.log(2)));
}
updateScale();
playAudio(document.getElementById('audio'));
})();
body {
background: #222;
}
<audio id="audio" controls crossorigin="anonymous">
<source src="https://upload.wikimedia.org/wikipedia/en/d/dc/Strawberry_Fields_Forever_%28Beatles_song_-_sample%29.ogg" />
<source src="https://upload.wikimedia.org/wikipedia/en/d/dc/Strawberry_Fields_Forever_%28Beatles_song_-_sample%29.ogg" />
</audio>
<canvas id="visualizer"></canvas>
However I don't know why it was working when you set the variable in global context...
Ps : your fiddle wasn't working on FF and only worked on chrome because of a bug, you need to set the crossorigin attribute before the resource are loaded, otherwise it has no effect.
I am trying to use the method 'requestAnimationFrame' with the help I can find on Internet. I can move an element, but when I want to do it with sprites, I am lost.
For example, the code below is working normally with 'setInterval', but I cannot manage to make it work with 'requestAnimationFrame'.
<!DOCTYPE html>
<html>
<head>
<title>Animating Sprites in HTML5 Canvas</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, user-scalable=no">
<style>
.demo {background: #aaaaaa;}
#myCanvas{background: #cccccc}
</style>
</head>
<body class="demo">
<canvas id="myCanvas" width="800" height="100"></canvas>
<script>
(function() {
// Canvas
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
// Set the fill style for the drawing context.
ctx.fillStyle = '#3399ff';
// VARIABLES
var width = 48; // Width CANVAS
var height = 60; // Height CANVAS
var xFrame = 0; // Frame x coordinate
var yFrame = 0; // Frame y coordinate
var dxFrame = 0; // Frame dx position in canvas
var dyFrame = 0; // Frame dy position in canvas
// SPRITE used
image = new Image()
image.src = 'myRunner2.png';
//
var requestID;
// shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element){
window.setTimeout(callback, 1000 / 60);
};
})();
// FUNCTION DRAWING MOVE (xFrame = 0 & yFrame = 1)
var drawMove = function(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(image, width * xFrame, height * yFrame, width, height, dxFrame, dyFrame, width, height);
if (xFrame == 7) {
xFrame = 0;
} else {
xFrame++
dxFrame+=2;
}
//window.requestAnimFrame(eMove);
}
// ANIMATION in 3 moves: Idle + Move + Tired
var intA;
function eMove() {
// Runner in motion (8 frames)
yFrame = 1;
xFrame = 0;
clearInterval(intA);
intA = setInterval(drawMove, 100);
}
eMove();
}());
</script>
</body>
</html>
I am looking for help about this issue, a portion of code will be great but a way to work or a direction to look for will be good as well. How to manipulate sprite with the method 'requestAnimationFrame'?
Ultimately, my goal is to move a sprite in one direction and the background in the other direction. I can move the sprite in one direction with setTimeout/setInterval methods alone or I can move in the other direction the background with 'requestAnimationFrame', but also separately.
I hope you understand my problem.
Thank you,
JLuc01
For requestAnimationFrame to work well it needs an accurate timer by which it can update the progress. The animation would then also depend on this variable. Of course a total duration will have to be set as well (to measure the progress). Here's a general piece of code :
var initial = update = new Date().getTime(), progress = 0, duration = 2000;
requestAnimationFrame(frameSequence);
function frameSequence() {
update = new Date().getTime();
var elapsed = update-initial;
progress = Math.max(elapsed/duration, 1);
someFunction(); // do calculations and implement them based on progress
if (progress < 1) requestAnimationFrame(frameSequence);
}
And a live example (relevant code at the bottom)
http://codepen.io/Shikkediel/pen/vEzqoX?editors=001
Edit - some comments promoted to update :
The requestAnimationFrame call is just a basic loop really to replace the timeout. It could be as simple as using requestAnimationFrame(drawMove) instead of clearInterval(intA); intA = setInterval(drawMove, 100). It'll probably do the whole thing in 8/60 of a second that way though (I see there are 8 frames and 60 is the common display refresh rate) - hence a timer would be needed.
This would optimise and work for sure : setInterval(requestAnimationFrame(drawMove), 100). It will not force a frame on the display then like a timeout does (giving performance issues and flickering) but make it wait for the first appropriate instance when there is a new paint of the screen. But not using timeouts at all is a much better approach.
I need to rotate an image inside an canvas..I have googled and saw similar questions in stackoverflow.What i learnt is
I cannot rotate single object inside canvas.
I can rotate only thewhole canvas.
So i need to translate to center of the object and then rotate the
canvas.
I Followed exactly same stuffs , But i am struck at translating to the image center..Below is the code i am using.Here is the jsfiddle http://jsfiddle.net/J6Pfa/1/. This one is rotating the whole canvas regardless image..some one guide me where i am wrong.Thanks
//hero canvas
ball = new Hero();
var ang = 0;
herocanvas = document.createElement("canvas");
herocanvas.width = herocanvas.width = 500;
herocanvas.height = herocanvas.height = 500;
heroctx = herocanvas.getContext('2d');
document.body.appendChild(herocanvas);
var requestAnimFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame;
var imgSprite = new Image();
imgSprite.src = 'http://i.imgur.com/WTgOHGg.png';
imgSprite.addEventListener('load',init,false);
function init()
{
startloop();
}
function startloop()
{
heroctx.save(); //saves the state of canvas
clearherobg() ; // clear canvas
heroctx.translate(ball.drawX, ball.drawY); //let's translate
heroctx.rotate(Math.PI / 180 * (ang += 4));
ball.draw(); // draw image here
heroctx.restore();
requestAnimFrame(startloop);
}
function Hero() {
this.srcX = 0;
this.srcY = 500;
this.drawX = 220;
this.drawY = 200;
this.width = 100;
this.height = 40;
this.speed = 5;
this.isUpKey = false;
this.isRightKey = false;
this.isDownKey = false;
this.isLeftKey = false;
}
Hero.prototype.draw = function () {
heroctx.drawImage(imgSprite,this.srcX,this.srcY,this.width,this.height,this.drawX,this.drawY,this.width,this.height);
};
function clearherobg() {
heroctx.clearRect(0,0,500,500);
}
Those who cannot read full code ..Please check startloop() , thats the main infinite loop..ball.drawX and ball.drawY are the x and y position of image inside canvas
Hero's drawX and drawY need to be updated to new coordinate system of canvas, if u want it to be in the middle of canvas it needs to be 0,0.
Something like this: jsfiddle.net/J6Pfa/3
Hm, i dont exactly understand what you want to achieve, an image moving on the circle path ? or having image in one place, and just rotate it ?