Android专注于canvas.scale操作后放置点的难度

时间:2013-03-13 09:34:22

标签: android view bitmap scaling gesture

这是我关于stackoverflow的第一个问题,所以请放轻松我。

让我给你一些背景知识:

我创建了一个应用程序来操作视图中的位图(在这种情况下,图像是设施的地图),我使用位图上点的实际x和y坐标在地图上放置点。我通过根据手势所做的图像放置的变化修改此偏移值来跟踪位图左上角相对于屏幕左上角的偏移量。这实际上非常适合平移,这使我可以轻松地将屏幕坐标(从长按手势)转换为位图上的实际坐标。有了这个,我在地图上绘制一个圆圈,并允许用户创建一个“兴趣点”,我将其推送到数据库。

处理缩放时出现问题。我正在缩放一个简单的
    canvas.scale(scalefastor ,scalefactor); 在onDraw中。使用此缩放,actaul缩放相对于图像的左上角,因此缩放的缩放不直观,因为您尝试放大的实际位置非常快速地在屏幕外运行。然而,以这种方式缩放图像不会影响图像的实际偏移,因此我的点放置仍然是准确的。我使用以下简单的数学来完成这个:

bitmapXCoordinate = (event.getX() - xOffset) /scaleFactor;

我想用

canvas.scale(scalefactor, scalefactor, gestureFocusX, gestureFocusY);

为了让变焦对用户保持直观,但这会对位图的实际矩阵进行转换,以便我的点位置不再起作用。似乎位图上的点现在以某种方式相对于比例的焦点而且所有放置的点都关闭并且倾向于该焦点。 我知道我需要考虑矩阵上的这种转换,以便正确地放置我的点,但显然,它需要一个比我更聪明的人。解决方案可能很简单,但我已经在这方面工作了好几天试图解释这个新的偏移量,我只是无法取得任何实际进展。任何对此解决方案的见解都将非常感激。

1 个答案:

答案 0 :(得分:0)

我挣扎了一个多星期,尝试了各种解决方案,然后才找到了一些东西,而我却完全不理解;),有工作的好处。您需要一个捏缩放(或其他)图像视图的工作实现,您可以从中获取当前比例和转换值。

我认为这个问题的困难源于这样一个事实:有两个问题需要解决:1,解码可能缩放和翻译的图像的点击,2,渲染存储的点击位置。

无论如何,要代码。要注册触摸:

private Float[] getNormalizedTouchLocation(MotionEvent event) {
    float xpos = getOffsetX();
    float ypos = getOffsetY();
    float scale = getScaleFactor();

    Drawable drawable = getDrawable();
    Rect image_bounds = drawable.getBounds();

    Matrix matrix = new Matrix(getImageMatrix());

    matrix.postScale(scale, scale, mPivotX, mPivotY);
    matrix.postTranslate(xpos, ypos);

    RectF image_rect = new RectF(image_bounds);

    matrix.mapRect(image_rect);

    float x = ((event.getX() - image_rect.left) / scale);
    float y = ((event.getY() - image_rect.top) / scale);

    return new Float[]{x, y};
}

然后渲染:

public void onDraw(Canvas canvas) {
    // Ensure parent leaves the canvas *unscaled* and *untranslated*.
    super.onDraw(canvas);

    float xpos = getOffsetX();
    float ypos = getOffsetY();
    float scale = getScaleFactor();

    canvas.save();

    Matrix matrix = canvas.getMatrix();
    matrix.postScale(scale, scale, mPivotX, mPivotY);
    matrix.postTranslate(xpos, ypos);

    Drawable drawable = getDrawable();
    Rect image_bounds = drawable.getBounds();

    RectF image_rect = new RectF(image_bounds);

    Matrix image_matrix = new Matrix(getImageMatrix());
    image_matrix.postScale(scale, scale, mPivotX, mPivotY);
    image_matrix.postTranslate(xpos, ypos);

    image_matrix.mapRect(image_rect);

    // mPoints is a list of float[2] coordinates.
    for (Float[] coord: mPoints) {

        // Draw a bitmap centered on each touch position.
        float x = (scale * coord[0] + image_rect.left) - mBitmap.getWidth() / 2;
        float y = (scale * coord[1] + image_rect.top) - mBitmap.getHeight() / 2;

        canvas.drawBitmap(mBitmap, x, y, mPaint);
    }

    canvas.restore();
}

希望这适合你!显然,这里的解决方案只能正确渲染在相同的渲染大小的图像上以相同的屏幕分辨率等登记的点 - 它可能会被修改为存储图像宽度/高度的分数,以便在图像/分辨率下工作。