2011-11-18 17 views
28

請參閱以下各節,以三種不同方式描述我的問題。希望應該幫助人們回答。如何在放大時查找點擊的絕對位置

問題:你怎麼找到一雙帆布/用戶空間座標表示,當你只有座標縮放圖像來表示,考慮到原有規模點&比例因子?

問題在實踐中:

我目前正試圖複製應用程序中使用的變焦功能,如畫廊/地圖,當你可以捏放大/變焦朝中點移動縮小捏。

向下保存縮放的中心點(基於當前屏幕在X,Y座標中)。然後,我有檢測到「規模」手勢時該功能動作:

class ImageScaleGestureDetector extends SimpleOnScaleGestureListener { 
    @Override 
    public boolean onScale(ScaleGestureDetector detector) { 
     if(mScaleAllowed) 
      mCustomImageView.scale(detector.getScaleFactor(), mCenterX, mCenterY); 
     return true; 
    } 
} 

的CustomImageView的比例函數是這樣的:

public boolean scale(float scaleFactor, float focusX, float focusY) { 
    mScaleFactor *= scaleFactor; 

    // Don't let the object get too small or too large. 
    mScaleFactor = Math.max(MINIMUM_SCALE_VALUE, Math.min(mScaleFactor, 5.0f)); 

    mCenterScaleX = focusX; 
    mCenterScaleY = focusY; 

    invalidate(); 

    return true; 
} 

縮放後的圖像的附圖由重寫來實現onDraw方法,用於在畫布中心縮放畫布並將其繪製到其中。

@Override 
public void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 

    canvas.save(); 
    canvas.translate(mCenterScaleX, mCenterScaleY); 
    canvas.scale(mScaleFactor, mScaleFactor); 
    canvas.translate(-mCenterScaleX, -mCenterScaleY); 
    mIcon.draw(canvas); 
    canvas.restore(); 
} 

這一切都從比例因子1縮放時工作得很好,這是因爲初始mCenterX和mCenterY是其基於在設備屏幕上的座標。 10,10在設備上是10,10在畫布上。

然而,在您已經放大之後,下次單擊位置10,10時,由於已經執行的縮放&轉換,它將不再對應於畫布中的10,10。

問題的抽象:

下面的圖像是圍繞中心點A.變焦操作的一個例子的每個框代表視圖的位置和大小時在該比例因子(1,2,3 ,4,5)。

Example

在這個例子中,如果你以2圍繞A然後一個因子你上位置B點擊縮放,所述X,Y報道爲B將基於屏幕上的位置 - 而不是在相對於位置初始畫布的0,0。

我需要找到讓B.

的絕對位置
+0

Android +設置樞軸點的標準視圖縮放比例不會完成這項工作嗎? –

+0

不確定「標準視圖縮放和樞軸點設置」是什麼意思?如果你可以擴展,這將是偉大的。 – Graeme

+1

我的意思是使用'setScaleX()'和'setScaleY(()'來縮放,'setPivotX()'和'setPivotY()'用於設置縮放的中心,它們都是View的方法,但是I只是讀了那些方法的minSdkVersion是11(蜂窩),所以如果你的目標是早期版本的話,這些信息對你來說可能是沒用的 –

回答

12

因此,重繪問題後,我找到了我正在尋找的解決方案。它通過幾個迭代的走了,但在這裏就是我的工作了:

Solution Description

乙 - 點,規模化經營

A1,A2,A3的中心 - 點,等於在用戶空間,但在畫布空間不同。

你知道BxBy值,因爲他們總是不斷無論什麼比例因子(你知道,在兩個帆布空間和用戶空間這個數值)。

您在用戶空間知道Ax & Ay這樣你就可以找到By之間AxBxAy的距離。這種測量是在用戶空間中,將其轉換爲畫布空間測量值,然後將其除以縮放因子。 (一旦轉換爲畫布空間,您可以看到紅色,橙色和黃色的這些線條)。

