javascript - D3 + React Native - X 位置更改时数据点值不更新

标签 javascript reactjs react-native d3.js svg

我正在尝试创建一个自定义折线图 this tutorialthis one以及。一切正常,但当我在图表上拖动手指时,我想显示当前位置的值(value)(iOS 上的股票应用程序或 Robinhood 应用程序)。起初,它显示一个值,但它是静态的并且不会更新。

LineChart.js

const d3 = {
  scale,
  shape,
}
const height = 300
const { width } = Dimensions.get('window')
const verticalPadding = 30

export default function LineChart({ data = exampleData }) {
  const minX = minBy(data, el => moment(el.label, 'LT'))
  const maxX = maxBy(data, el => moment(el.label, 'LT'))
  const minY = minBy(data, el => el.value)
  const maxY = maxBy(data, el => el.value)
  const scaleX = scaleTime()
    .domain([moment(minX.label, 'LT'), moment(maxX.label, 'LT')])
    .range([0, width])
  const scaleY = scaleLinear()
    .domain([minY.value, maxY.value])
    .range([height - verticalPadding, verticalPadding])
  const line = d3.shape
    .line()
    .x(d => scaleX(moment(d.label, 'LT')))
    .y(d => scaleY(d.value))
    .curve(d3.shape.curveBasis)(data)

  return (
    <View style={styles.container}>
      <Svg {...{ width, height }}>
        <Path d={line} fill="transparent" stroke={GREEN} strokeWidth="2" />
      </Svg>
      <View style={{ ...StyleSheet.absoluteFill, width }}>
        <Cursor d={line} scaleY={scaleY} scaleX={scaleX} data={data} />
      </View>
    </View>
  )
}

Cursor.js

const { Value } = Animated
const { width } = Dimensions.get('window')

export default ({ d, scaleY, scaleX, data }) => {
  const translationX = new Value(0)
  const path = parsePath(d)
  const length = interpolate(translationX, {
    inputRange: [0, width],
    outputRange: [0, path.totalLength],
  })
  const { x, y } = getPointAtLength(path, length)
  const translateX = x
  const cursorX = sub(x, 4)
  const cursorY = sub(y, 4)
  const text = scaleY.invert(cursorX.__getValue())
  const onGestureEvent = event([
    {
      nativeEvent: {
        x: translationX,
      },
    },
  ])

  return (
    <PanGestureHandler onGestureEvent={onGestureEvent}>
      <Animated.View>
        <Animated.View style={{ transform: [{ translateX }], ...styles.label }}>
          <Animated.Text style={{ color: 'white' }}>{text}</Animated.Text>
        </Animated.View>
        <Animated.View style={[styles.line, { transform: [{ translateX }] }]} />
        <Animated.View
          style={[
            styles.cursor,
            { transform: [{ translateX: cursorX, translateY: cursorY }] },
          ]}
        />
      </Animated.View>
    </PanGestureHandler>
  )
}

这是上面代码的结果:

current

编辑 这是小吃的链接:https://snack.expo.io/@clytras/intrigued-truffle

最佳答案

您已使用React Native Reanimated call 获得 translationX 的回调值更改,然后在其中您可以更新文本,它必须使用 setNativeProps<Text>以来组件没有 text原生 Prop ,你必须使用 <TextInput>就像 revolut-chart 中那样示例:

光标组件代码

// Changed imports
import React, { useEffect, useRef } from 'react';
import { Dimensions, TextInput } from 'react-native';
import Animated, { event, interpolate, sub, useCode, call } from 'react-native-reanimated';

...

export default function Cursor({ d, scaleY, scaleX, data }) {
  // Create a ref for the TextInput component
  const textRef = useRef();

  const translationX = new Value(0)
  const path = parsePath(d)
  const length = interpolate(translationX, {
    inputRange: [0, width],
    outputRange: [0, path.totalLength],
  })
  const { x, y } = getPointAtLength(path, length)
  const translateX = x
  const cursorX = sub(x, 4)
  const cursorY = sub(y, 4)
  // const text = scaleY.invert(cursorX.__getValue())
  const onGestureEvent = event([
    {
      nativeEvent: {
        x: translationX,
      },
    },
  ]);

  // Update text value using xValue = 0 when the component is mounted
  useEffect(() => {
    updateText(0);
  }, []);

  // Create reanimated code to get a translationX change callback
  useCode(() => {
    return call([translationX], (value) => {
      // On translationX value change update the text using the value
      updateText(value);
    })
  }, [translationX]);

  // Function to update the text based on current translationX value
  function updateText(xValue) {
    const { x, y } = getPointAtLength(path, xValue);
    const cursorX = sub(x, 4)
    const updated = scaleY.invert(cursorX.__getValue());

    // Use setNativeProps to update the TextInput component text prop
    textRef.current.setNativeProps({ text: `${updated.toFixed(5)}` })
  }

  return (
    <PanGestureHandler onGestureEvent={onGestureEvent}>
      <Animated.View>
        <Animated.View style={{ transform: [{ translateX }], ...styles.label }}>
          <TextInput ref={textRef} style={{ color: 'white' }}/>
        </Animated.View>
        <Animated.View style={[styles.line, { transform: [{ translateX }] }]} />
        <Animated.View
          style={[
            styles.cursor,
            { transform: [{ translateX: cursorX, translateY: cursorY }] },
          ]}
        />
      </Animated.View>
    </PanGestureHandler>
  )
}

屏幕截图示例

RN D3 chart

您可以在这里查看更新的世博小吃:https://snack.expo.io/@clytras/intrigued-truffle

关于javascript - D3 + React Native - X 位置更改时数据点值不更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61331754/

相关文章:

javascript - 如何从 JavaScript 对象中删除键和值

javascript - JS Web蓝牙API : Error startNotification() not supported

javascript - 如何使用 CodeIgniter 安装 React Js ..?

node.js - 将contentful导入到react-native中

facebook - returnKeyType "next"不起作用

javascript - Jquery 文本框的简单实时所见即所得编辑器

javascript - 下拉列表选择在 Internet Explorer 中无法正常工作

javascript - 获取 props in action -> reducer -> 自定义函数

node.js - 如何从我的 React Web 应用程序发送电子邮件

android - AVG 杀毒软件将我的 React Native Android 应用程序检测为恶意软件