An example can be found here compass.java.
Api here
Even when I first answered this question a few years ago, I didn't really understand how Canvas transforms (like translate, rotate, etc.) worked. I used to think that translate moved the thing that you were drawing. Actually, translate moves the entire coordinate system. This has the desired effect of also moving the thing you are drawing.
On your screen it looks like you are moving the drawing:
What is actually happening is you are moving the coordinate system to a new place on the canvas:
I draw the tree first at (0,0). Then I translate the origin of the coordinate system to some other spot on the canvas. Then I draw the tree again at (0,0). This way my drawing code doesn't have to change anything at all. Only the coordinate system changes.
Normally (0,0) is at the top left of your view. Doing Canvas.translate moves it to some other part of your view.
Saving and Restoring the Coordinate System
You can do save() and restore() to get back to your original coordinate system.
// draw the tree the first time
canvas.drawBitmap(tree, 0, 0, mPaint);
// draw the tree the second time
canvas.save();
canvas.translate(dx, dy); // dx = change in x, dy = change in y
canvas.drawBitmap(tree, 0, 0, mPaint); // draw still thinks it is at (0,0)
canvas.restore(); // undo the translate
When you restore, the drawing is already on the canvas. Restoring doesn't change that. It just moves the coordinate system back to wherever it was when you saved it.
Why Translate
Note that you could achieve the same affect by changing the x,y coordinates of the draw method:
// draw the tree the first time
canvas.drawBitmap(tree, x, y, mPaint);
// update the x,y coordinates
x += dx;
y += dy;
// draw the tree the second time
canvas.drawBitmap(tree, x, y, mPaint);
This might be more intuitive coming from a math background. However, when you are translating, rotating, and scaling your image, it is often much easy to keep your drawing logic the same and just transform the canvas. Recalculating x and y for every draw could be very expensive.
Imagine it's a Print Head.
The easiest way to explain this is to imagine it is the print head of an inkjet or 2D printer.
translate basically "moves" the print head along the X and Y axes the number of pixels that you tell it to.
The resulting position becomes the new "origin" (0,0).
Now that we understand that, let's make a simple face by doing the following:
Starting Origin:
x
The x will (roughly) represent where the origin (or print head) is.
Draw a rectangle for the left eye:
canvas.drawRect(10, 10, 10, 10, paint);
x__
|__|
Note: The "origin" has not changed, it is still at the top left of this rectangle.
Move "origin" right by 20 points:
canvas.translate(20, 0)
__ x
|__|
Draw the right eye using the exact same rectangle command:
canvas.drawRect(10, 10, 10, 10, paint);
__ x__
|__| |__|
Move "origin" back to the original X position and move it down on the Y axis:
canvas.translate(-20, 20) // Positive numbers for the second param is "down" on the y-axis.
__ __
|__| |__|
x
And draw a mouth to finish it off:
canvas.drawLine( 0, 0, 30, 0, paint );
__ __
|__| |__|
x___________
Now just move the "origin" down 20 points to showcase our masterpiece:
canvas.translate(0, 20)
__ __
|__| |__|
___________
x
Not perfectly to scale as there's only so much you can do with a monospace font. :)
Translate - Basically do what it says. Just translate the canvas using x,y. If you want to draw two objects and the one is just translation of the other e.g x2 = x1 + 50 for each point . You don't have to make all your calculations again for the second object but you can just translate the canvas and draw again the same object. I hope this example will help you.
it will change the position of your canvaz(except scale) either x or y
if we translate & scale then it is transformation in general terminology
Related
I need to make a rotating wheel on my android App. To do so, I'm creating a custom View in order to place it anywhere I want in the App activities.
All around the wheel, I need to place TextViews.
Thanks to the width and height of the view, I can get the center point of the canvas' view.
I know the angle, I know the radius, so now I need to place textviews on the edge of the circle by calculating the coordinates on the canvas.
Does anyone knows how to achieve that ?
Thanks in advance !
A point at angle theta on the circle whose center is (x0,y0) and whose radius is r is (x0 + r cos theta, y0 + r sin theta)
Or
Once you have drawn the circle you have to rotate the canvas put the text at required angle and then again restore it as,
canvas.save();
canvas.rotate(45, x, y);
canvas.drawText("your text here", x, y, paint);
canvas.restore();
Hope that helps..!!
I created a rectangle using x and y integers which change values when I touch the rectangle and swipe in a certain direction (x increases when I swipe right, y increases when I swipe up, etc.). This rectangle is also being rendered onto a canvas. I have a game loop which calls an update() method and render() method. The update() method updates the x and y values and creates a collision detection rectangle, the render() method then uses these values to render an updated rectangle to my canvas.
Say I use the method canvas.translate(0, -50) before I draw this rectangle in my game loop. The rectangle appears 50 pixels above where it used to be, however my x and y values remain the same so I have to swipe below my rendered rectangle for it to actually do something. What's a simple and efficient way of updating the x and y so that my rectangle is actually located where it is rendered and not below it? I need the collision detection box to be located where the rectangle is drawn.
I taught myself how to program, so I am not really sure if there is an easier way, but if I were you whenever you call canvas.translate() just change the x and y values to adjust. For example, this is what I would do for the sample you gave:
canvas.translate(0, -50)
x = x+0
y = y+(-50)
If you are too lazy to add the extra two lines you could put it all in to a function and just replace canvas.translate() with whatever function you made.
In fact I will make that function right now. Why not?
public void translate(double XMove, double YMove) {
canvas.translate(XMove, YMove);
x = x+XMove;
y = y+YMove;
}
Im making a 2d game where my character is controlled by a joystick and I rotate him using canvas.rotate(angel, x, y). My character shoots in the same direction he is heading, now I want to add fire coming out of his rifle when he shoots. The problem is, how do I rotate this fire-image around my character?
How I rotate My character:
canvas.save();
canvas.rotate((float) controls.getAngle(), controls.charPosition.x + charBitmap.getWidth() / 2, controls.charPosition.y + charBitmap.getHeight() / 2);
character.draw(canvas, controls.charPosition.x,controls.charPosition.y);
canvas.restore();
How I rotate the Fire:
canvas.save();
canvas.rotate((float) controls.getAngle(), controls.charPosition.x + (fireBitmap.getWidth()) / 2, controls.charPosition.y + (fireBitmap.getHeight() / 2));
fire.draw(canvas, controls.charPosition.x, controls.charPosition.y);
canvas.restore();
As you probably know, drawing my fire like this will make it rotate around its own center, just like with my character. But I want it to rotate around my character so it looks like the fire is coming out of his gun.
Any ideas? If anything is unclear please let me know in a comment. Thanks!
I will try to tailor this answer so that it's more specific, but if I understand you correctly, you may not want to rotate the canvas to create the rotation of the fire. Instead you may want to describe it with a trig function relative to the character's location. So I think it will look something like your drawing of the character.
canvas.save();
canvas.rotate((float) controls.getAngle(), controls.charPosition.x + charBitmap.getWidth() / 2, controls.charPosition.y + charBitmap.getHeight() / 2);
fire.draw(canvas, controls.charPosition.x+(fireRadius*cos(fireAngle)),controls.charPosition.y+(fireRadius*sin(fireAngle));
canvas.restore();
Where in this code, fireRadius is how far from the center of the character drawing you want the fire drawing to be and fireAngle is the angle of the fire from the center of the character. This won't be quite right because it will track the corner of the fire image, not the center. I think that can be fixed somewhat easily. If not, I will change soon.
You could use Canvas.translate(dx, dy). Idea is to move the fire a certain distance away from the gun, which can be directly along x -axis, and then rotate Canvas around gun center. This results fire to rotate given angle at given distance from the gun.
canvas.save();
canvas.rotate((float) controls.getAngle(), controls.charPosition.x + (fireBitmap.getWidth()) / 2, controls.charPosition.y + (fireBitmap.getHeight() / 2));
canvas.translate(distanceFromGun, 0);
fire.draw(canvas, controls.charPosition.x, controls.charPosition.y);
canvas.restore();
Please do note the order. Canvas matrix operations are pre multiplying and though translation is made later in the code.
how to set the screen coordinate system of android screen as first Quadrant of the XY plane
,iwant the (0,0) position to be at bottom left , and i wanna know if i can use the trignometric equation on android screen as Android XY plane is not like the Xy plane
I don't think there's a way to do it that would affect the entire system, such as the XML layout files. But if you just want to draw with a Canvas, you can use translate() and scale().
First use translate() to slide the canvas down so 0,0 is at the bottom. Now the top of the screen would be a negative number, so call scale() to flip it around. Now 0,0 is still at the bottom, and the top of the screen is a positive number.
I'm working with information from this answer and its comments. Use something like:
canvas.save(); // need to restore after drawing
canvas.translate(0, canvas.getHeight()); // reset where 0,0 is located
canvas.scale(1, -1); // invert
... // draw to canvas here
canvas.restore(); // restore to normal
And yes, you can use normal 2D trigonometric functions with the XY coords. You can do it even if they're not translated, you just have to think it through more carefully.
I don't know that you're going to have much luck changing where (0,0) is located, but you could set a constant that accounts for such. myY = y minus screenHeight so (x, myY) adjusts y to the bottom of the screen and works from there +/-.
look up canvas.scale(xs,ys,xp,yp)
xp and yp are the new coordinates that you set for your (0,0) point.
I'm trying to build a custom clock view in Android. See image http://twitpic.com/1devk7
So far to draw the time and hour markers I have been using the Canvas.rotate method to get the desired effect. However, notice that it is difficult to interpret the numbers in the lower half of the clock (e.g. 6 or 9?) because of the angle in which they are drawn.
When using drawText, is it possible to draw the text at 45/90/180 degrees so that all text appears upright when my onDraw method has finished?
To draw a text rotated by 90 degrees at point (x,y), use this code:
canvas.save();
canvas.rotate(-90, x, y);
canvas.drawText(text, x, y, paint);
canvas.restore();
How can you display upside down text with a textview in Android?