Review——RN視圖縮放框架react-native-view-transformer解析


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM