質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

0回答

687閲覧

Rect Native の Animated.Value で offsetの値を interpolate する方法はありますか?

benzo

総合スコア35

React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

0クリップ

投稿2019/09/08 18:14

編集2019/09/08 18:16

前提・実現したいこと

readt native の PanGestureHandler を使って Image を動かそうとしています。
Imageは無限に動かせるわけではなく範囲は決まっており、もしその範囲を超えて動かしていた場合、
アニメーションしながら範囲内までイメージを戻したいと思っています。

発生している問題・エラーメッセージ

scale などの Animated.Value ならば interpolate を使うといいんだろうなというのはわかるのですが、
Panの場合、

typescript

1var _translateX = this.currentX; 2var _translateY = this.currentY; 3 4_translateX.setOffset(this._lastX); 5_translateX.setValue(0); 6_translateY.setOffset(this._lastY); 7_translateY.setValue(0); 8 9this.currentX = _translateX; 10this.currentY = _translateY;

といったように Offset を指定する必要があり、この Offset を interpolate する方法がわかりません。

該当のソースコード

reactnative

1 2_handlePanGestureStateChange = (e: PanGestureHandlerGestureEvent) => { 3 this._lastX += e.nativeEvent.translationX; 4 this._lastY += e.nativeEvent.translationY; 5 6 // ここで生の入力値を作成 7 var lastX = this.currentX; 8 var lastY = this.currentY; 9 10 lastX.setOffset(this._lastX); 11 lastX.setValue(0); 12 lastY.setOffset(this._lastY); 13 lastY.setValue(0); 14 15 // 生の値 = lastX, lastY 16 17 // ここでcrop済みの値を作成 18 let minX = (this.state.width / 2 / this._lastScale - this.state.originalWidth / 2) * this._lastScale; 19 let maxX = (this.state.originalWidth - this.state.width / 2 / this._lastScale - this.state.originalWidth / 2) * this._lastScale; 20 let minY = (this.state.height / 2 / this._lastScale - this.state.originalHeight / 2) * this._lastScale; 21 let maxY = (this.state.originalHeight - this.state.height / 2 / this._lastScale - this.state.originalHeight / 2) * this._lastScale; 22 23 this._lastX = Math.max(Math.min(this._lastX, maxX), minX); 24 this._lastY = Math.max(Math.min(this._lastY, maxY), minY); 25 26 var cropedX = this.currentX; 27 var cropedY = this.currentY; 28 29 cropedX.setOffset(this._lastX); 30 cropedX.setValue(0); 31 cropedY.setOffset(this._lastY); 32 cropedY.setValue(0); 33 34 // crop済みの値 = cropedX, cropedY 35 36 this.currentX = // ここで lastX から cropedX にアニメーションさせたい  37 this.currentY = // ここで lastY から cropedY にアニメーションさせたい 38};

reactnative

1render() { 2 return ( 3 <View style={[this.props.style, {borderColor: 'red', borderWidth: 2}]}> 4 {/* imageを表示する部分 */} 5 <View style={{position: 'absolute', left: 0, top: 0, width: '100%', height: '100%', overflow: 'hidden'}}> 6 <Animated.View 7 style={{ 8 width: '100%', 9 height: '100%', 10 transform: [ 11 { translateX: this.currentX }, 12 { translateY: this.currentY } 13 ] 14 }} 15 > 16 <Animated.View 17 style={{ 18 width: '100%', 19 height: '100%', 20 transform: [ 21 { scale: this.state.scale } 22 ] 23 }} 24 > 25 {/* 拡縮の中心が画像の真ん中に来るようにすると計算が楽なのでコンポーネントが画面の真ん中に来るようにする */} 26 <Image 27 source={this.state.open == null ? { uri: '' } : { uri: this.state.open }} 28 style={{ 29 width: this.state.originalWidth, 30 height: this.state.originalHeight, 31 position: 'absolute', 32 top: -this.state.originalHeight / 2 + this.state.viewHeight / 2, 33 left: -this.state.originalWidth / 2 + this.state.width / 2, 34 }} 35 /> 36 </Animated.View> 37 </Animated.View> 38 </View> 39 {/* ジェスチャーのハンドリング */} 40 <View 41 onLayout={(e) => { 42 {/* Viewのサイズを取得しておく */} 43 let width = e.nativeEvent.layout.width; 44 let viewHeight = e.nativeEvent.layout.height; 45 let height = width * this.props.size[1] / this.props.size[0] 46 47 let scaleX = width / this.state.originalWidth; 48 let scaleY = height / this.state.originalHeight; 49 50 this.scaleMin = Math.max(scaleX, scaleY); 51 //this.scaleMin = scaleX; 52 53 this.setState({width: width, height: height, viewHeight: viewHeight}) 54 }} 55 style={{position: 'absolute', left: 0, top: 0, width: '100%', height: '100%', overflow: 'hidden', opacity: 0.5}} 56 > 57 <PanGestureHandler 58 ref={this.panRef} 59 waitFor={[this.pinchRef]} 60 onGestureEvent={Animated.event( 61 [{ nativeEvent: { translationX: this.currentX, translationY: this.currentY } }], 62 { useNativeDriver: true } 63 )} 64 onHandlerStateChange={this._handlePanGestureStateChange} 65 > 66 <Animated.View style={{ width: '100%', height: '100%', backgroundColor: 'blue' }}> 67 <PinchGestureHandler 68 ref={this.pinchRef} 69 onGestureEvent={Animated.event( 70 [{ nativeEvent: { scale: this.currentScale } }], 71 { useNativeDriver: true } 72 )} 73 onHandlerStateChange={this._handlePinchGestureStateChange} 74 > 75 <Animated.View style={{ width: '100%', height: '100%', backgroundColor: 'green', }}/> 76 </PinchGestureHandler> 77 </Animated.View> 78 </PanGestureHandler> 79 </View> 80 </View> 81 ); 82 }

試したこと

this.currentX = croped.interpolate({ inputRange: [0, 1], outputRange: [lastX, cropedX] });

としてみたけどうまくいきません。

どのようにすればoffsetの値をinterpolateすることができるでしょうか?

補足情報(FW/ツールのバージョンなど)

Expo使ってます。

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tgfjt

2019/12/05 10:19

タイトルの `Rect Native` を `React Native` に修正された方が検索しやすくて良いと思いますー!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問