canvas 清空画布怎么移动画布中心点

Canvas之translate、scale、rotate、skew步骤讲解 - 移动开发当前位置:& &&&Canvas之translate、scale、rotate、skew步骤讲解Canvas之translate、scale、rotate、skew步骤讲解&&网友分享于:&&浏览:0次Canvas之translate、scale、rotate、skew方法讲解!
尊重原创,欢迎转载,转载请注明: FROM&
GA_studio& &http://blog.csdn.net/tianjian4592&&
前面说Canvas大致可以分为三类:
1. save、restore 等与层的保存和回滚相关的方法;
2. scale、rotate、clipXXX 等对画布进行操作的方法;
3. drawXXX 等一系列绘画相关的方法;
前面主要讲了drawBitmap方法,并举了一个星球浮动的栗子,在那个例子中,星球有大有小,需要移动,有时候可能需求上还需要旋转或错切,有了这些需求,我们就需要使用到与Canvas相关的translate、scale、rotate、skew这几个方法,平移、缩放、旋转、错切,这四个词听起来是如此的熟悉,我们在做一些基本动画的时候经常会与这几个词打交道,现在我们一个个看下当把这几个家伙和Canvas(画布)结合能产生什么效果;
当然在看之前得先明确两个基本概念:
1.Canvas 的左上角是(0,0);
2.基于左上角往右 X 为正,往下 Y 为正,反之为负;
一、canvas.translate() - 画布的平移:
首先咱们在画布上画一个400 X 400 红色的矩形
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
此时整个画布的左上角出现了一个红色的矩形(为了更清楚,蓝色打个底)该矩形大小为400 X 400 ,效果如下:
接下来我们canvas.translate( )玩玩
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLUE);
canvas.translate(100, 100);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
看下效果:
此时可以看到,虽然是绘制同样的矩形,但矩形在画布上的位置已经向右和向下各移动了100px;
既然如此,这个时候如果我们再将canvas 平移(translate)(100,100),再绘制一个同样的矩形会出现什么情况呢?会与之前的矩形重叠吗?咱们拭目以待:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLUE);
canvas.translate(100, 100);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
canvas.translate(100, 100);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
从效果上看,两次translate 进行了叠加,绘制第二个矩形的时候画布已经偏移了(200,200);
好了,了解到这里,咱们利用canvas.translate( )一起来做个小栗子,绘制一个生活中比较常用的刻度尺;
咱们先从网上找个用于参考的刻度尺图片:
从图上看,刻度尺的元素有:外框、刻度线(不同的数值刻度线长短不一)、数字
所以我们所要做的就是对上面的元素在onDraw里分别绘制:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制外框
drawOuter(canvas);
// 绘制刻度线
drawLines(canvas);
// 绘制数字
drawNumbers(canvas);
}咱们先简单分析一下,刻度尺有个外框,外框距离左右都有一定的边距,第一根和最后一根刻度线距离边框也有一定的边距,其余刻度线之间距离相同,另外一些特殊的刻度线长短不一;
有了上面的分析,咱们一个一个来,先绘制外框,外框也就是一个矩形,只需要确定边框的位置和大小,然后使用canvas.drawRect( )绘制即可:
咱们先定义几个需要的数据,为了屏幕适配,数据均为dp:
// 刻度尺高度
private static final int DIVIDING_RULE_HEIGHT = 70;
// 距离左右间
private static final int DIVIDING_RULE_MARGIN_LEFT_RIGHT = 10;
// 第一条线距离边框距离
private static final int FIRST_LINE_MARGIN = 5;
// 打算绘制的厘米数
private static final int DEFAULT_COUNT = 9;然后将以上数据转为对应像素值:
private void initData() {
mDividRuleHeight = (int) TypedValue.PLEX_UNIT_DIP,
DIVIDING_RULE_HEIGHT, mResources.getDisplayMetrics());
mHalfRuleHeight = mDividRuleHeight / 2;
mDividRuleLeftMargin = (int) TypedValue.PLEX_UNIT_DIP,
DIVIDING_RULE_MARGIN_LEFT_RIGHT, mResources.getDisplayMetrics());
mFirstLineMargin = (int) TypedValue.PLEX_UNIT_DIP,
FIRST_LINE_MARGIN, mResources.getDisplayMetrics());
有了以上数据,则可以确定外边框的Rect为:
mOutRect = new Rect(mDividRuleLeftMargin, top, mTotalWidth - mDividRuleLeftMargin,
mRuleBottom);
接下来看刻度线的绘制,根据厘米可以计算出中间的格数,根据厘米占用屏幕宽度和所占格数可以计算出每一格所占屏幕宽度:
mLineInterval = (mTotalWidth - 2 * mDividRuleLeftMargin - 2 * mFirstLineMargin)
/ (DEFAULT_COUNT * 10 - 1);
有了每一格所占宽度,我们只需要在绘制刻度线的时候不断将画布右移对应宽度即可:
* 绘制刻度线
* @param canvas
private void drawLines(Canvas canvas) {
canvas.save();
canvas.translate(mLineStartX, 0);
int top = mMaxLineT
for (int i = 0; i &= DEFAULT_COUNT * 10; i++) {
if (i % 10 == 0) {
top = mMaxLineT
} else if (i % 5 == 0) {
top = mMiddleLineT
top = mMinLineT
canvas.drawLine(0, mRuleBottom, 0, top, mLinePaint);
canvas.translate(mLineInterval, 0);
canvas.restore();
}由于刻度尺上分三种长短的刻度线,我们也做对应处理,10的整数倍的刻度线最长,5的整数倍的刻度线中等长度,其余较短;
此时绘制出的刻度尺效果为:
此时刻度尺的基本样子就出来了,对应文字大家有兴趣可以自己加上;
俗话说,条条大路通罗马,我们除了使用canvas.translate ,还能不能使用别的方式进行实现呢,答案当然是可以,比如在绘制的时候根据for循环里的 i 值也可以直接计算出每一根刻度线的位置,然后直接进行绘制,相比之下,这两种方式的优劣大家也可以自行比较一下,好了,canvas.translate() 就说这么多;
二、canvas.scale( ) - 画布的缩放:
关于scale,android 提供了以下两个接口:
* 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 native void scale(float sx, float 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) {
translate(px, py);
scale(sx, sy);
translate(-px, -py);
}我们先看下scale(float sx , float sy),我们还是以上面的正方形作为栗子,调用canvas.scale(float sx , float sy)之后看下效果;
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLUE);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
canvas.scale(0.5f, 0.5f);
mPaint.setColor(Color.YELLOW);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
}我们将画布在x,y方向上均缩放为 0.5 倍,使用默认基准点(原点 0,0),效果如下:
效果就相当于用个钉子钉在(0,0)处,然后把矩形的x,y缩放为一半,我们再来看看第二个接口scale(float sx , float sy, float px,float py):
前两个参数为将画布在x、y方向上缩放的倍数,而px和py 分别为缩放的基准点,从源码上可以非常清楚的看出和scale(float sx , float sy)的差别:
translate(px, py);
scale(sx, sy);
translate(-px, -py);即先将画布平移px,py,然后scale,scale结束之后再将画布平移回原基准点;
我们再在之前的基础上绘制一个同样的矩形,x , y 均缩放为 0.5 倍,缩放中心为矩形的中心:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLUE);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
// 保存画布状态
canvas.save();
canvas.scale(0.5f, 0.5f);
mPaint.setColor(Color.YELLOW);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
// 画布状态回滚
canvas.restore();
canvas.scale(0.5f, 0.5f, 200, 200);
mPaint.setColor(Color.BLACK);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
一起来看下效果:
效果就相当于用个钉子钉在矩形的中心,然后进行缩放;
根据上面android 的实现,我们其实可以使用以下代码实现同样的效果:
// 先将画布平移到矩形的中心
canvas.translate(200, 200);
// 将画布进行缩放
canvas.scale(0.5f, 0.5f);
// 将画布移回原基准点
canvas.translate(-200, -200);
mPaint.setColor(Color.BLACK);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
到此为止,我们也就了解了对画布的缩放,基于canvas.scale(),我们一起完成一个小例子:
上面是网络上找的一张让人产生视觉误差的静态图,我们模拟绘制出上面的效果;
思路非常的简单:
1. 绘制一个和屏幕等宽的正方形;
2. 将画布以正方形中心为基准点进行缩放;
3. 在缩放的过程中绘制原正方形;
注:每次绘制都得使用canvas.save() &和 canvas.restore()进行画布的锁定和回滚,以免除对后面绘制的影响(后面会单独讲)
先初始化画笔,注意此时画笔需要设置成空心:
* 初始化画笔
private void initPaint() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
// 将画笔设置为空心
mPaint.setStyle(Style.STROKE);
// 设置画笔颜色
mPaint.setColor(Color.BLACK);
// 设置画笔宽度
mPaint.setStrokeWidth(mLineWidth);
然后循环的将画布缩放的同时绘制原正方形:
* 绘制正方形
* @param canvas
private void drawSquare(Canvas canvas) {
for (int i = 0; i & TOTAL_SQUARE_COUNT; i++) {
// 保存画布
canvas.save();
float fraction = (float) i / TOTAL_SQUARE_COUNT;
// 将画布以正方形中心进行缩放
canvas.scale(fraction, fraction, mHalfWidth, mHalfHeight);
canvas.drawRect(mSquareRect, mPaint);
// 画布回滚
canvas.restore();
}一起来看下绘制的效果:
其实最终效果和网上找的还是有点小差别的,由于画布的缩放,越小的时候画笔宽度越细,而原图是所有的都一样宽度,但似乎画笔宽度缩放之后效果更佳,哈哈 ... ...&
三、canvas.rotate( ) - 画布的旋转:
canvas.rotate( )和canvas.scale()可以类比起来看,如果理解了canvas.scale( ),那么canvas.rotate( )将会非常简单实用;
简单来讲,canvas.rotate( )即是将画布进行旋转,和canvas.scale( )类似的是,它也有两个可以使用的方法:
* Preconcat the current matrix with the specified rotation.
* @param degrees The amount to rotate, in degrees
public native void rotate(float degrees);
* Preconcat the current matrix with the specified rotation.
* @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) {
translate(px, py);
rotate(degrees);
translate(-px, -py);
两个方法的区别也是在于基准点的选取,默认是以原点作为基准点,另一个则是以传入的x,y 作为基准点,是不是和scale 一模一样,咱们一起来rotate一下:
咱们先转转左上角的矩形,转多少度呢?先来个90度玩玩吧;
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLUE);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
mPaint.setColor(Color.YELLOW);
canvas.rotate(90);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
我们的预期是屏幕上有个旋转了的骚黄色矩形,一起来看看;
擦,黄色的矩形呢?
由于基准点是原点,我们直接旋转了90 度,所以已经将矩形旋转出屏幕,当然看不到了,我们将角度调小一点,改为45 度:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLUE);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
mPaint.setColor(Color.YELLOW);
canvas.rotate(45);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
此时我们可以可以清楚的看到黄色的矩形是红色矩形绕原点(0,0)旋转45度之后的结果;
我们再将旋转基准点改为矩形中心看看:
canvas.rotate(45,200,200);
可以看到现在黄色矩形是红色矩形绕着中心旋转后的结果:
到这里,我们已经了解了canvas.rotate(float degrees)和 canvas.rotate(float degrees,float px , float py)的使用,同样也应该清楚后者的实现如下:
translate(px, py);
rotate(degrees);
translate(-px, -py);
好了,我们再利用canvas.rotate()完成个闹钟表盘的小例子:
闹钟表盘其实和刻度尺类似,只是一个是在一条直线上绘制,一个是在一个圆周上绘制,说到底都是确定一个位置绘制刻度线;
既然是圆周,最简单的方式莫过于在闹钟的12点钟处划线,通过canvas的旋转绘制到对应圆周处,我们一起实现一下:
整个圆周是360 度,每隔 30 度为一个整时间刻度,整刻度与刻度之间有四个短刻度,划分出5个小段,每个段为6度,有了这些分析,我们则可以采用如下代码进行绘制:
* 绘制刻度
* @param canvas
private void drawLines(Canvas canvas) {
for (int i = 0; i &= 360; i++) {
if (i % 30 == 0) {
mLineBottom = mLineTop + mLongLineH
mLinePaint.setStrokeWidth(mLineWidth);
mLineBottom = mLineTop + mShortLineH
mLinePaint.setStrokeWidth(mHalfLineWidth);
if (i % 6 == 0) {
canvas.save();
canvas.rotate(i, mHalfWidth, mHalfHeight);
canvas.drawLine(mLineLeft, mLineTop, mLineLeft, mLineBottom, mLinePaint);
canvas.restore();
此时效果如下:
整体代码如下:
* 闹钟表盘
* @author AJian
public class RotateClockView extends View {
private static final int LONG_LINE_HEIGHT = 35;
private static final int SHORT_LINE_HEIGHT = 25;
private Paint mCirclePaint, mLineP
private DrawFilter mDrawF
private int mHalfWidth, mHalfH
// 圆环线宽度
private int mCircleLineWidth, mHalfCircleLineW
// 直线刻度线宽度
private int mLineWidth, mHalfLineW
// 长线长度
private int mLongLineH
// 短线长度
private int mShortLineH
// 刻度线的左、上位置
private int mLineLeft, mLineT
// 刻度线的下边位置
private int mLineB
// 用于控制刻度线位置
private int mFixLineH
public RotateClockView(Context context) {
super(context);
mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG
| Paint.FILTER_BITMAP_FLAG);
mCircleLineWidth = (int) TypedValue.PLEX_UNIT_DIP, 8,
getResources().getDisplayMetrics());
mHalfCircleLineWidth = mCircleLineW
mLineWidth = (int) TypedValue.PLEX_UNIT_DIP, 4,
getResources().getDisplayMetrics());
mHalfLineWidth = mLineWidth / 2;
mFixLineHeight = (int) TypedValue.PLEX_UNIT_DIP, 4,
getResources().getDisplayMetrics());
mLongLineHeight = (int) TypedValue.PLEX_UNIT_DIP,
LONG_LINE_HEIGHT,
getResources().getDisplayMetrics());
mShortLineHeight = (int) TypedValue.PLEX_UNIT_DIP,
SHORT_LINE_HEIGHT,
getResources().getDisplayMetrics());
initPaint();
private void initPaint() {
mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCirclePaint.setColor(Color.RED);
// 将画笔设置为空心
mCirclePaint.setStyle(Style.STROKE);
// 设置画笔宽度
mCirclePaint.setStrokeWidth(mCircleLineWidth);
mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mLinePaint.setColor(Color.RED);
mLinePaint.setStyle(Style.FILL_AND_STROKE);
// 设置画笔宽度
mLinePaint.setStrokeWidth(mLineWidth);
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
protected void onDraw(Canvas canvas) {
canvas.setDrawFilter(mDrawFilter);
super.onDraw(canvas);
// 绘制表盘
drawCircle(canvas);
// 绘制刻度
drawLines(canvas);
* 绘制刻度
* @param canvas
private void drawLines(Canvas canvas) {
for (int i = 0; i &= 360; i++) {
if (i % 30 == 0) {
mLineBottom = mLineTop + mLongLineH
mLinePaint.setStrokeWidth(mLineWidth);
mLineBottom = mLineTop + mShortLineH
mLinePaint.setStrokeWidth(mHalfLineWidth);
if (i % 6 == 0) {
canvas.save();
canvas.rotate(i, mHalfWidth, mHalfHeight);
canvas.drawLine(mLineLeft, mLineTop, mLineLeft, mLineBottom, mLinePaint);
canvas.restore();
* 绘制表盘
* @param canvas
private void drawCircle(Canvas canvas) {
canvas.drawCircle(mHalfWidth, mHalfHeight, mHalfWidth - mHalfCircleLineWidth, mCirclePaint);
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mHalfWidth = w / 2;
mHalfHeight = h / 2;
mLineLeft = mHalfWidth - mHalfLineW
mLineTop = mHalfHeight - mHalfWidth + mFixLineH
同样的,有兴趣的同学可以自己补上文字;
四、canvas.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 native void skew(float sx, float sy);
这个方法只要理解了两个参数即可:
float sx:将画布在x方向上倾斜相应的角度,sx为倾斜角度的tan值;
float sy:将画布在y轴方向上倾斜相应的角度,sy为倾斜角度的tan值;
注意,这里全是倾斜角度的tan值,比如我们打算在X轴方向上倾斜45度,tan45=1;
先在X 轴上倾斜45 度,我们一起看看:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLUE);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
// x 方向上倾斜45 度
canvas.skew(1, 0);
mPaint.setColor(0x8800ff00);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
}效果如下:
再在y轴上倾斜45度看看:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLUE);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
// y 方向上倾斜45 度
canvas.skew(0, 1);
mPaint.setColor(0x8800ff00);
canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);
}此时效果如下:
关于Canvas(画布)的translate(平移)、scale(缩放) 、rotate(旋转) 、skew(错切)就说这么多,这些方法都不复杂,而灵活的使用往往能解决绘制中很多看似复杂的问题,所以重在理解,并在看到与之相关的效果时能够及时恰当的进行关联。
当然对Canvas的操作往往使用Matrix(后面会单独讲)也能达到同样的效果,想看例子可参考&一个绚丽的loading动效分析与实现!
源码下载链接
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 1234567891011 Copyright & &&版权所有> html5 canvas怎么以某个中心点旋转图片
html5 canvas怎么以某个中心点旋转图片
gxh66_5688 & &
发布时间: & &
浏览:5 & &
回复:0 & &
悬赏:0.0希赛币
html5 canvas如何以某个中心点旋转图片
var num=0;function draw(){ num+=1; if(num==60) num=1;
cxt.clearRect(0,0,canvas.width,canvas.height);
cxt.save();//将坐标原点平移到当前图片所在的位置,width,height分别为图片的坐标,这个可以根据自己的需要进行更改&& cxt.translate(width,height);//将坐标原点平移到要中心点,这里是以图片的底部为中心点进行旋转13,62为图片本身的中心点&&& cxt.translate(13,62);//每次旋转6度&&& cxt.rotate(num*(Math.PI/30));&&& cxt.translate(-13,-62);//因为是以图片的底部作为中心点,所以这时候的图片位置在画布的原点上&&& cxt.drawImage(aimg,0,0);&&& cxt.restore(); }
本问题标题:
本问题地址:
温馨提示:本问题已经关闭,不能解答。
暂无合适的专家
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&Android自定义View之Canvas的使用
在Android项目开发中,很多时候自带的View不能满足我们的需要,而需要我们继续View类或其子类去实现我们的自定义View。不管是Android,还是HTML5,绘制View都用了一个画布(Canvas)的概念。下面先上一段我写的测试代码,再分析要点。
public class CocoView extends View {
private static final String tag = &CocoView&;
private Paint rectPaint = new Paint();
private Paint circlePaint = new Paint();
private Paint linePaint = new Paint();
private Paint pathPaint = new Paint();
private Paint textPaint = new Paint();
public CocoView(Context context) {
super(context);
initCocoView();
public CocoView(Context context, AttributeSet attrs) {
super(context, attrs);
initCocoView();
private void initCocoView() {
rectPaint.setColor(getResources().getColor(R.color.color1));
linePaint.setStrokeWidth(3);
circlePaint.setColor(getResources().getColor(R.color.color2));
circlePaint.setAntiAlias(true);
circlePaint.setAlpha(120);
linePaint.setColor(getResources().getColor(R.color.color3));
linePaint.setStrokeWidth(6);
pathPaint.setColor(getResources().getColor(R.color.color4));
pathPaint.setStyle(Style.STROKE); // 还有FILL, FILL_AND_STROKE
pathPaint.setStrokeWidth(3);
textPaint.setColor(Color.BLACK);
textPaint.setTextSize(28);
protected void onDraw(Canvas canvas) {
Log.e(tag, &onDraw : & + getMeasuredWidth() + &, & + getMeasuredHeight());
// 1.绘颜色
canvas.drawColor(Color.WHITE);
// 2.绘矩形
canvas.drawRect(100, 100, 300, 300, rectPaint);
canvas.save();
// 设置只在指定范围内绘制(即下面的绘制只在这个范围内的部分才可见),注意:1、坐标还是按View的坐标;2、不会影响前面已经绘制的;3、加save()和restore()块,是为了不影响restore()后面绘制
canvas.clipRect(200, 200, 350, 350);
// 3.绘圆形
canvas.drawCircle(300, 300, 100, circlePaint);
canvas.restore();
// 4.绘线条
canvas.drawLine(0, 0, 300, 300, linePaint);
// 5.绘路径、不规则图形
Path path = new Path();
path.moveTo(50, 50);
path.lineTo(300, 50);
path.lineTo(50, 300);
path.close();
canvas.drawPath(path, pathPaint);
canvas.save();
canvas.translate(50, 50); // 画布移动,注意:默认的画布是与View的坐标对齐的,移动后就会与View的坐标产生偏移,而下面绘制的坐标将是基于移动后的画布
canvas.scale(0.5f, 0.5f); // 画布缩放,理解一下,一张标有X,Y坐标的图片,缩放后,下面操作的坐标,都是按缩放后画布的坐标,也实际尺寸不同。如果是先scale再translate,则translate的坐标也是基于缩放后画布的坐标
canvas.rotate(45); // 画布旋转(默认以原点,顺时针)
// 6.绘图片
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
canvas.drawBitmap(bitmap, 50, 50, null);
canvas.restore();
// 7.绘文本
canvas.drawText(&CocoView&, 50, 50, textPaint);
canvas.save();
Matrix matrix = new Matrix();
matrix.postTranslate(300, 300);
canvas.concat(matrix);
canvas.skew(1, 0); // 倾斜
canvas.drawRect(0, 0, 100, 100, rectPaint);
canvas.restore();
Paint类:主要用来定义画笔的属性,不管是画图形、画文字、画图片,都是通过画笔来画,而画笔有粗有细、有各种颜色设置等,就在Paint类中定义。
Canvas类:画布,带有X,Y坐标系。可以在画布上画各种图形、线条、文字、图片,而所画出来的内容与效果,就是这个自定义View将要显示成的样子。
上述例子中只列举了常用几种图片的画法,当然还有很多图形画法没有列举出来,可参考Android API文档,也比较容易掌握。下面重点说一下画布的移动、缩放、 旋转、倾斜操作,与及save()、restore()的用法。
要灵活地掌握这些用法,建议,先了解一下View的绘制过程。可参考:
View绘制过程分析之measure
View绘制过程分析之layout
View绘制过程分析之draw
要明白一点就是:View的大小和相对于父布局的位置,是已经在measure()和layout()阶段中确定的了,而draw()操作是在这两个阶段之后的操作。我们可以理解为,在我们调用draw()方法绘制自定义View之前,父布局已经为这个View确定好了一个矩形的框框,我们在这个框框上放一张画布,我们在画布上作画。画布可以无限放大,可以随意移动位置,可以随意旋转,而真正显示给用户看到的样子,只是透过这个矩形框框所看到的部分。更形象的理解,我们在支架上固定放一相机,相机对面是一张大画板,你可以随意移动画板,随意涂鸦,而当按下快门,真正映成相片的那一个矩形框框的区域。
画布可以理解为一张带了X,Y坐标系的底图,以(0,0)为原点。
画布移动(translate):这个原点就偏离了View的原点(即那个矩形框框的),可以这样理解,绘图是在画布上绘,不是在View上绘,所以这些方法用到的坐标,都是画布的坐标,按下快门,相机中所成的像才是View的效果。
画布旋转(rotate):可联想到你将现实中的画布、画板按时针方法旋转一个角度。旋转有一个基点,即以哪个点为支点去旋转。前面说到画布是有X,Y坐标系的,我们可以在脑海中联想,这个坐标系,全部已经画成了X,Y轴交叉的线条,整张画布就成了格子簿。假设旋转45度角,那我们看到的这些X,Y线,已经不是横、竖了,而是倾斜了45度角。但绘图是按布局的坐标去绘的。OK,我们得把自己的头倾斜45度,去看着画布绘图,这些我们眼里看到的画布又是正的了。注意:那个View矩形框框是不变的!
画布缩放(scale):与现实中画布不同,Canvas支持缩放。缩放是对整对画布缩放(这些可以理解画布为了张画有X,Y交叉线条的图片),坐标X,Y值与实现的值已经不同,还是要紧记一点,我们在画布上画,不管画布上X,Y值多大多小,我们都是按画布的坐标来画!
画布倾斜(skew):还记得以前学数学时,正方形、长方形,是怎样变成平行四边形的吗?两个参数,skew(画布的Y边向X轴方向倾斜的角度tan值,画布的X边向Y轴方向倾斜的角度tan值)。这些候,画布上X,Y线已经不再是垂直交叉了,构成的格格已经不再上正方形了。而不管画布的坐标系变成怎么样,都得按画布的坐标系来绘画。
经过以上画布的变换与图片的绘制后,“咔嚓&一声,拍照成像,View最终效果形成。
能理解上面的内容,就不难理解save()和restore()的作用了。
canvas.save();
//在这中间,根据绘图需要,可对画布做各种移动、旋转、缩放、倾斜操作。
canvas.restore();
//在这之后,画布恢复成原来的样子,原点(0,0)与View框框原点对齐。
@容新华技术博客 -&http://blog.csdn.net/rongxinhua&- 原创文章,转载请注明出处
> 本站内容系网友提交或本网编辑转载,其目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请及时与本网联系,我们将在第一时间删除内容!
转载请标明出处:http://blog.csdn.net/lmj/article/details/ 很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章.先总结下自定义View的步骤: 1.自定义View的属 ...
转载请标明出处:http://blog.csdn.net/lmj/article/details/ 继续自定义View之旅,前面已经介绍过一个自定义View的基础的例子,Android 自定义View (一),如果你还对自定义View不了解可以去看看.今天给大家带来一个稍微复杂点的例子. 自定义View显示一张图片,下面包含 ...
关于自定义View就讲到这了,自定义View可以说有很大的用途,在这里我们小小的总结一下,哈哈,也算是一个笔记,方便以后学习. 一.使用自定义View的两种基本方法 1. setContentView(new HelloView(this)); 这种方法是在Activity中直接使用View. 优点:这样布局的话可以很大程度上的自己控制View,绘图灵活,可 ...
例子如下:Android 自定义View 密码框 例子
1 良好的自定义View 易用,标准,开放. 一个设计良好的自定义view和其他设计良好的类很像.封装了某个具有易用性接口的功能组合,这些功能能够有效地使用CPU和内存,并且十分开放的.但是,除了开始一个设计良好的类之外,一个自定义view应该: l 符合安卓标准 l 提供能够在Android
Android自定义View实现很简单 继承View,重写构造函数.onDraw,(onMeasure)等函数. 如果自定义的View需要有自定义的属性,需要在values下建立attrs.xml.在其中定义你的属性. 在使用到自定义View的xml布局文件中需要加入xmlns:前缀=&/apk/ ...
很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章.先总结下自定义View的步骤: 1.自定义View的属性 2.在View的构造方法中获得我们自定义的属性 [ 3.重写onMesure ] 4.重写onDraw 我把3用[]标出了,所以说 ...
android 自定义view实现图形移动
--(自定义view及属性) 转载说明出处:http://blog.csdn.net/liyulei/article/details/7204191
首先,先了解一下需求.有一个看起来类似立体的图,图 ...
Android自定义View实现很简单 继承View,重写构造函数.onDraw,(onMeasure)等函数. 如果自定义的View需要有自定义的属性,需要在values下建立attrs.xml.在其中定义你的属性. 在使用到自定义View的xml布局文件中需要加入xmlns:前缀=&/apk/ ...

我要回帖

更多关于 canvas清除画布 的文章

 

随机推荐