由於點B是恆定的,它與邊緣之間的距離是恆定的(這些由藍線表示)。該值在用戶空間和畫布空間中相等。

你從你留下了在畫布空間A點的座標總寬度減去這兩個帆布空間測量(AxBxBxEdge)知道畫布在畫布空間的寬度,使:

public float[] getAbsolutePosition(float Ax, float Ay) { 

    float fromAxToBxInCanvasSpace = (mCenterScaleX - Ax)/mScaleFactor; 
    float fromBxToCanvasEdge = mCanvasWidth - Bx; 
    float x = mCanvasWidth - fromAxToBxInCanvasSpace - fromBxToCanvasEdge; 

    float fromAyToByInCanvasSpace = (mCenterScaleY - Ay)/mScaleFactor; 
    float fromByToCanvasEdge = mCanvasHeight - By; 
    float y = mCanvasHeight - fromAyToByInCanvasSpace - fromByToCanvasEdge; 

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

上面的代碼和圖片描述了當您點擊原始中心的左上方時。我用同樣的邏輯,找出A無論哪個象限它位於和重構爲以下幾點:

public float[] getAbsolutePosition(float Ax, float Ay) { 

    float x = getAbsolutePosition(mBx, Ax); 
    float y = getAbsolutePosition(mBy, Ay); 

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

private float getAbsolutePosition(float oldCenter, float newCenter, float mScaleFactor) { 
    if(newCenter > oldCenter) { 
     return oldCenter + ((newCenter - oldCenter)/mScaleFactor); 
    } else { 
     return oldCenter - ((oldCenter - newCenter)/mScaleFactor); 
    } 
} 
+0

嘿格雷姆我面臨類似的問題?這是我的頭從最近1個月的最後我發現了一個問題我需要你的幫助來破解解決方案嗎?我理解你的上述邏輯有點但需要你的幫助...我應該在哪裏與你聯繫?在此先感謝 – user1169079

+0

我是其中一個Android'聊天室 - 我會在那裏 – Graeme

+0

但是在聊天中只有用戶提名的用戶可以聊天嗎?請確實接受請求..謝謝 – user1169079

1

實在不好意思,這是一個簡短的回答,在匆忙的方式。但我最近也在看這個 - 我發現http://code.google.com/p/android-multitouch-controller/做你想做的事(我想 - 我不得不閱讀你的文章)。希望這可以幫助。如果這沒有幫助,我今晚有一個適當的看看,看看我能否進一步幫助。

+0

不得不原諒我,因爲在這一點上我非常疲倦,但在這個傢伙的源代碼中,他使用了一個名爲「MultiTouchObjectCanvas 「在這個界面裏面我這是一種名爲「getPositionAndScale」的方法,描述爲「獲取拖動對象原點的屏幕座標,以及將屏幕座標轉換爲對象座標的縮放倍數。「這正是我想要的 - 不幸的是我看不到這個接口在哪裏實現...... – Graeme

+0

看看他的演示 - http://code.google.com/p/android-multitouch-controller/source /browse/trunk/demo/MTPhotoSortr/src/org/metalev/multitouch/photosortr/PhotoSortrView.java – Martyn

2

這裏是基於格雷姆的回答我的解決方案:

public float[] getAbsolutePosition(float Ax, float Ay) { 
    MatrixContext.drawMatrix.getValues(mMatrixValues); 

    float x = mWidth - ((mMatrixValues[Matrix.MTRANS_X] - Ax)/mMatrixValues[Matrix.MSCALE_X]) 
      - (mWidth - getTranslationX()); 

    float y = mHeight - ((mMatrixValues[Matrix.MTRANS_Y] - Ay)/mMatrixValues[Matrix.MSCALE_X]) 
      - (mHeight - getTranslationY()); 

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

參數Ax和Ay是用戶通過onTouch()觸摸的點,我在MatrixContext類中擁有我的靜態矩陣實例以保存先前的縮放/轉換值。

相關問題