当前位置:   article > 正文

Android涂鸦画板原理详解——从初级到高级(二)_画画涂鸦游戏原理

画画涂鸦游戏原理

前言

前面写了《Android涂鸦画板原理详解——从初级到高级(一)》,讲了涂鸦原理初级和中级的应用,现在讲解高级应用。如果没有看过前面一篇文章的同学,建议先去看看哈。

准备

高级涂鸦涉及到图片操作,包括对图片进行缩放移动、涂鸦等,这里涉及到矩阵的变换。关于矩阵变换的知识,请查看我的另一篇文章《浅谈矩阵变换——Matrix》。根据文中的介绍,接下来使用变换坐标系的空间想象去理解涂鸦中涉及到的矩阵变换。

高级涂鸦

高级涂鸦支持对图片涂鸦, 可移动缩放图片。思路如下:

  1. 创建自定义View: AdvancedDoodleView,由外部创建时传入Bitmap图像对象。
  2. 在View大小确定时候的回调onSizeChanged()中进行初始化操作,计算图片居中显示的所需参数,如图片缩放倍数和偏移值。
  3. 定义PathItem类,封装涂鸦轨迹,包括Path和偏移值等信息。
class PathItem {
   
    Path mPath = new Path(); // 涂鸦轨迹
    float mX, mY; // 轨迹偏移值
}
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 单击时需要判断是否点中某个涂鸦,Path提供了接口computeBounds()计算当前图形的矩形范围,可以通过判断单击的点是否在矩形范围内判断。使用TouchGestureDetector识别单击和滑动手势。(TouchGestureDetector在我另一个项目Androids中,使用时需要导入依赖)

  2. 滑动过程中需要判断当前是否有选中的涂鸦,如果有则对该涂鸦进行移动,把偏移值记录在PathItem中;没有则绘制新的涂鸦轨迹。

  3. 监听双指缩放手势,计算图片缩放的倍数。

4-6中涉及到的触摸坐标要换算成对应图片坐标系中的坐标,稍后详细讲解 )

  1. 在AdvancedDoodleView的onDraw方法中,根据图片缩放倍数和偏移值绘制图片;绘制每个PathItem之前根据偏移值移动画布。

坐标映射

选择画布和图片共用一个坐标系,了解图片的位置信息后,最后需要处理的就是,屏幕坐标系与图片(画布)坐标系的映射,即把屏幕上滑动的轨迹投射到图片中。

从上图的分析中,我们可以得出如下映射关系:

图片坐标x=(屏幕坐标x-图片在屏幕坐标系x轴上的偏移量)/图片缩放倍数

图片坐标y=(屏幕坐标y-图片在屏幕坐标系y轴上的偏移量)/图片缩放倍数
  • 1
  • 2
  • 3

(注意,图片是以左上角为中心进行缩放的)

对应代码:

/**
 * 将屏幕触摸坐标x转换成在图片中的坐标x
 */
public final float toX(float touchX) {
    return (touchX - mBitmapTransX) / mBitmapScale;
}

/**
 * 将屏幕触摸坐标y转换成在图片中的坐标y
 */
public final float toY(float touchY) {
    return (touchY - mBitmapTransY) / mBitmapScale;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

可见,屏幕坐标投射到图片上时,需要减去偏移量,因为图片的位置是一直不变的,我们对图片进行偏移,其实是对View的画布进行偏移。

最终实现效果如下:

代码如下:

public class AdvancedDoodleView extends View {
   

    private final static String TAG = "AdvancedDoodleView";

    private Paint mPaint = new Paint();
    private List<PathItem> mPathList = new ArrayList<>(); // 保存涂鸦轨迹的集合
    private TouchGestureDetector mTouchGestureDetector; // 触摸手势监听
    private float mLastX, mLastY;
    private PathItem mCurrentPathItem; // 当前的涂鸦轨迹
    private PathItem mSelectedPathItem; // 选中的涂鸦轨迹

    private Bitmap mBitmap;
    private float mBitmapTransX, mBitmapTransY, mBitmapScale = 1;

    public AdvancedDoodleView(Context context, Bitmap bitmap) {
   
        super(context);
        mBitmap = bitmap;

        // 设置画笔
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(20);
        mPaint.setAntiAlias(true);
        mPaint.setStrokeCap(Paint.Cap.ROUND);

        // 由手势识别器处理手势
        mTouchGestureDetector = new TouchGestureDetector(getContext(), new TouchGestureDetector.OnTouchGestureListener() {
   

            RectF mRectF = new RectF();

            // 缩放手势操作相关
            Float mLastFocusX;
            Float mLastFocusY;
            float mTouchCentreX, mTouchCentreY;

            @Override
            public boolean onScaleBegin(ScaleGestureDetectorApi27 detector
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/598697
推荐阅读
相关标签
  

闽ICP备14008679号