小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
1. Canvas 与屏幕
Canvas不等于屏幕,屏幕不会动的,我们也无法对屏幕进行(平移,缩放等)操作,只能对Canvas进行操作,所以对Canvas进行操作,屏幕不动,最终会导致看到的图像不同。
下面开始讲解Canvas的变幻操作:
包括:translate,rotate,scale,skew,clip,clipout,matrix
2. translate 平移
/**
* Preconcat the current matrix with the specified translation
*
* @param dx The distance to translate in X
* @param dy The distance to translate in Y
*/
public void translate(float dx, float dy) {
if (dx == 0.0f && dy == 0.0f) return;
nTranslate(mNativeCanvasWrapper, dx, dy);
}
对Canvas进行平移,
dx: x轴方向进行平移,正值向屏幕右侧
dy:y轴方向进行平移,正值向屏幕下方
mPaint.setStrokeWidth(50);
canvas.drawPoint(0, 0, mPaint);
mPaint.setColor(Color.RED);
canvas.translate(200, 400);
canvas.drawPoint(0, 0, mPaint);
绘制矩形
mPaint.setStrokeWidth(50);
canvas.drawRect(200, 200, 700, 700, mPaint);
mPaint.setColor(Color.RED);
canvas.translate(200, 400);
canvas.drawRect(200, 200, 700, 700, mPaint);
mPaint.setColor(Color.GRAY);
canvas.drawRect(300, 300, 800, 800, mPaint);
3. scale 缩放
/**
* Preconcat the current matrix with the specified scale.
*
* @param sx The amount to scale in X
* @param sy The amount to scale in Y
*/
public void scale(float sx, float sy) {
if (sx == 1.0f && sy == 1.0f) return;
nScale(mNativeCanvasWrapper, sx, sy);
}
/**
* Preconcat the current matrix with the specified scale.
*
* @param sx The amount to scale in X
* @param sy The amount to scale in Y
* @param px The x-coord for the pivot point (unchanged by the scale)
* @param py The y-coord for the pivot point (unchanged by the scale)
*/
public final void scale(float sx, float sy, float px, float py) {
if (sx == 1.0f && sy == 1.0f) return;
translate(px, py);
scale(sx, sy);
translate(-px, -py);
}
sx:横向的缩放,默认为1,小数缩小,整数放大
sy:纵向的缩放,默认为1,小数缩小,整数放大
canvas.drawRect(200, 200, 700, 700, mPaint);
canvas.scale(0.5f,0.5f);
mPaint.setColor(Color.GRAY);
canvas.drawRect(200, 200, 700, 700, mPaint);
第二个函数,缩放位置控制:
px,py,看源码知道是先translate,执行sx,sy然后再translate反方向。
第二次translate的坐标为(-pxsx,-pxsy),最终的效果就是px,py是缩放后不动的点。
canvas.drawRect(200, 200, 700, 700, mPaint);
canvas.scale(0.5f,0.5f, 200, 200);
mPaint.setColor(Color.GRAY);
canvas.drawRect(200, 200, 700, 700, mPaint);
4. Canvas 的旋转rotate
/**
* Preconcat the current matrix with the specified rotation.
*
* @param degrees The amount to rotate, in degrees
*/
public void rotate(float degrees) ;
/** *
* @param degrees The amount to rotate, in degrees
* @param px The x-coord for the pivot point (unchanged by the rotation)
* @param py The y-coord for the pivot point (unchanged by the rotation)
*/
public final void rotate(float degrees, float px, float py) {
if (degrees == 0.0f) return;
translate(px, py);
rotate(degrees);
translate(-px, -py);
}
rotate有两个函数:
rotate(float degrees)
rotate(float degrees, float px, float py)
Degree:旋转的角度,正值为顺时针,负值为逆时针
Px,py:旋转的中心,如果不指定旋转中心默认为(0,0)点
canvas.drawRect(200, 200, 700, 700, mPaint);
canvas.rotate(-10);
mPaint.setColor(Color.GRAY);
canvas.drawRect(200, 200, 700, 700, mPaint);
以默认(0,0)为旋转点
指定旋转中心为矩形中心
canvas.drawRect(200, 200, 700, 700, mPaint);
canvas.rotate(-10, 450, 450);
mPaint.setColor(Color.GRAY);
canvas.drawRect(200, 200, 700, 700, mPaint);
5. Skew 倾斜 画布
/**
* Preconcat the current matrix with the specified skew.
*
* @param sx The amount to skew in X
* @param sy The amount to skew in Y
*/
public void skew(float sx, float sy) {
if (sx == 0.0f && sy == 0.0f) return;
nSkew(mNativeCanvasWrapper, sx, sy);
}
**参数说明:
****sx:画布在x方向上倾斜相应的角度,sx倾斜角度的tan值,
**sy:画布在y轴方向上倾斜相应的角度,sy为倾斜角度的tan值,
canvas.drawRect(200, 200, 700, 700, mPaint);
canvas.save();
canvas.skew(tan(30), 0);
mPaint.setColor(Color.GRAY);
canvas.drawRect(200, 200, 700, 700, mPaint);
canvas.restore();
mPaint.setColor(Color.BLUE);
canvas.drawRect(200, 800, 700, 1300, mPaint);
canvas.save();
canvas.skew(0, tan(30));
mPaint.setColor(Color.GRAY);
canvas.drawRect(200, 800, 700, 1300, mPaint);
canvas.restore();
private float tan(int degree) {
return (float) Math.tan(degree * 1.0 / 180.0 * Math.PI);
}
6. clip 切割画布
**根据矩形或者路径裁剪画布,画布被切割之后,只有部分区域可用,其他区域无法绘制内容。
**Clip函数切割的区域可用,clipOut未被切割的区域可用。(过时函数不再讲解)
clipRect(@NonNull RectF rect)
clipRect(@NonNull Rect rect)
clipRect(float left, float top, float right, float bottom)
clipRect(int left, int top, int right, int bottom)
clipPath(@NonNull Path path)
一下函数需要api26以上
clipOutRect(@NonNull RectF rect)
clipOutRect(@NonNull Rect rect)
clipOutRect(float left, float top, float right, float bottom)
clipOutRect(int left, int top, int right, int bottom)
clipOutPath(@NonNull Path path)
canvas.drawRect(200, 200, 700, 700, mPaint);
mPaint.setColor(Color.GRAY);
canvas.drawRect(200, 800, 700, 1300, mPaint);
canvas.clipRect(200, 200, 700, 700);
canvas.drawCircle(100, 100, 100, mPaint); //画不上
canvas.drawCircle(300, 300, 100, mPaint); //可以画上
canvas.drawCircle(650, 650, 100, mPaint); //部分画上
7. matrix 变换
setTranslate(float dx,float dy):平移操作
setSkew(float kx,float ky):skew操作
setSkew(float kx,float ky,float px,float py):
setRotate(float degrees):旋转
setRotate(float degrees,float px,float py):
setScale(float sx,float sy):缩放
setScale(float sx,float sy,float px,float py):
Matrix的pre XXX和postXXX是左乘右乘的区别,是为了组合各种操作,因为矩阵不符合交换率,所以左乘右乘效果不同,一般利用matrix的效果需要反着乘得到最终的matrix.
以上的效果和canvas的set操作效果一样。
canvas.drawRect(200, 200, 700, 700, mPaint);
mPaint.setColor(Color.GRAY);
Matrix matrix = new Matrix();
matrix.setRotate(10);
canvas.setMatrix(matrix);
canvas.drawRect(200, 200, 700, 700, mPaint);
\