Создать дыру в реагирующем веб-представлении для сенсорных событий

Мы пытаемся повторить то же самое, что было сделано с этим плагином: https://github.com/mapsplugin/cordova-plugin-googlemaps/blob/master/README.md (как работает этот плагин), но с использованием response-native + mapbox gl(родной).

Идея проста: веб-просмотр и просмотр карты - это "братья и сестры", веб-просмотр находится над просмотром карты, а часть веб-просмотра прозрачна, а отображение карты отображается под ним. Мы бы хотели, чтобы любые события касания, происходящие в этой прозрачной области, не регистрировались веб-обзором и всплывающими надписями / чем-либо другим, чтобы вы могли просматривать / перетаскивать / увеличивать карту.

Проще говоря: мы хотим, чтобы часть(а не вся) веб-просмотра не фиксировала события, а позволяла базовому представлению захватывать их.

Похоже, что есть некоторые методы в реагировать на нативные, которые позволяют сделать это (условно контролировать захват событий) ( https://facebook.github.io/react-native/docs/view.html), но мы не можем найти любой работающий пример, чтобы протестировать его, и мы не можем полностью понять предоставленную документацию (мы даже не можем понять, должен ли этот обратный вызов быть указан для родительского представления или дочерних представлений).

Так что в основном нам просто нужен какой-то инструмент в реагирующем режиме для условного захвата сенсорных событий.

Кто-нибудь может помочь нам с этим? Пример с картой / веб-просмотром может быть слишком сложным, любой условный захват событий в двух видах должен сильно помочь.

1 ответ

Я не уверен, что это идеальное решение, но что вы можете сделать, это создать EvenEmitter и просто заставить WebView перехватывать все клики. Те, которые должны обрабатываться картой, могут быть отправлены на саму карту.

Я использую их на экранах, где может быть создано несколько компонентов, но они могут быть отправлены на родительский экран. В основном он используется для обработки модальных экранов.

import EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter';

this._eventEmitter = new EventEmitter();

        this._eventEmitter.addListener('modal', (data) => {
            this.setState({
                visibleModal: true,
                modalData: data
            });
        });

Затем вы можете использовать их как emitter.emit("модальные", данные)

Редактировать:

Вот еще один подход, который также показывает, как вы можете использовать методы, которые вы задавали в вопросе.

class Class extends Component {

    onStartShouldSetResponder = () => true;
    onEvent = (e) => {
        let object = {};
        object.locationX = e.nativeEvent.locationX;
        object.locationY = e.nativeEvent.locationY;
        object.pageY = e.nativeEvent.pageY;
        object.pageX = e.nativeEvent.pageX;
        object.target = e.nativeEvent.target;
        //object.touches = e.nativeEvent.touches; //These will trigger a cyclic error while parsing but you can access them
        //object.changedTouches = e.nativeEvent.changedTouches;
        object.identifier = e.nativeEvent.identifier;
        alert(JSON.stringify(object));

        if (object.pageX > this.state.x && object.pageX < (this.state.x + this.state.width) && object.pageY > this.state.y && object.pageY < (this.state.y + this.state.height))
            alert("inside") //Here you can trigger whatever function you need from the underlying view
    }

    onLayout = (event) => {
        this.setState({
            x: event.nativeEvent.layout.x,
            y: event.nativeEvent.layout.y,
            width: event.nativeEvent.layout.width,
            height: event.nativeEvent.layout.height,
        });
    }

    render(){

        return(    

            <ScrollView>

            <View ref={"target"} style={{
                position: 'absolute',
                height: 200,
                width: 200,
                left: 100,
                top: 100,
                backgroundColor: 'rgba(0,0,0,0.5)'
            }}
            onLayout={this.onLayout}
            />

            <View 
            onl
            onStartShouldSetResponder={this.onStartShouldSetResponder} 
            onResponderMove={this.onEvent}
            style={{
                backgroundColor: 'rgba(255,0,0,0.3)',
                width: '100%',
                height: 150
            }}/>

            <TouchableWithoutFeedback 
            onPress={this.onEvent}
            onLongPress={this.onEvent}
            style={{
                backgroundColor: 'rgba(0,255,0,0.3)',
                width: '100%',
                height: 150
            }}> 
            <View style={{height: 150, backgroundColor: 'rgba(0,255,0,0.3)'}}/>
            </TouchableWithoutFeedback>

            <View 
            onTouchStart={this.onEvent}
            onTouchEnd={this.onEvent}
            style={{
                backgroundColor: 'rgba(0,0,255,0.3)',
                width: '100%',
                height: 150
            }}> 
            </View>

            </ScrollView>

        );
    }

}

Может быть, это поможет вам передать события в другие представления

Другие вопросы по тегам