React-Leaflet标记文件未找到。

31

我有一个非常简单的代码,用于使用react-leaflet显示地图并在上面放置标记。但是,在我的浏览器控制台中会出现以下两个错误:

GET http://localhost:8080/marker-icon-2x.png 404 (未找到)

GET http://localhost:8080/marker-shadow.png 404 (未找到)

我尝试通过下载这两个图像并将它们放在根目录来解决此问题。它可以工作。然而,我该如何更改react-leaflet标记元素查找标记图像的URL?我想将它们存储在“./images”而不是根目录中。


2
你能标记有帮助的答案吗? - Stevan Tosic
9个回答

95

试试这个 :)

由于某些原因,React leaflet不包含图像,您需要重置默认图标图像。

以下是一些有效的示例,我希望它能解决您的问题。

您还可以从公共链接中添加图标

https://cdnjs.com/libraries/Leaflet.awesome-markers

import React, { Component } from 'react';
import L from 'leaflet';
import {
    Map, TileLayer, Marker, Popup
} from 'react-leaflet'
import 'leaflet/dist/leaflet.css';
import './style.css';


import icon from 'leaflet/dist/images/marker-icon.png';
import iconShadow from 'leaflet/dist/images/marker-shadow.png';

let DefaultIcon = L.icon({
    iconUrl: icon,
    shadowUrl: iconShadow
});

L.Marker.prototype.options.icon = DefaultIcon;

14
谢谢!当我缩小地图时,这些标记出现了另一个问题:它们会"移动"并变得不准确。您可以通过将'iconSize: [25,41], iconAnchor: [12,41]'添加到默认图标中来解决此问题。 - EngJon
1
谢谢,我已经试了几天了,一直在努力弄清楚它。 - Sai Krishnadas
2
难以置信,一个2018年的答案比最近的答案更有帮助。 - JkAlombro

15

这是对我有效的解决方案:

我在文件顶部添加了以下几行:

import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
import L from 'leaflet';

delete L.Icon.Default.prototype._getIconUrl;

L.Icon.Default.mergeOptions({
    iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png').default,
    iconUrl: require('leaflet/dist/images/marker-icon.png').default,
    shadowUrl: require('leaflet/dist/images/marker-shadow.png').default
});

3
谢谢!.default 对我很有帮助。不知怎么的,我在这里找到了我需要的答案 :) - The Shmoo
1
我做了。我只是复制了这段代码,它就可以运行了。我不知道为什么。谢谢。 - MateuszC
1
这个几个月前还能正常工作,现在却出现了一长串错误,以 Uncaught Error: iconUrl not set in Icon options (see the docs). 开头,最后以 The above error occurred in the <ForwardRef(ContainerComponent)> component: 结尾。有什么办法可以让它再次正常工作吗? - Nipuna

12

为Next.js添加答案

  1. node_modules/leaflet/dist/images复制标记图标到public/images,例如/images/marker-icon.png

  2. 创建Leaflet图标引用并在Marker中使用该引用

const icon = L.icon({ iconUrl: "/images/marker-icon.png" });

// some other code

<Marker key={obj.id} position={position} icon={icon}>

// rest of the code

1
在Next.js中工作得很好!谢谢。 - lakjeewa Wijebandara

6

使用react、leaflet和react-leaflet时,似乎并不是所有的东西都能很好地整合在一起。我也遇到了同样的问题,并找到了这个链接:

https://github.com/PaulLeCam/react-leaflet/issues/453

你需要重新设置leafelet本身,因为在导入leaflet.css后会出现一些错误。

希望它有所帮助。


4

将leaflet包中的所有图像复制到public目录:

cp node_modules/leaflet/dist/images/* {PUBLIC_WEB_DIRECTORY}/leaflet_images/

修复Leaflet中的路径。
import L from 'leaflet';
L.Icon.Default.imagePath='leaflet_images/';

2

@ch4nd4n的回答详细解释如下,并适用于leaflet(v1.8.0)和reactjs(v17)。

import iconMarker from 'leaflet/dist/images/marker-icon.png'
import iconRetina from 'leaflet/dist/images/marker-icon-2x.png'
import iconShadow from 'leaflet/dist/images/marker-shadow.png'

那么,

const icon = L.icon({ 
    iconRetinaUrl:iconRetina, 
    iconUrl: iconMarker, 
    shadowUrl: iconShadow 
});

Marker组件添加图标属性。

<Marker key={index} position={[loc.lat, loc.long]} icon={icon}>
    <Popup><h3>{loc.name}</h3> {loc.address}</Popup>
</Marker>

1
类似的解决方案,适用于 TypeScript。
//CSS and marker image fix for Leaflet map
import "leaflet/dist/leaflet.css";
import iconMarker from "leaflet/dist/images/marker-icon.png";
import iconRetina from "leaflet/dist/images/marker-icon-2x.png";
import iconShadow from "leaflet/dist/images/marker-shadow.png";
import L from "leaflet";
L.Icon.Default.mergeOptions({
  iconRetinaUrl: iconRetina,
  iconUrl: iconMarker,
  shadowUrl: iconShadow,
});

将此代码添加到您脚本的导入部分。 说明 据我所知,Leaflet通常从CDN使用,但在使用react的情况下,我们将使用node模块。因此,我们需要将CSS重新指向node模块的CSS,并且还需要将默认图标重定向到指向node模块。

1
我最终解决了这个问题,方法是移除以下代码:

import 'leaflet/dist/leaflet.css';

这段代码在我的地图组件文件中。我通过create-react-app index.html文件导入leaflet css,这样我的标记可以和地图一起加载。希望这能帮助任何卡住的人。

嗯,为了抽象化,最好将CSS导入保留在您的地图组件中。假设您从项目中删除地图;您是否需要担心清理整个代码库以查找相关资源并将其删除? - Kalnode

0
对于任何试图在 Expo React Native 应用中使用 Leaflet 的人来说,标记图像也无法加载。一个解决方法是使用 expo-assetnpx expo install expo-asset,然后将图标放置在资产文件夹中。然后,您需要使用 expo-asset 获取一个 URI,并将其用作 Leaflet 图标的 iconUrl
import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import L from "leaflet";
import { Asset } from "expo-asset";

import React from "react";
import { StyleSheet } from "react-native";

const WebMap = () => {
  const icon = require('../../../assets/icon.png');
  const iconURI = Asset.fromModule(icon).uri;

  const leafletIcon = new L.Icon({
    iconUrl: iconURI,
    iconSize: [30, 30],
    iconAnchor: [22, 94],
    popupAnchor: [-3, -76],
  });
  return (
      <MapContainer
        center={[51.505, -0.09]}
        zoom={13}
        scrollWheelZoom={true}
        style={styles.container}
      >
        <TileLayer
          url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"
          attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        />
        <Marker position={[51.505, -0.09]} icon={leafletIcon}>
          <Popup>
            A pretty CSS3 popup. <br /> Easily customizable.
          </Popup>
        </Marker>
      </MapContainer>
  );
};

const styles = StyleSheet.create({
  container: {
    width: "500px",
    height: "500px",
  },
});

export default WebMap;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接