You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native集成OpenLayers时,通过WebView调用JS函数失败的问题求助

React Native集成OpenLayers时,通过WebView调用JS函数失败的问题求助

各位好,我现在在开发一个React Native结合OpenLayers的应用,遇到了一个卡住的问题:我有两个项目,一个是写了OpenLayers地图的JS项目,里面定义了showMiddlemarker()和hideMiddlemarker()两个函数;另一个是React Native项目,我想通过WebView组件调用这两个函数,但用injectJavaScript方法完全没效果,想请大家帮忙排查下原因!

我的实现逻辑

  • 在React Native中加载本地的index.html(对应OpenLayers的地图页面)
  • 用一个swch状态来控制调用显示/隐藏中间标记的函数,状态变化时会触发injectJavaScript的执行
  • 已经确认swch状态在正确变化(console.log能输出对应的值),但WebView里的函数就是没被触发
  • 另外我测试了onMessage方法是能正常工作的,只有injectJavaScript调用函数这里出问题

React Native端代码

import { useAssets } from "expo-asset";
import { useContext, useEffect, useRef, useState } from "react";
import { useWindowDimensions } from "react-native";
import WebView from "react-native-webview";
import { Context } from "../App";

const Page = () => {
    const [assets] = useAssets([require("../assets/index.html")]);
    const [htmlString, setHtmlString] = useState<string>();
    const pageDimensions = useWindowDimensions();
    const webViewRef = useRef<WebView | null>(null);

    const [add, setAdd, swch] = useContext(Context);


    useEffect(() => {
        if (assets) {
            fetch(assets[0].localUri || "")
                .then((res) => res.text())
                .then((html) => setHtmlString(html));
        }
    }, [assets]);


    useEffect(() => {
        if (webViewRef.current) {
            console.log(swch)
            const functionToCall = swch ? "showMiddlemarker();" : "hideMiddlemarker();";
            webViewRef.current.injectJavaScript(`${functionToCall}; true;`);
        }
    }, [swch]);

    if (!htmlString) {
        return null; 
    }

    return (
        <WebView
            ref={(r) => (webViewRef.current = r)}
            javaScriptEnabled
            source={{
                html: htmlString,
            }}
            style={{
                width: pageDimensions.width,
                height: pageDimensions.height,
            }}
            scrollEnabled={false}
            overScrollMode="never"
            showsHorizontalScrollIndicator={false}
            showsVerticalScrollIndicator={false}
            scalesPageToFit={false}
            containerStyle={{ flex: 1 }}
            onLoad={() => {
                webViewRef.current?.injectJavaScript(`
                  function showMiddlemarker() {
                    console.log("Showing marker");
                    markerElement.style.display = "block";
                  }
                  function hideMiddlemarker() {
                    console.log("Hiding marker");
                    markerElement.style.display = "none";
                  }
                  true;
                `);
              }}
              
        />
    );
};

export default Page;

OpenLayers端JS代码

import "./style.css"
import Feature from 'ol/Feature.js';
import Map from 'ol/Map.js';
import Overlay from 'ol/Overlay.js';
import Point from 'ol/geom/Point.js';
import View from 'ol/View.js';
import {Icon, Style} from 'ol/style.js';
import {OGCMapTile, OSM, Vector as VectorSource} from 'ol/source.js';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer.js';
import { fromLonLat } from 'ol/proj';

const coords = fromLonLat([25.91667,47.85])

const map = new Map({
  target: 'map',
  layers: [
    new TileLayer({
      source: new OSM(),
    }),
  ],
  view: new View({
    center: coords,
    zoom: 13,
  }),
});

const marker = new VectorLayer({
  source: new VectorSource({
    features:[
      new Feature({
        geometry: new Point(
          coords
        )
      })
    ]
  }),
  style: new Style({
    image: new Icon({
      src:"https://i.imgur.com/oOGwJW8.png",
      scale:0.07
    })
  })
})

const markerElement = document.createElement("div");
markerElement.className = "marker";
markerElement.style.width = "32px";
markerElement.style.height = "32px";
markerElement.style.backgroundImage = "url('https://i.imgur.com/oOGwJW8.png')";
markerElement.style.backgroundSize = "contain";
markerElement.style.position = "absolute";
markerElement.style.transform = "translate(-50%, -50%)";
markerElement.style.display = "block"

const markerOverlay = new Overlay({
  element: markerElement,
  positioning: "center-center",
  stopEvent: false,
});
map.addOverlay(markerOverlay);

map.getView().on("change:center", () => {
  const center = map.getView().getCenter();
  markerOverlay.setPosition(center);
});

markerOverlay.setPosition(coords);

//map.addLayer(marker)

function hideMiddlemarker() {
  markerElement.style.display = "none";
}

function showMiddlemarker() {
  markerElement.style.display = "block";
}

当前效果截图

目前地图能正常加载显示,中间标记也能正常显示,就是没法通过React Native的状态切换来控制它的显示隐藏:
当前地图显示效果

备注:内容来源于stack exchange,提问作者Tecleanu Ionut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 10:28:07