d3 React Native中的缩放行为

时间:2017-10-26 12:59:20

标签: d3.js react-native

在React Native中,我用d3和ART库绘制我的图表。

export default class DevTest extends React.Component {

    static defaultProps = {
        width: 300,
        height: 150,
    }

    mainScaleX = d3Scale.scaleTime()
        .domain(d3Array.extent(chartDataTo, data => data.date))
        .range([0, this.props.width])

    mainScaleY = d3Scale.scaleLinear()
        .domain(d3Array.extent(chartDataTo, data => data.value))
        .range([this.props.height, 0])

    rawChartValue = d3Shape.line()
        .x(data => this.mainScaleX(data.date))
        .y(data => this.mainScaleY(data.value))

    render(){

        return (
            <View>
                <Surface width = {this.props.width} height = {this.props.height}>
                    <Group x = {0} y = {0}>
                        <Shape
                            d = {this.rawChartValue(chartData)}
                            stroke = "#000"
                            strokeWidth = {1}
                        />
                    </Group>
                </Surface>
            </View>
        )
    }
}

有没有办法实现类似d3 svg的缩放行为,但没有DOM变异。例如,使用一些只有x和y值的d3纯函数作为重新缩放mainScaleX和mainScaleY的输入?

1 个答案:

答案 0 :(得分:1)

您可以使用PanResponder中的react-nativezoomIdentity中的d3-zoom来实现此目的。

代码示例看起来像这样

componentWillMount() {
    this._panResponder = PanResponder.create({
        onMoveShouldSetPanResponder: (evt, gestureState) => true,
        onPanResponderMove: (event, { dx, dy }) => {
            const zoomIdentity = d3Zoom.zoomIdentity.translate(dx, dy)
            this._onDrag(zoomIdentity)
        },
    });
}

_onDrag(zoomIdentity){
    this.setState({
        rescaledX: zoomIdentity.rescaleX(this.state.mainScaleX),
        rescaledY: zoomIdentity.rescaleY(this.state.mainScaleY)
    })
}

然后将重新调整后的{X,Y}传递给图表组件

render(){
    return (
        <View {...this._panResponder.panHandlers}>
            <Component 
                {...this.props}
                scaleX = {this.state.rescaledX}
                scaleY = {this.state.rescaledY}
            />
        </View>
    )
}