2

かなりの量のズームに関する質問を読み、ここで座標を再計算したと言って始めましょう。しかし、私はそれらを自分の状況に適用できないようです。

ズームとスクロールができるカスタム ImageView クラスがあります。私が抱えている問題は、次のことをこの順序で行うことに起因しています。

  1. ポイントにズームインし、そのポイントを焦点として使用する(これは機能します)
  2. ズームインしたままスクロールする
  3. 別のポイントで拡大/縮小しようとしています (うまくいきません)

カスタム ビューの例を次に示します。赤と緑の 2 つの円があります。赤は焦点があるべき場所で、緑は焦点が実際の場所に近い場所です。 ここに画像の説明を入力

オレンジ色の円で囲まれた領域を拡大しようとすると、問題が発生します。下の写真では、オレンジ色の丸で囲まれた領域を拡大しようとしました (焦点がどこにあると計算されるかを示すためだけに、それほどではありません)。以下に示すように、赤い円は新しい焦点を正しく計算しますが、何らかの理由で緑の円は実際にズームイン/ズームアウトしている場所です。

ここに画像の説明を入力

次のコードを使用して、ズームされた座標を実際のイメージビュー座標にマップしています

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]}デバッグ用に設定されており、正確には焦点ではありませんが、かなり近い位置にあります。そのため、新しい焦点を正しく計算しているように見えますが (赤い円)、正しく適用されていないようです。誰でも何か間違ったことを見つけることができますか? 前もって感謝します!

4

1 に答える 1

4

多くの苦労の末、私は解決策を発見しました。コードは次のとおりです。

@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);

答えは、2 つの点の違いを見つけ出し、画像がスケーリングされるたびに画像ビューを変換するのと同じくらい簡単でした。

于 2013-09-03T21:58:39.087 に答える