java - 缩放时画布不在手指位置上绘制
问题描述
我正在尝试制作一个绘画应用程序。缩放有点工作,当我尝试在缩放后在画布上绘制时,它不会在手指的位置上绘制。相反,它会在设备屏幕上绘制比例。
我做了一些研究,但找不到解决方案的答案。-> 浮点 x = (event.getX() - scalePointX)/mScaleFactor;// 不起作用,
我试图实现矩阵但没有成功。当画布放大或缩小时,有人可以帮我在手指上画画吗?
谢谢!
public class paintView extends View {
Paint paint;
Path path;
Bitmap bitmap;
Canvas mcanvas;
private final float TOUCH_TOLERANCE = 4;
private float mX, mY;
public static final int DEFAULT_BG_COLOR = Color.WHITE;
private int backgroundColor = DEFAULT_BG_COLOR;
private ArrayList<FingerPath> paths = new ArrayList<>();
private Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
private final ScaleGestureDetector mScaleGesture;
private float mScaleFactor = 1.f;
private float mPosX;
private float mPosY;
private float scalePointX, scalePointY;
private Rect clipBounds_canvas;
public paintView(Context context) {
this(context, null);
}
public paintView(Context context, AttributeSet attrs){
super(context, attrs);
mScaleGesture = new ScaleGestureDetector(context, new ScaleListener());
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(8f);
}
public void init(DisplayMetrics metrics){
int height = metrics.heightPixels;
int width = metrics.widthPixels;
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mcanvas = new Canvas(bitmap);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.save();
mcanvas.drawColor(backgroundColor);
clipBounds_canvas = canvas.getClipBounds();
for(FingerPath fp: paths){
paint.setMaskFilter(null);
mcanvas.drawPath(fp.path, paint);
}
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor,scalePointX,scalePointY);
canvas.drawBitmap(bitmap, 0, 0, mBitmapPaint);
canvas.restore();
}
private void touchStart(float x, float y){
path = new Path();
FingerPath fp = new FingerPath(path);
paths.add(fp);
path.reset();
path.moveTo(x,y);
mX = x;
mY = y;
}
private void touchMove(float x, float y){
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if(dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE ){
path.quadTo(mX, mY, (x+mX)/2, (y+mY)/2);
mX = x;
mY = y;
}
}
private void touchUp(){
path.lineTo(mX,mY);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
final float x = (event.getX() - scalePointX)/mScaleFactor;
final float y = (event.getY() - scalePointY)/mScaleFactor;
mScaleGesture.onTouchEvent(event);
final int action = event.getAction();
switch(action & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_DOWN:
touchStart(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touchMove(x,y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touchUp();
invalidate();
break;
}
return true;
}
public class FingerPath {
public Path path;
public FingerPath(Path path) {
this.path = path;
}
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
scalePointX = detector.getFocusX();
scalePointY = detector.getFocusY();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.5f, Math.min(mScaleFactor, 3.0f));
//zoom out 'up to' the size of canvas(screen size)
//mScaleFactor = (mScaleFactor < 1 ? 1 : mScaleFactor);
invalidate();
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
}
}
解决方案
我遇到了这个问题,并且能够用This stack overflow question解决它。我所做的是存储当前的比例偏移量,当我绘制新路径时,我将绘制矩阵偏移这个存储的值。您的解决方案非常接近,您可以缩放绘图矩阵,而不是缩放画布。还有一个友好的提示,您可能还需要在缩放后缩放线条粗细,因此请使用与缩放相同的值。
推荐阅读
- python - Pandas CSV 的 KeyError
- javascript - 基于对象数组中唯一键的分组
- postgresql - Postgresql 热备单表复制
- symfony - 通过某个值动态获取控制器中的服务实例
- javascript - 鼠标悬停时保留窗口对话框,否则
- python - 从 df.columns 中的文本中删除非英语单词 单词包含字母和数字
- python - 如何使用python的键盘模块键入任何给定的包含特殊字符的字符串?
- mule - MULE4中缓存条目的有效期是如何计算的?
- javascript - JavaScript:函数引用存储在数组中时的执行上下文
- kotlin - 为什么索引是集合而不是列表的属性?