寫一個圖片預覽器(react-native),溫習一下初中數學

statistics

source download download/month
npmjs.com npm npm
npm.taobao.org npm.taobao
cnpmjs.org cnpm

需求很簡單:

  1. 能夠放大任意一處我想放大的地方
  2. 能夠移動,查看任意圖片細節
  3. 支持網絡圖片和本地圖片

技術實現

1、加載圖片和獲取圖片尺寸

2、設置尺寸、放大到恰好滿屏、居中

  1. react-native圖片transform的縮放的中心點在圖片的中心,所以,把圖片先發居中就好
  2. 比較圖片的長寬比和屏幕的寬高比,若是是圖片比較寬那麼就橫向滿屏,若是比較高就縱向滿屏,以下圖:
/*
    * center and zoom to fit the window
    * @ _width: the picture width
    * @ _height: the picture height
    * */
    center(_width, _height){
        let {width, height} = Dimensions.get('window'),
            rateImage = _width/_height,
            rateWindow = width/height,
            top,
            left,
            scale
        if (rateImage > rateWindow) {
            scale = width/_width
        } else {
            scale = height/_height
        }
        top = (height - _height)/2
        left = (width - _width)/2
        this.setState({
            left,
            top,
            width:_width,
            height: _height,
            scale,
            rate: scale
        })
    }

3、準備移動和縮放動做

1.設置兩個變量來記錄(上一次手指的和縮放的)狀態javascript

this._touches = [
            {},
            {}
        ]
        this._zoom = undefined

2.每次動做結束以後清除狀態java

onPanResponderRelease: (evt, gestureState) => {
                // reset
                this._touches = [
                    {},
                    {}
                ]
                this._zoom = undefined
            }

3.每次開始觸摸的時候的時候記錄狀態react

// touche start
onPanResponderGrant:(evt, gestureState) => {
    // mark touches info
    for (let x in this._touches) {
    if (evt.nativeEvent.touches[x]) {
        this._touches[x].x = evt.nativeEvent.touches[x].pageX
        this._touches[x].y = evt.nativeEvent.touches[x].pageY
        this._touches[x].identifier = evt.nativeEvent.touches[x].identifier
        }
    }
},

4.每次移動的時候,若是沒有記錄狀態就記錄狀態,若是有記錄就開始作動做啦↓↓↓git

4、移動圖片

1.這個很簡單,只要圖片跟着手指動就能夠了,由於縮放變換的中心是圖片的中心,因此只須要簡單的改變left 和 top 就能夠了,??github

// compute the distance has touch moved
let moveX = evt.nativeEvent.touches[0].pageX - this._touches[0].x
let moveY = evt.nativeEvent.touches[0].pageY - this._touches[0].y
// set the state
this.state.left += moveX
this.state.top += moveY
this.setState({
    left: this.state.left,
    top: this.state.top
})

5、 放大圖片

一個宗旨:圖片跟着手指動。什麼意思呢?看圖吧!npm

合理的解釋:縮放操做時,上面的始終觸點在圓圓的眼睛上面(對不起圓圓了),下面的觸點始終在中指戒指上一點點。react-native

一、縮放比例計算(以上圖爲例)

// 縮放前,戒指到眼睛的距離爲 d,這個是圖片的真實距離
// 屏幕上,戒指到眼睛的距離爲D
// 縮放比例爲 S,屏幕的尺寸/圖片的尺寸
// 所以有個等式
d * S = D
// 那麼,在新的位置
dn * Sn = Dn
// 在圖片中,dn是相等的
// 所以,解個方程能夠獲得
Sn = Dn/D * S
// Dn 和 D 分別能夠有 新的觸點的座標 和 舊的 觸點的座標 表示,S已知
// 這樣咱們就獲得了 新的縮放比例 和 觸點座標的關係了

二、圖片位置的計算 (已上圖爲例)

剛剛已經說到,RN變換的中心點是圖片的中心,那麼,我要放大一個角落的位置,如何讓圖片看起來是以這個角落爲縮放中心呢?改變left 和 top 就能夠了。網絡

// 以left爲例,top同理可得
// 上圖中,兩個觸點的連線的中點位置大約是圓圓的第二顆牙齒(下面稱爲牙齒)
// 設牙齒的X座標爲 X (屏幕的座標)
// 牙齒在圖片中距離圖片中線的距離爲 d
// 圖片的實際寬度爲w
// 圖片的位置爲l(事實上爲放大前的左邊距)
// 縮放比例爲 S,屏幕的尺寸/圖片的尺寸
// 圖片的縮放中心是圖片的中心,所以有一個等式:
X = (0.5 * w + l) - d * S
// 那麼對於新的位置也有同樣的等式
Xn = (0.5 * wn + ln) - dn * Sn
// 事實上就,X的位置不變,d的位置不變,w也不會變,那麼就有等式了
(0.5 * w + l) - d * S = (0.5 * w + ln) - d * Sn
// 由這裏就能夠解出ln 和 l , S ,Sn的關係了。
// l,S已知,Sn上面已經算出來了

結語

到此整個思路已經出來了,代碼看github。
不過這也是爲了知足本身的開發需求,沒有開放不少可定製的內容。
最後爲了裝個X(學英語??),寫英文的READMEide

相關文章
相關標籤/搜索