如何使用位图在缩放的画布上绘制线条,圆圈

时间:2014-05-09 14:27:00

标签: android canvas drawing scaling zooming

我有一个带有位图图像的画布。我可以使用捏放大和缩小手势来缩放整个画布。现在我想在缩放的画布上绘制线条或徒手画,即放大。虽然这样做,但是当画布没有缩放时我得到准确的结果但是当画布放大时我会在某个随机位置绘制线条。

未缩放画布时的线条绘制

Line drawing when canvas is not scaled

画布在onTouchMove中放大时的线条绘制

Line Drawing when canvas is zoomed in onTouchMove

用户在绘制线条时缩小或onTouchEnd时的结果。 线应位于U处,如第二张图所示。

Result when user zooms out or onTouchEnd while drawing line. LINE SHOULD BE AT U AS SHOWN IN THE SECOND FIGURE

这是我的代码

@Override
public boolean onTouchEvent(MotionEvent event)
{
    float x = event.getX();
    float y = event.getY();

    if(WriteApp.getAction().equalsIgnoreCase("draw"))
    {
        isDrawing=true;
        int touchCount = event.getPointerCount();
        //Log.i("", "from on draw x"+x+" y "+y);
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i("", "touch start x"+x+" y "+y);
            touch_start(x, y);
            this.invalidate();
            break;
        case MotionEvent.ACTION_MOVE:

            touch_move(x, y);
            this.invalidate();
            break;
        case MotionEvent.ACTION_UP:
            Log.i("", "touch end x"+x+" y "+y);
            touch_up();
            this.invalidate();
            break;
        }
        return true;
    }
    isDrawing=false;
    switch (event.getAction() & MotionEvent.ACTION_MASK)
    {
    case MotionEvent.ACTION_DOWN:

        mode = DRAG;

        //We assign the current X and Y coordinate of the finger to startX and startY minus the previously translated
        //amount for each coordinates This works even when we are translating the first time because the initial
        //values for these two variables is zero.
        startX = event.getX()-previousTranslateX;
        startY = event.getY()-previousTranslateY;
        break;

    case MotionEvent.ACTION_MOVE:
        translateX = event.getX()-startX;
        translateY = event.getY()-startY;

        //We cannot use startX and startY directly because we have adjusted their values using the previous translation values.
        //This is why we need to add those values to startX and startY so that we can get the actual coordinates of the finger.
        double distance = Math.sqrt(Math.pow(event.getX()-(startX + previousTranslateX), 2) +
                Math.pow(event.getY()-(startY + previousTranslateY), 2)
                );

        if(distance > 0)
        {
            dragged = true;
        }

        break;

    case MotionEvent.ACTION_POINTER_DOWN:
        mode = ZOOM;
        break;

    case MotionEvent.ACTION_UP:
        mode = NONE;
        dragged = false;

        //All fingers went up, so let’s save the value of translateX and translateY into previousTranslateX and
        //previousTranslate
        previousTranslateX = translateX;
        previousTranslateY = translateY;
        break;

    case MotionEvent.ACTION_POINTER_UP:
        mode = DRAG;

        //This is not strictly necessary; we save the value of translateX and translateY into previousTranslateX
        //and previousTranslateY when the second finger goes up
        previousTranslateX = translateX;
        previousTranslateY = translateY;
        break;
    }

    detector.onTouchEvent(event);

    //We redraw the canvas only in the following cases:
    //
    // o The mode is ZOOM
    // OR
    // o The mode is DRAG and the scale factor is not equal to 1 (meaning we have zoomed) and dragged is
    // set to true (meaning the finger has actually moved)
    if ((mode == DRAG && scaleFactor != 1f && dragged) || mode == ZOOM)
    {
        invalidate();
    }

    return true;
}

@Override
public void onDraw(Canvas canvas) {

    canvas.save();

    //If translateX times -1 is lesser than zero, let’s set it to zero. This takes care of the left bound
    //if(((translateX*-1)(scaleFactor-1)*displayWidth)<0)
    //If translateX times -1 is lesser than zero, let's set it to zero. This takes care of the left bound
    if((translateX * -1) < 0) {
        translateX = 0;
    }

    //This is where we take care of the right bound. We compare translateX times -1 to (scaleFactor - 1) * displayWidth.
    //If translateX is greater than that value, then we know that we've gone over the bound. So we set the value of 
    //translateX to (1 - scaleFactor) times the display width. Notice that the terms are interchanged; it's the same
    //as doing -1 * (scaleFactor - 1) * displayWidth
    else if((translateX * -1) > (scaleFactor - 1) * displayWidth) {
        translateX = (1 - scaleFactor) * displayWidth;
    }

    if(translateY * -1 < 0) {
        translateY = 0;
    }

    //We do the exact same thing for the bottom bound, except in this case we use the height of the display
    else if((translateY * -1) > (scaleFactor - 1) * displayHeight) {
        translateY = (1 - scaleFactor) * displayHeight;
    }


    //We need to divide by the scale factor here, otherwise we end up with excessive panning based on our zoom level
    //because the translation amount also gets scaled according to how much we’ve zoomed into the canvas.
    canvas.translate(translateX, translateY);

    //We’re going to scale the X and Y coordinates by the same amount
    canvas.scale(scaleFactor, scaleFactor);

    super.onDraw(canvas);

    //The rest of your canvas-drawing code 


    canvas.drawBitmap( mBitmap, 0, 0, mBitmapPaint);
    if(scaleFactor!=1.f)
        canvas.restore();

    if(isDrawing)
        canvas.drawPath( mPath,  dPaint);

    if(scaleFactor==1.f)
        canvas.restore();

}

1 个答案:

答案 0 :(得分:0)

首先发布您的代码

用于触摸捏缩放缩小

找到此网址以供参考

https://github.com/MikeOrtiz/TouchImageView/blob/master/src/com/ortiz/touch/TouchImageView.java