使用PanResponder在React Native中考虑SVG viewBox

时间:2019-06-05 18:49:43

标签: react-native svg draggable viewbox

我正在尝试使SVG元素在内部可拖动,但是PanResponder无法解决SVG viewBox导致拖动的元素不跟随屏幕周围的触摸的问题。

我尝试利用触摸事件的X和Y值来影响SVG元素的X和Y值,但效果比使用PanResponder时差。当我切换为仅使用触摸事件的X和Y值时,我尝试使用在svgwg.org上找到的方程式将触摸事件X和Y转换为SVG坐标。

viewBox: "0 0 960.1 1856.51"

将X Y值转换为SVG坐标时使用的代码

svgXYConvert = (eX, eY) =>{
    let eW = this.props.width; 
    let eH = this.props.height;
    let [vbX, vbY, vbW, vbH] = this.props.viewBox.split(" ");

    // Calculate the scale of elements and vb
    let scaleX = eW/vbW;
    let scaleY = eH/vbH;

    // translation points
    let translateX = eX - (vbX * scaleX);
    let translateY = eY - (vbY * scaleY);
    return [translateX, translateY];
}

PanResponder组件

import React from 'react';
import {PanResponder, Animated} from 'react-native';
import {Image, G, Rect} from 'react-native-svg';

const AnimatedG = Animated.createAnimatedComponent(G);

class DragImg extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
          pan: new Animated.ValueXY({x: this.props.x, y: this.props.y}),
          x: this.props.x,
          y: this.props.y,
        }
      }
    componentWillMount() {
      this._panResponder = PanResponder.create({
            onPanResponderTerminationRequest: () => false,
            onStartShouldSetPanResponder: (e, gesture) => true,
            onPanResponderGrant: (e, gesture) => {
              this.state.pan.setOffset(this.state.pan.__getValue());
            },
            onPanResponderMove: Animated.event([
                null, { dx: this.state.pan.x, dy: this.state.pan.y}
              ])
            },
            onPanResponderRelease: (e) => {
              this.state.pan.flattenOffset();
            }
        })
    }
    render(){        
        let imgStyle = {transform: this.state.pan.getTranslateTransform()};
        return <AnimatedG style={imgStyle} {...this._panResponder.panHandlers} x={this.state.x} y={this.state.y}>
            <Image href={this.props.href} height={this.props.height} width={this.props.width} />
            <Rect fill="transparent" height={this.props.height} width={this.props.width}/>
          </AnimatedG>
    }
}
export default DragImg;

将其呈现在设备高度为100%的SVG内部时,我在iPad上施加横向压力,允许他们缩放正在使用的SVG,以便更清晰地查看细节。如果他们放大了SVG占据整个屏幕的位置,则元素将通过PanResponder以正确的速度移动并几乎完美地跟随触摸,但是如果将它们缩小或使用默认屏幕,我们将向他们显示整个SVG的可见位置。拖动的元素移动缓慢且跟踪效果不佳。

我不确定该如何使SVG元素正确跟踪,而不管它们是在SVG上放大还是缩小。

1 个答案:

答案 0 :(得分:0)

我做了一些类似的代码。我在Animated.View上添加了position: absolute,所以我将其移动,同时将SVG Circle移动到SVG区域内。为此,我将SVG大小缩放为具有maxWidth和minWidth的理想大小。此外,SVG必须具有以下属性:preserveAspectRatio="xMinYMin",因为它需要从(0,0)开始作为起点。

您可以看到它在这里工作:https://snack.expo.io/@albertcito/svg-pan-responder