我正在尝试用户手指(触摸)绘制线条。如果没有缩放,那么实施起来非常容易 没有缩放的绘图在这里是完美的截图
运作良好。如你看到的。
但如果我缩放画布,它会开始绘制具有一些边距/测量误差/容差的点。在计算缩放的触摸点时,我似乎没有提前采取一些价值,我尝试了很多不同的公式,但没有任何帮助。
似乎我必须考虑到某些delta值中的问题
因为如果我使用这个版本的缩放功能,它效果很好,但只能缩放到左上角。
canvas.scale(mScaleFactor, mScaleFactor);
使用此缩放
canvas.scale(mScaleFactor, mScaleFactor, scalePointX, scalePointY);
多点触控变焦(捏合)效果很好,但坐标不正确。
请帮助解决问题,似乎在计算缩放的x和y时我必须采用这些scalePointX, scalePointY
变量。
这是我的代码。任何帮助将受到高度赞赏。
private void initWorkSpace(Context context) {
mPaint = new Paint();
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
mRect = new Rect();
mPath = new Path();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeWidth(10f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.getClipBounds(mRect);
canvas.save();
canvas.scale(mScaleFactor, mScaleFactor, scalePointX, scalePointY);
canvas.translate(mRect.top,mRect.left);
canvas.drawPath(mPath, mPaint);
canvas.restore();
}
// when ACTION_DOWN start touch according to the x,y values
private void startTouch(float x, float y) {
mPath.moveTo(x, y);
mX = x;
mY = y;
}
// when ACTION_MOVE move touch according to the x,y values
private void moveTouch(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOLERANCE || dy >= TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
public void clearCanvas() {
mPath.reset();
invalidate();
}
// when ACTION_UP stop touch
private void upTouch() {
mPath.lineTo(mX, mY);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
final int action = ev.getAction();
Log.e("TOUCH","REAL X :" + ev.getX() + " REAL Y : " + ev.getY());
Log.e("TOUCH","RECT TOP :" + mRect.top + " RECT LEFT : " + mRect.left + " RECT RIGHT : " + mRect.right + " RECT BOTTOM :" + mRect.bottom);
final float scaledX = ev.getX()/mScaleFactor+mRect.left*mScaleFactor;
final float scaledY = ev.getY()/mScaleFactor+mRect.top*mScaleFactor;
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
/*final float x = (ev.getX() - scalePointX) / mScaleFactor;
final float y = (ev.getY() - scalePointY) / mScaleFactor;
cX = x - mPosX + scalePointX; // canvas X
cY = y - mPosY + scalePointY; // canvas Y*/
// Remember where we started
mLastTouchX = scaledX;
mLastTouchY = scaledY;
Log.e("DOWN","Scale FACTOR : " + mScaleFactor);
Log.e("DOWN","X : " +mLastTouchX + " Y :" + mLastTouchY + " scalePointX : " + scalePointX + " scalePointY : " + scalePointY );
Log.e("DOWN","Last X : " + mLastTouchY + " Last Y :" + mLastTouchY);
startTouch(mLastTouchX, mLastTouchY);
invalidate();
break;
}
case MotionEvent.ACTION_MOVE: {
/* final float x = (ev.getX() - scalePointX) / mScaleFactor;
final float y = (ev.getY() - scalePointY) / mScaleFactor;
cX = x - mPosX + scalePointX; // canvas X
cY = y - mPosY + scalePointY; // canvas Y
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleDetector.isInProgress()) {
final float dx = x - mLastTouchX; // change in X
final float dy = y - mLastTouchY; // change in Y
mPosX += dx;
mPosY += dy;
invalidate();
}*/
Log.e("ACTION_MOVE","Scale FACTOR : " + mScaleFactor);
Log.e("ACTION_MOVE","X : " + scaledX + " Y :" + scaledY + " cX : " + cX + " cY : " + cY );
Log.e("ACTION_MOVE","Last X : " + mLastTouchX + " Last Y :" + mLastTouchY);
mLastTouchX = scaledX;
mLastTouchY = scaledY;
moveTouch(scaledX, scaledY);
invalidate();
break;
}
case MotionEvent.ACTION_UP: {
mLastTouchX = 0;
mLastTouchY = 0;
upTouch();
invalidate();
}
}
return true;
}
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.1f, Math.min(mScaleFactor, 10.0f));
mScaleFactor = (mScaleFactor < 1 ? 1 : mScaleFactor);
invalidate();
return true;
}
}
答案 0 :(得分:0)
您只需要将屏幕坐标转换为修改后的画布坐标: 请执行以下方法:
///如果您已经移动(转移)了画布: TouchX = TouchX-translatedX; TouchY = TouchY-translationY;
//如果已缩放画布: TouchX = TouchX / scaleFactor; TouchY = TouchY / scaleFactor;
//如果已翻译画布并对其进行缩放: TouchX =(TouchX-translatedX)/ scaleFactor; TouchY =(TouchY-translatedY)/ scaleFactor;
//然后使用此TouchX和TouchY进行绘制。
我希望这会有所帮助。