使用矩阵在焦点上缩放图像视图的正确方法 [英] Correct way to use a matrix to zoom an imageview around a focal point

查看:104
本文介绍了使用矩阵在焦点上缩放图像视图的正确方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先让我说我已经阅读了很多缩放问题并重新计算了此处的坐标.但是我似乎无法将它们应用于我的情况.

Let me start off by saying I've read through a fair amount of zoom questions and recalculating coordinates on here. But I can't seem to apply them to my situation.

我有一个可以缩放和滚动的自定义ImageView类.我遇到的问题来自按此顺序执行以下操作:

I have a custom ImageView class that can zoom and scroll. The problem I am having comes from doing the following in this order:

  1. 放大某个点,然后将该点用作焦点(有效)
  2. 在放大的同时滚动
  3. 尝试放大/缩小其他点(不起作用)

这是自定义视图的示例.有两个圆圈:红色和绿色.红色是焦点应该的位置,绿色是焦点接近实际上的位置.

Here is a example of the custom view. There are two circles: red and green. red is where the focal point should be and green is where the focal point is close to where it actually is.

当我尝试放大橙色圈出的区域时会出现问题.在下面的图片中,我尝试放大了橙色圆圈区域(不是很多,只是为了显示计算出焦点的位置).如下所示,红色圆圈正确地计算了新的焦点,但是由于某种原因,绿色圆圈实际上是它放大/缩小的地方.

The problem arises when I try to zoom in on the area circled in orange. In the below picture, I tried to zoom in on the orange circled area (not very much, just to show where the focal point is calculated to be). As you can see below, the red circle correctly calculates the new focal point, but for some reason the green circle is actually where it is zooming in/out around.

我正在使用以下代码将缩放的坐标与实际的imageview坐标映射

I am using the following code to map the zoomed coordinates with the actual imageview coordinates

public boolean onScale(ScaleGestureDetector detector) {
        //update the current scale
    scaleFactor *= detector.getScaleFactor();
    scaleFactor = Math.max(ZOOM_LEVEL_4, Math.min(scaleFactor, ZOOM_LEVEL_0));

    //applying the scaleFactor to the focal point as determined in onScaleBegin
    transformMatrix.setScale(scaleFactor, scaleFactor, 
                  newFocalPoints[0], newFocalPoints[1]);

    //apply the matrix to the child
    child.transform(transformMatrix, newFocalPoints[0],  newFocalPoints[1],
                oldFocalPoints[0], oldFocalPoints[1]);
    return true;
}

@Override
public boolean onScaleBegin(ScaleGestureDetector detector){
    //when a new scaling process begins, get the current imageMatrix and 
    //map the points to account for the current zoom level

    //the initial points. based on screen location and current scroll pos
    float startX = detector.getFocusX() + getScrollX();
    float startY = detector.getFocusY() + getScrollY();
    oldFocalPoints = new float[]{startX, startY};

    //map oldFocalPoints to coordinates of the imageView based on current zoom
    Matrix inverseTransformMatrix = new Matrix();

    if(transformMatrix.invert(inverseTransformMatrix))
        inverseTransformMatrix.mapPoints(newFocalPoints, oldFocalPoints);

    return true;
}

出于调试目的,上图中的绿点设置为{oldCoordinates[0], oldCoordinates[1]},尽管它并不是重点,但距离还很近.这样看来,尽管我似乎在正确地计算新的焦点(红色圆圈),但似乎并没有正确地应用它.谁能发现错误?预先感谢!

The green dot in the above pictures is set to be at {oldCoordinates[0], oldCoordinates[1]} for debug purposes, and while it isn't exactly the focal point, it is pretty darn close. So it seems that although I appear to be calculating the new focal point correctly (red circle), it doesn't seem to be applied correctly. Can anyone spot something wrong? Thanks in advance!

推荐答案

经过一番痛苦之后,我发现了解决方案.这是代码:

After much pain, I have discovered the solution. Here is the code:

@Override
public boolean onScale(ScaleGestureDetector detector) {

    scaleFactor *= detector.getScaleFactor();
    scaleFactor = Math.max(ZOOM_4, Math.min(scaleFactor, ZOOM_LEVEL_0));

    float xDiff = initialFocalPoints[0] - currentFocalPoints[0];
    float yDiff = initialFocalPoints[1] - currentFocalPoints[1];

    transformMatrix.setScale(scaleFactor, scaleFactor, 
                                 currentFocalPoints[0], currentFocalPoints[1]);
    transformMatrix.postTranslate(xDiff, yDiff);    
    child.setImageMatrix(transformMatrix);

    return true;
}

@Override
public boolean onScaleBegin(ScaleGestureDetector detector){

    float startX = detector.getFocusX() + getScrollX();
    float startY = detector.getFocusY() + getScrollY();

    initialFocalPoints = new float[]{startX, startY};

    if(transformMatrix.invert(inverseTransformMatrix))
    inverseTransformMatrix.mapPoints(currentFocalPoints, initialFocalPoints);
    return true;
}

与众不同的几行如下:

float xDiff = initialFocalPoints[0] - currentFocalPoints[0];
float yDiff = initialFocalPoints[1] - currentFocalPoints[1];
transformMatrix.postTranslate(xDiff, yDiff);

答案很简单,只需找出两点之间的差异,并在每次缩放图像时转换图像视图即可.

The answer was as simple as figuring out the difference between the two points and translating the imageview everytime the image is scaled.

这篇关于使用矩阵在焦点上缩放图像视图的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