teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

4

質問内容を書き直しました

2018/05/15 05:55

投稿

yamady
yamady

スコア176

title CHANGED
@@ -1,1 +1,1 @@
1
- Fetchしたデータを使ってstateのデータを変更したい(react native)
1
+ AnimatedViewをfetchしたViewで表示したい(react native)
body CHANGED
@@ -1,20 +1,76 @@
1
- 何度も申し訳ありませ
1
+ 質問の内容に不備がありましたので、再度こちらにて訂正さて載せさせていただきます
2
+ React Native Mapというライブラリで、Animated Viewを表示できるようにしたいと考えています。
2
3
 
3
- React Native Mapsの[Animated View](https://github.com/react-community/react-native-maps/blob/master/example/examples/AnimatedViews.js)をデータベースからFetchしたデータを入れ込んで、表示を実現しようとています。
4
+ [こちらのリンク先にあるAnimatedView.js](https://github.com/react-community/react-native-maps/blob/master/example/examples/AnimatedViews.js)をコピペするとちゃんと表示されるのですが、自前のデータベースからFetchしてきたデータを当てようとすると下記のエラーが生じしまいます。
4
- しかし、下記のエラーが生じてしまい表示できずじまいです。。
5
5
 
6
6
  ```
7
- TypeError: Cannot read property 'selected' of undefined
7
+ Invariant Violation: outputRange must have at least 2 elements
8
8
  ```
9
+ ※[こちらのエラーをぐぐってみた](https://github.com/react-community/react-native-maps/issues/746)のですが、未解決のようです。。。
9
10
 
10
- ### ソースコード
11
+ 変更点は下記の部分です。
11
12
 
12
- > AnimatedView.js
13
+ > Fetchするためのredux追加
13
14
 
15
+ ```JavaScript
16
+ ・・・
17
+ const mapStateToProps = (state) => {
18
+ const markers = _.orderBy(state.markers, ['id'], ['desc']);
19
+
20
+ return { markers };
21
+ };
22
+
23
+ export default connect(mapStateToProps, {
24
+ markersFetch
25
+ })(AnimatedViews);
14
26
  ```
27
+
15
- function getMarkerState(panX, panY, scrollY, i) {
28
+ > this.stateで出していたmarkersをthis.propsで書き換え
29
+
30
+ ```JavaScript
31
+ const {
32
+     ・・・
33
+ markers
34
+ } = this.state;
35
+ ```
36
+
37
+ 上記の部分を下記のように書き換えました。
38
+
39
+ ```JavaScript
40
+ const { markers } = this.props;
41
+ ```
42
+
43
+ どのようにして解決すればよろしいでしょうか・・・。
44
+ お手数ですが、おたすけくださいませ。
45
+
46
+
47
+ ▼ソースコードはこちらです
48
+ ```JavaScript
16
49
  ・・・
17
50
 
51
+ function getMarkerState(panX, panY, scrollY, i) {
52
+ const xLeft = (-SNAP_WIDTH * i) + (SNAP_WIDTH / 2);
53
+ const xRight = (-SNAP_WIDTH * i) - (SNAP_WIDTH / 2);
54
+ const xPos = -SNAP_WIDTH * i;
55
+
56
+ const isIndex = panX.interpolate({
57
+ inputRange: [xRight - 1, xRight, xLeft, xLeft + 1],
58
+ outputRange: [0, 1, 1, 0],
59
+ extrapolate: 'clamp',
60
+ });
61
+
62
+ const isNotIndex = panX.interpolate({
63
+ inputRange: [xRight - 1, xRight, xLeft, xLeft + 1],
64
+ outputRange: [1, 0, 0, 1],
65
+ extrapolate: 'clamp',
66
+ });
67
+
68
+ const center = panX.interpolate({
69
+ inputRange: [xPos - 10, xPos, xPos + 10],
70
+ outputRange: [0, 1, 0],
71
+ extrapolate: 'clamp',
72
+ });
73
+
18
74
  const selected = panX.interpolate({
19
75
  inputRange: [xRight, xPos, xLeft],
20
76
  outputRange: [0, 1, 0],
@@ -25,8 +81,53 @@
25
81
 
26
82
  const translateX = panX;
27
83
 
84
+ const anim = Animated.multiply(isIndex, scrollY.interpolate({
85
+ inputRange: [0, BREAKPOINT1],
86
+ outputRange: [0, 1],
87
+ extrapolate: 'clamp',
28
- ・・・
88
+ }));
29
89
 
90
+ const scale = Animated.add(ONE, Animated.multiply(isIndex, scrollY.interpolate({
91
+ inputRange: [BREAKPOINT1, BREAKPOINT2],
92
+ outputRange: [0, SCALE_END - 1],
93
+ extrapolate: 'clamp',
94
+ })));
95
+
96
+ // [0 => 1]
97
+ let opacity = scrollY.interpolate({
98
+ inputRange: [BREAKPOINT1, BREAKPOINT2],
99
+ outputRange: [0, 1],
100
+ extrapolate: 'clamp',
101
+ });
102
+
103
+ // if i === index: [0 => 0]
104
+ // if i !== index: [0 => 1]
105
+ opacity = Animated.multiply(isNotIndex, opacity);
106
+
107
+
108
+ // if i === index: [1 => 1]
109
+ // if i !== index: [1 => 0]
110
+ opacity = opacity.interpolate({
111
+ inputRange: [0, 1],
112
+ outputRange: [1, 0],
113
+ });
114
+
115
+ let markerOpacity = scrollY.interpolate({
116
+ inputRange: [0, BREAKPOINT1],
117
+ outputRange: [0, 1],
118
+ extrapolate: 'clamp',
119
+ });
120
+
121
+ markerOpacity = Animated.multiply(isNotIndex, markerOpacity).interpolate({
122
+ inputRange: [0, 1],
123
+ outputRange: [1, 0],
124
+ });
125
+
126
+ const markerScale = selected.interpolate({
127
+ inputRange: [0, 1],
128
+ outputRange: [1, 1.2],
129
+ });
130
+
30
131
  return {
31
132
  translateY,
32
133
  translateX,
@@ -46,22 +147,72 @@
46
147
 
47
148
  const { markers } = this.props;
48
149
 
150
+ const panX = new Animated.Value(0);
151
+ const panY = new Animated.Value(0);
152
+
153
+ const scrollY = panY.interpolate({
154
+ inputRange: [-1, 1],
155
+ outputRange: [1, -1],
156
+ });
157
+
158
+ const scrollX = panX.interpolate({
159
+ inputRange: [-1, 1],
160
+ outputRange: [1, -1],
161
+ });
162
+
163
+ const scale = scrollY.interpolate({
164
+ inputRange: [0, BREAKPOINT1],
165
+ outputRange: [1, 1.6],
166
+ extrapolate: 'clamp',
167
+ });
168
+
169
+ const translateY = scrollY.interpolate({
170
+ inputRange: [0, BREAKPOINT1],
171
+ outputRange: [0, -100],
172
+ extrapolate: 'clamp',
173
+ });
174
+
49
175
  const animations = markers.map((m, i) =>
50
176
  getMarkerState(panX, panY, scrollY, i));
51
- ・・・
52
177
 
178
+ this.state = {
179
+ panX,
180
+ panY,
181
+ animations,
182
+ index: 0,
53
- componentWillMount() {
183
+ canMoveHorizontal: true,
184
+ scrollY,
185
+ scrollX,
186
+ scale,
187
+ translateY,
54
- this.props.markersFetch();
188
+ region: new AnimatedRegion({
189
+ latitude: LATITUDE,
190
+ longitude: LONGITUDE,
191
+ latitudeDelta: LATITUDE_DELTA,
192
+ longitudeDelta: LONGITUDE_DELTA,
193
+ }),
194
+ };
55
195
  }
56
196
 
57
197
  componentDidMount() {
198
+ const { region, panX, panY, scrollX } = this.state;
58
199
  const { markers } = this.props;
59
- const { region, panX, panY, scrollX } = this.state;
60
200
 
61
201
  panX.addListener(this.onPanXChange);
62
202
  panY.addListener(this.onPanYChange);
63
203
 
204
+ region.stopAnimation();
205
+ region.timing({
206
+ latitude: scrollX.interpolate({
207
+ inputRange: markers.map((m, i) => i * SNAP_WIDTH),
208
+ outputRange: markers.map(m => m.coordinate.latitude),
64
- ・・・
209
+ }),
210
+ longitude: scrollX.interpolate({
211
+ inputRange: markers.map((m, i) => i * SNAP_WIDTH),
212
+ outputRange: markers.map(m => m.coordinate.longitude),
213
+ }),
214
+ duration: 0,
215
+ }).start();
65
216
  }
66
217
 
67
218
  onStartShouldSetPanResponder = (e) => {
@@ -94,58 +245,16 @@
94
245
  }
95
246
 
96
247
  onPanYChange = ({ value }) => {
248
+ const { canMoveHorizontal, region, scrollY, scrollX, index } = this.state;
97
249
  const { markers } = this.props;
98
- const { canMoveHorizontal, region, scrollY, scrollX, index } = this.state;
99
- const shouldBeMovable = Math.abs(value) < 2;
100
- if (shouldBeMovable !== canMoveHorizontal) {
101
- this.setState({ canMoveHorizontal: shouldBeMovable });
102
- if (!shouldBeMovable) {
103
- const { coordinate } = markers[index];
104
- region.stopAnimation();
105
- region.timing({
106
- latitude: scrollY.interpolate({
107
- inputRange: [0, BREAKPOINT1],
108
- outputRange: [
109
- coordinate.latitude,
110
- coordinate.latitude - (LATITUDE_DELTA * 0.5 * 0.375),
111
- ],
112
- extrapolate: 'clamp',
113
- }),
114
- latitudeDelta: scrollY.interpolate({
115
- inputRange: [0, BREAKPOINT1],
116
- outputRange: [LATITUDE_DELTA, LATITUDE_DELTA * 0.5],
117
- extrapolate: 'clamp',
118
- }),
119
- longitudeDelta: scrollY.interpolate({
120
- inputRange: [0, BREAKPOINT1],
121
- outputRange: [LONGITUDE_DELTA, LONGITUDE_DELTA * 0.5],
122
- extrapolate: 'clamp',
123
- }),
124
- duration: 0,
125
- }).start();
126
- } else {
127
- region.stopAnimation();
128
- region.timing({
129
- latitude: scrollX.interpolate({
130
- inputRange: markers.map((m, i) => i * SNAP_WIDTH),
131
- outputRange: markers.map(m => m.coordinate.latitude),
132
- }),
133
- longitude: scrollX.interpolate({
134
- inputRange: markers.map((m, i) => i * SNAP_WIDTH),
135
- outputRange: markers.map(m => m.coordinate.longitude),
136
- }),
137
- duration: 0,
138
- }).start();
139
- }
140
- }
141
- }
142
250
 
251
+ ・・・
252
+
143
253
  onRegionChange(/* region */) {
144
254
  // this.state.region.setValue(region);
145
255
  }
146
256
 
147
257
  render() {
148
- const { markers } = this.props;
149
258
  const {
150
259
  panX,
151
260
  panY,
@@ -153,19 +262,27 @@
153
262
  canMoveHorizontal,
154
263
  region,
155
264
  } = this.state;
265
+ const { markers } = this.props;
156
266
 
267
+ return (
157
- console.log('this.props', this.props);
268
+ <View style={styles.container}>
269
+ <PanController
270
+ style={styles.container}
271
+ vertical
272
+ horizontal={canMoveHorizontal}
273
+ xMode="snap"
274
+ snapSpacingX={SNAP_WIDTH}
275
+ yBounds={[-1 * screen.height, 0]}
158
- console.log('this.state', this.state);
276
+ xBounds={[-screen.width * (markers.length - 1), 0]}
159
-
277
+ panY={panY}
278
+ panX={panX}
279
+ onStartShouldSetPanResponder={this.onStartShouldSetPanResponder}
280
+ onMoveShouldSetPanResponder={this.onMoveShouldSetPanResponder}
281
+ >
160
282
  <AnimatedMap
161
283
  provider={this.props.provider}
162
284
  style={styles.map}
163
- region={{
285
+ region={region}
164
- latitude: 35.6797392,
165
- longitude: 139.7348855,
166
- latitudeDelta: 0.0922,
167
- longitudeDelta: 0.0421,
168
- }}
169
286
  onRegionChange={this.onRegionChange}
170
287
  >
171
288
  {markers.map((marker, i) => {
@@ -194,83 +311,49 @@
194
311
  );
195
312
  })}
196
313
  </AnimatedMap>
314
+ <View style={styles.itemContainer}>
315
+ {markers.map((marker, i) => {
316
+ const {
317
+ translateY,
318
+ translateX,
319
+ scale,
320
+ opacity,
321
+ } = animations[i];
197
322
 
198
- ・・・
199
- ```
200
-
201
- 下記のコンポーネントを引っ張ってきています。
202
-
203
- > AnimatedPlaceView.js
204
-
205
- ```
206
- import React from 'react';
207
- import PropTypes from 'prop-types';
208
-
209
- import {
210
- StyleSheet,
211
- Text,
212
- Animated,
213
- } from 'react-native';
214
-
215
- class AnimatedPriceMarker extends React.Component {
216
- render() {
217
- const { amount, selected, style } = this.props;
218
-
219
- const background = selected.interpolate({
220
- inputRange: [0, 1],
221
- outputRange: ['#005E7F', '#00A0D8'],
222
- });
223
-
224
- const border = selected.interpolate({
225
- inputRange: [0, 1],
226
- outputRange: ['#005E7F', '#00A0D8'],
227
- });
228
-
229
- return (
323
+ return (
230
- <Animated.View style={[styles.container, style]}>
231
- <Animated.View
324
+ <Animated.View
325
+ key={marker.id}
326
+ style={[styles.item, {
327
+ opacity,
328
+ transform: [
329
+ { translateY },
330
+ { translateX },
232
- style={[
331
+ { scale },
233
- styles.bubble,
234
- {
235
- backgroundColor: background,
236
- borderColor: border,
237
- },
332
+ ],
238
- ]}
333
+ }]}
239
- >
240
- <Text style={styles.dollar}>$</Text>
241
- <Text style={styles.amount}>{amount}</Text>
242
- </Animated.View>
243
- <Animated.View
244
- style={[styles.arrowBorder, { borderTopColor: border }]}
245
- />
334
+ />
246
- <Animated.View
247
- style={[styles.arrow, { borderTopColor: background }]}
248
- />
335
+ );
336
+ })}
249
- </Animated.View>
337
+ </View>
338
+ </PanController>
339
+ </View>
250
340
  );
251
341
  }
252
342
  }
253
- ```
254
343
 
344
+ AnimatedViews.propTypes = {
255
- ### コンソール結果
345
+ provider: ProviderPropType,
346
+ };
256
347
 
257
- > this.props
348
+ ...
258
349
 
259
- ```
350
+ const mapStateToProps = (state) => {
260
- {screenProps: undefined, markers: Array(2), markersFetch: ƒ}
351
+ const markers = _.orderBy(state.markers, ['id'], ['desc']);
261
- markers:Array(2)
262
- 0:
263
- amount:"30"
264
- coordinate:{longitude: -122.406417, latitude: 37.785834}
265
- id:"1"
266
- name:"Test2"
267
- __proto__:Object1
268
352
 
353
+ return { markers };
269
- ・・・
354
+ };
270
- ```
271
355
 
356
+ export default connect(mapStateToProps, {
272
- > this.state
357
+ markersFetch
273
-
274
- ![state結果](a6ba214d4d823ce4079109d3bd0aa828.png)
358
+ })(AnimatedViews);
275
-
276
- stateが何も取れていないところから、propsで取得したmarkersがきちんとstateの方にはまっていないのではないかと思うのですが。。すみませんが、お手すきの際にどうぞおたすけください。
359
+ ```

3

const animationsを追記しました。

2018/05/15 05:55

投稿

yamady
yamady

スコア176

title CHANGED
File without changes
body CHANGED
@@ -46,6 +46,8 @@
46
46
 
47
47
  const { markers } = this.props;
48
48
 
49
+ const animations = markers.map((m, i) =>
50
+ getMarkerState(panX, panY, scrollY, i));
49
51
  ・・・
50
52
 
51
53
  componentWillMount() {

2

AnimatedPlaceView.jsを追記しました

2018/05/14 17:58

投稿

yamady
yamady

スコア176

title CHANGED
File without changes
body CHANGED
@@ -196,6 +196,60 @@
196
196
  ・・・
197
197
  ```
198
198
 
199
+ 下記のコンポーネントを引っ張ってきています。
200
+
201
+ > AnimatedPlaceView.js
202
+
203
+ ```
204
+ import React from 'react';
205
+ import PropTypes from 'prop-types';
206
+
207
+ import {
208
+ StyleSheet,
209
+ Text,
210
+ Animated,
211
+ } from 'react-native';
212
+
213
+ class AnimatedPriceMarker extends React.Component {
214
+ render() {
215
+ const { amount, selected, style } = this.props;
216
+
217
+ const background = selected.interpolate({
218
+ inputRange: [0, 1],
219
+ outputRange: ['#005E7F', '#00A0D8'],
220
+ });
221
+
222
+ const border = selected.interpolate({
223
+ inputRange: [0, 1],
224
+ outputRange: ['#005E7F', '#00A0D8'],
225
+ });
226
+
227
+ return (
228
+ <Animated.View style={[styles.container, style]}>
229
+ <Animated.View
230
+ style={[
231
+ styles.bubble,
232
+ {
233
+ backgroundColor: background,
234
+ borderColor: border,
235
+ },
236
+ ]}
237
+ >
238
+ <Text style={styles.dollar}>$</Text>
239
+ <Text style={styles.amount}>{amount}</Text>
240
+ </Animated.View>
241
+ <Animated.View
242
+ style={[styles.arrowBorder, { borderTopColor: border }]}
243
+ />
244
+ <Animated.View
245
+ style={[styles.arrow, { borderTopColor: background }]}
246
+ />
247
+ </Animated.View>
248
+ );
249
+ }
250
+ }
251
+ ```
252
+
199
253
  ### コンソール結果
200
254
 
201
255
  > this.props

1

selectedのview部分を追記しました

2018/05/14 06:59

投稿

yamady
yamady

スコア176

title CHANGED
File without changes
body CHANGED
@@ -155,6 +155,44 @@
155
155
  console.log('this.props', this.props);
156
156
  console.log('this.state', this.state);
157
157
 
158
+ <AnimatedMap
159
+ provider={this.props.provider}
160
+ style={styles.map}
161
+ region={{
162
+ latitude: 35.6797392,
163
+ longitude: 139.7348855,
164
+ latitudeDelta: 0.0922,
165
+ longitudeDelta: 0.0421,
166
+ }}
167
+ onRegionChange={this.onRegionChange}
168
+ >
169
+ {markers.map((marker, i) => {
170
+ const {
171
+ selected,
172
+ markerOpacity,
173
+ markerScale,
174
+ } = animations[i];
175
+
176
+ return (
177
+ <Marker
178
+ key={marker.id}
179
+ coordinate={marker.coordinate}
180
+ >
181
+ <PriceMarker
182
+ style={{
183
+ opacity: markerOpacity,
184
+ transform: [
185
+ { scale: markerScale },
186
+ ],
187
+ }}
188
+ amount={marker.amount}
189
+ selected={selected}
190
+ />
191
+ </Marker>
192
+ );
193
+ })}
194
+ </AnimatedMap>
195
+
158
196
  ・・・
159
197
  ```
160
198