react-native-view-transformer解析
一、組成
結構:
->library ->transform ->Rect.js ->TransformUtils.js ->ViewTransformer.js ->index.js ->.npmignore ->package.json ->README.md
依賴:
"dependencies": { "react-native-gesture-responder": "0.1.1", "react-native-scroller": "0.0.6" }
react-native-view-transformer(后文簡稱‘vt’),是基於RN手勢系統和滑輪做的一個視圖封裝組件。含有放大縮小、雙擊和拖動控制功能。
二、功能解析
vt主要是由transform下的三個文件創造而成。其中,Rect負責構造基本矩形;TransformUtils控制矩形轉換的樣式;ViewTransformer控制矩形轉換的屬性。
控制縮放比例:ViewTransformer.js->animateBounce()
animateBounce() { let curScale = this.state.scale; //最小最大縮放倍數 let minScale = 0.2; let maxScale = this.props.maxScale; let scaleBy = 1; if (curScale > maxScale) { scaleBy = maxScale / curScale; } else if (curScale < minScale) { scaleBy = minScale / curScale; } let rect = transformedRect(this.transformedContentRect(), new Transform( scaleBy, 0, 0, { x: 0, y: 0 } )); rect = alignedRect(rect, this.viewPortRect(), scaleBy); this.animate(rect); }
控制界面移動速度:ViewTransformer.js->applyResistance()
applyResistance(dx, dy) { let availablePanDistance = availableTranslateSpace(this.transformedContentRect(), this.viewPortRect()); if ((dx > 0 && availablePanDistance.left < 0) || (dx < 0 && availablePanDistance.right < 0)) { //手勢橫向移動距離 dx /= 1; } if ((dy > 0 && availablePanDistance.top < 0) || (dy < 0 && availablePanDistance.bottom < 0)) { //手勢縱向移動距離 dy /= 1; } return { dx, dy } }
控制雙擊放大倍數:ViewTransformer.js->performDoubleTapUp()
performDoubleTapUp(pivotX, pivotY) { console.log('performDoubleTapUp...pivot=' + pivotX + ', ' + pivotY); let curScale = this.state.scale; //控制每次雙擊放大的倍數 let scaleBy = 1; let rect = transformedRect(this.transformedContentRect(), new Transform( scaleBy, 0, 0, { x: pivotX, y: pivotY } )); rect = transformedRect(rect, new Transform(1, this.viewPortRect().centerX() - pivotX, this.viewPortRect().centerY() - pivotY)); rect = alignedRect(rect, this.viewPortRect()); this.animate(rect); }
控制界面邊界限制:ViewTransformer.js->animateBounce() -> TransformUtils.js-> alignedRect()
export function alignedRect(rect:Rect, viewPortRect:Rect, scaleBy) { let dx = 0, dy = 0; //控制左右邊界 if (rect.left > viewPortRect.left) { dx = viewPortRect.left - rect.left; } else if (Math.abs(rect.right) > (2000*scaleBy - 720)) { dx = 2000*scaleBy; } //控制上下邊界 if (rect.top > viewPortRect.top) { dy = viewPortRect.top - rect.top; } else if (Math.abs(rect.bottom) > 1000) { dy = 340; } return rect.copy().offset(dx, dy); }
控制界面展示中心:TransformUtils.js-> fitCenterRect()
export function fitCenterRect(contentAspectRatio, containerRect:Rect) { let w = containerRect.width(); let h = containerRect.height(); let viewAspectRatio = w / h; if (contentAspectRatio > viewAspectRatio) { h = w / contentAspectRatio; } else { w = h * contentAspectRatio; } //控制新界面的布局中心點 return new Rect( containerRect.centerX() - w / 2, containerRect.centerY() - h / 2, containerRect.centerX() + w / 2, containerRect.centerY() + h / 2 ); }