Rotating and moving an image in a canvas element?

2024/2/27 8:17:32

I would like to move and rotate an image of a ball in a element. The ball is 68x68 and the canvas is 300x200. The ball moves along the x and y axis, flipping its x and y velocity when it hits a wall - all of this works. I just can't figure how to do rotation on top of the movement.

My draw() function, which I call through window.setInterval every 30ms, looks something like this:

  var draw = function() {ctx.clearRect(0, 0, canvas.width, canvas.height);ctx.save();ctx.rotate(ball_radians);ctx.drawImage(ball_img, x, y);ctx.restore();// calculate new x, y, and ball_radians}

This makes the ball fly around the screen, so clearly I'm doing something wrong. What am I missing?

Answer
  1. Translate the context to the point on the canvas that the object should rotate about.
  2. Rotate the context.
  3. Either:
    • Translate the context by the negative offset within the object for the center of rotation, and then draw the object at 0,0, or
    • Draw the image using the negative offset within the object for the center of rotation.

e.g.

ctx.save();
ctx.translate( canvasLocX, canvasLocY );
ctx.rotate( ballRotationInRadians );
ctx.drawImage( ball_img, -ballCenterX, -ballCenterY );
ctx.restore();

Note that if you need absolute speed, instead of saving and restoring the canvas (handling many properties that you didn't change) you can just undo your work:

ctx.translate( canvasLocX, canvasLocY );
ctx.rotate( ballRotationInRadians );
ctx.drawImage( ball_img, -ballCenterX, -ballCenterY );
ctx.rotate( -ballRotationInRadians );
ctx.translate( -canvasLocX, -canvasLocY );

The previous bit of premature optimization has been blindly parroted from someone else; I have not personally benchmarked to verify that it is correct.

Edit: I've added a mocked up working example of this here: http://phrogz.net/tmp/canvas_beachball.html

http://en.ppmy.cn/q/42540.html

Related Q&A

Regular expression for Indian Currency validation using JavaScript

Can anyone please tell me how to check whether the entered amount (Indian currency) in a textbox is valid or not using regular expression?I have few conditions..The amount should not contain more than…

How to turn off Velocity unit testing in Meteor? [duplicate]

This question already has answers here:Temporarily disable Meteor testing packages (e.g. Velocity + Mocha) without removing them(3 answers)Closed 8 years ago.Im using the mike:mocha package and Im tryi…

Catch the window.open from javascript

I have a web page into a html iframe, the web page has a javascript function to open links, that function use the window.open method to open a new window.I cannot modify the javascript function (the pa…

Merging two bezier-based shapes into one to create a new outline

Lets say I have the data to render two overlaying bezier-based shapes, that are overlapping, displayed in a svg or on the canvas (doesnt really matter where). I would like to calculate the outline of t…

Can I assign a different radius for each pie slice using Highcharts?

I am using Highcharts and it is working just amazing, i am stuck at a place where i want to plot a pie chart in which every pie slice (in a single pie chart) has a different radius.Below is the image a…

Dynamically Importing JavaScript

What is the correct way to dynamically import JavaScript (.js) files into a parent JavaScript code, please?I am using the following code, but it seems not correct:function loadjscssfile(filename, file…

Angularjs dynamic directives

Note: Im quite new to angularjsWhat is the best solution/practice for problem: I have an array or typed values, for each type there should be different input(template and input validation)?E.g. and si…

How to Cut, Copy and Paste from JavaScript to a Users Clipboard

There are multiple similar questions in stackoverflow which deal with how to Cut, Copy, and Paste from JavaScript (in response to a button press, for instance) without the user having to use CTRL+X, C,…

Is it okay to use with()?

Once, I saw an example like this:var a, x, y; var r = 10; with (Math) {a = PI * r * r;x = r * cos(PI);y = r * sin(PI / 2); }And it looks very convenience, because that way I dont have to type all the M…

Any better way to combine multiple callbacks?

I need to call an async function (with loop) for multiple values and wait for those results. Right now Im using the following code:(function(){var when_done = function(r){ alert("Completed. Sum of…