I have a code to scale drawing canvas.
So i tried this code. i scale it but it moves down,
here is my code:
canvas.save();
scaleA = 1.1;
scaleB = 1.1;
canvas.scale(scaleA, scaleB);
canvas.restore();
the issue is even when i scale the Y coordinates move down, so i try to translate or reduce y coordinates but i still issue. any one knows how to properly scale a drawing canvas?
i tried like this:
canvas.save();
scaleA = 1.1;
scaleB = 1.1;
canvas.translate(scaleA, -scaleB);
canvas.scale(scaleA, scaleB);
canvas.restore();
You have to set the center of your image, if your image center is equal to the canvas(view) center
canvas.scale(sx, sy, canvas.getWidth() / 2, canvas.getHeight() / 2);
Or else, change the last two params to whatever center you want it to be, you don't need to translate
Related
I have looked all over, but nothing has worked. Every time I try finding the center of the screen for my watch face, it always end up slightly higher than the center, and to the far right of the screen (This is different than the problem that the original template from Android Studio has, where the Watch face is slightly up and all the way to the far left of the screen). What could I be doing wrong?
(First screenshot on Left: My problem. Second screenshot: Original form of the Android Wear template from Android Studio)
#Override
public void onDraw(Canvas canvas, Rect bounds) {
if (isInAmbientMode()) {canvas.drawColor(Color.BLACK);
}
else {
canvas.drawRect(0, 0, bounds.width(), bounds.height(), mBackgroundPaint);
}
// Draw H:MM in ambient mode or H:MM:SS in interactive mode.
long now = System.currentTimeMillis();
mCalendar.setTimeInMillis(now);
int width = bounds.width();
int height = bounds.height();
float centerX = width / 2f;
float centerY = height / 2f;
String text = mAmbient
? String.format("%d:%02d", mCalendar.get(Calendar.HOUR),
mCalendar.get(Calendar.MINUTE))
: String.format("%d:%02d", mCalendar.get(Calendar.HOUR),
mCalendar.get(Calendar.MINUTE));
canvas.drawText(text, centerX, centerY, mTextPaint);
}
Full code can be found here
As far as i can tell from a quick look on your sources you already calculate mTextXOffset and mTextYOffset but don't use it for your draw call, hence the texts origin is centered in your problematic screenshot instead of the texts center.
adjusting your centerX and centerY by mTextXOffset and mTextYOffset should do the trick.
If you're drawing text using a center point you can use
mTextPaint.setTextAlign(Paint.Align.CENTER);
which will draw from the center. Otherwise the x coordinte represents the left hand side of the text you are drawing.
So the scenario is that I have a surfaceView of size 640 x 480 on which I am showing on camera preview. Now I draw a something vertically on the screen. After that I am rotating the canvas using
canvas.rotate(90, getWidth()/2, getHeight/2);
Once I do that, I am expecting my drawing to be scaled and drawn horizontally. It does draw it horizontally but it is not scaling it according the width and height.
Here is the pictorial example explanation to help you understand better.
https://lh4.googleusercontent.com/-2wlImCt0m88/UcHzhKUSGBI/AAAAAAAAB9Y/bGNMOTu9DqM/s1440/canvas_rotation.png
Is there a way or an algorithm by which I can rotate the canvas and then scale it accordingly?
let me know if you need any further explanation.
Thanks in advance.
Well so I figured out the solution to it. What we can do is that we can use
canvas.scale( newX, newY, pivotX, pivotY);
/*
* Where
* newX = oldX * (newWidth/oldWidth);
* newY = oldY * (newHeight/oldHeight);
* pivotX = same as before;
* pivotY = same as before;
*/
I have implemented a long onDraw method which draws a set of rectangles. The rectangles are too small and I want them to appear bigger. But unfortunately I can't change the rectangle coordinates because they are stored in a database. So is there any way I can zoom in the canvas using canvas.scale() ?
I'm going to preface this answer by saying you will need to draw everything at 0,0 and then scale it, and finally translate it to behave properly.
Simply do the following in your onDraw method:
canvas.save();
canvas.translate(xValue, yValue);
canvas.scale(xScale, yScale)
/* draw whatever you want scaled at 0,0*/
canvas.restore();
xScale shrinks or stretches in the X direction,
yScale shrinks or stretches in the Y direction.
1.0 is the default for these, so 2.0 would stretch it by double and 0.5 would shrink it by half.
Example:
canvas.save();
canvas.translate(50, 50);
canvas.scale(0.5f, 0.5f);
canvas.drawRect(0.0, 0.0, 5.0, 5.0, paint);
canvas.restore();
This will draw a rectangle with length 5.0, and width 5.0, scale it down to 2.5 for length and width, and then move it to (50, 50).
The result will be a rectangle drawn as if you did this:
canvas.drawRect(50.0, 50.0, 52.5, 52.5, paint);
I hope this helps!
I'm want to scale a canvas with a bitmap drawn on it. I'm able to scale the canvas but the bitmap drawn on it moves to the upper left respectively lower right.
#Override
protected void onDraw(Canvas canvas) {
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
//draw bitmap
}
For the last few days I tried many different approaches from manipulating translation coordinates to pivot points for scaling. But nothing did work for me. I'm pretty sure there must be an easy solution for my problem.
Thanks in advance
Like you mentioned, the pivot point is the correct way to do this:
canvas.scale(2,2, redCircle.x, redCircle.y);
will work. There is no need for extra translation.
var widthNew = ctx.canvas.width / 2;
var heightNew = ctx.canvas.height / 2;
ctx.setTransform(scale,0,0,scale,-(scale-1)*widthNew,-(scale-1)*heightNew);
This will help you scale the canvas horizontally and vertically with the horizontal and vertical translation.
I'm trying to show a picture, which can be zoomed and panned, and that rotates with a compass reading. With the code below, all three actions kind of work, but they influence each other.
Here is what I want to achieve:
1. Rotate around the center of the screen
2. Scale leaving the same part of the picture in the center
3. Pan to the desired spot in the picture
Here is what is actually happening with the code below:
1. Rotation works as intended, around the center of the screen
2. Scaling works, but it scales around the center of the picture
3. Translation only works as intended if angle is zero, otherwise it's moving in a wrong direction
// the center of the view port
float centerX = screen.right/2;
float centerY = screen.bottom/2;
Matrix m = new Matrix();
m.preRotate(angle, centerX, centerY);
m.preScale(mScaleFactor, mScaleFactor, centerX, centerY);
// scaling the amount of translation,
// rotating the translation here gave crazy results
float x = mPosX / mScaleFactor;
float y = mPosY / mScaleFactor;
m.preTranslate(x, y);
canvas.drawBitmap(pic, m, null);
If I translate first, and later rotate, the translation works as intended but the rotation is not around the center of the view port anymore.
How can I apply all three transformations, without them influencing each other?
I'm not sure about the scaling around the centre of the image, but as for the translation being in the wrong direction is it not as a consequence of you rotating the image but not the translations? Maybe try something like this:
float x = (mPosX*(cos(angle) + sin(angle)) / mScaleFactor;
float y = (mPosY*(cos(angle) - sin(angle)) / mScaleFactor;
m.preTranslate(x, y);
Also does the matrix object have a method to apply an affine transformation directly? Because then you won't need to think about the order of operations.
The affine transformation might look something like this:
M = |mScaleFactor*cos(angle) sin(angle) x|
| -sin(angle) mScaleFactor*cos(angle) y|
| 0 0 1|
But this will rotate around the corner of the image so you need to use the preTranslate() function first like so:
Mt.preTranslate(-centerX,-centerY);
And APPLY Mt to pic before applying M and then after you need to apply -Mt