捏缩放后获取正确的坐标(绘图线)Android Canvas

时间:2015-08-30 18:02:00

标签: android canvas drawing android-canvas android-view

我正在尝试用户手指(触摸)绘制线条。如果没有缩放,那么实施起来非常容易 没有缩放的绘图在这里是完美的截图

enter image description here

运作良好。如你看到的。

但如果我缩放画布,它会开始绘制具有一些边距/测量误差/容差的点。在计算缩放的触摸点时,我似乎没有提前采取一些价值,我尝试了很多不同的公式,但没有任何帮助。

以下是缩放画布的结果。 enter image description here

似乎我必须考虑到某些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;
        }
    }

1 个答案:

答案 0 :(得分:0)

您只需要将屏幕坐标转换为修改后的画布坐标: 请执行以下方法:

///如果您已经移动(转移)了画布:     TouchX = TouchX-translatedX;     TouchY = TouchY-translationY;

//如果已缩放画布:    TouchX = TouchX / scaleFactor;    TouchY = TouchY / scaleFactor;

//如果已翻译画布并对其进行缩放:    TouchX =(TouchX-translatedX)/ scaleFactor;     TouchY =(TouchY-translatedY)/ scaleFactor;

//然后使用此TouchX和TouchY进行绘制。

我希望这会有所帮助。