30

我尝试了我在网上找到的所有东西,Stackoverflow 和 Github,但我仍然无法成功。

我想用自定义图标制作自定义标记,但是在下面的代码中,我总是遇到错误:'TypeError: options.icon.createIcon is not a function'

这是我的代码(文件夹路径没有错误,一切都在 src/js 或 src/img 中)

图标.js

import L from 'leaflet';

const iconPerson = L.Icon.extend({
  options: {
    iconUrl: require('../img/marker-pin-person.svg'),
    iconRetinaUrl: require('../img/marker-pin-person.svg'),
    iconAnchor: null,
    popupAnchor: null,
    shadowUrl: null,
    shadowSize: null,
    shadowAnchor: null,
    iconSize: new L.Point(60, 75),
    className: 'leaflet-div-icon'
  }
});

export { iconPerson };

MarkerPin人

import React from 'react';
import { Marker } from 'react-leaflet';
import {  iconPerson  } from './Icons';


export default class MarkerPinPerson extends React.Component {

  render() {

    return (
      <Marker
        position={this.props.markerPosition}
        icon={ iconPerson }
        >
      </Marker>
      );
  }
}

真的在寻找你的帮助!

4

6 回答 6

47

我终于找到了Icon.js文件的正确代码:

import L from 'leaflet';

const iconPerson = new L.Icon({
    iconUrl: require('../img/marker-pin-person.svg'),
    iconRetinaUrl: require('../img/marker-pin-person.svg'),
    iconAnchor: null,
    popupAnchor: null,
    shadowUrl: null,
    shadowSize: null,
    shadowAnchor: null,
    iconSize: new L.Point(60, 75),
    className: 'leaflet-div-icon'
});

export { iconPerson };
于 2017-12-09T17:47:02.570 回答
7

我是在试图弄清楚如何呈现自定义图标服务器端(使用 react-leaflet-universal)时被带到这里的。我想我会发布这个,以防将来有人出于同样的原因发现自己在这里。就像在 react-leaflet-markercluster 的情况下一样,我可以通过在返回函数中要求传单来实现这一点,例如:

<Map center={this.props.center}
             zoom={zoom}
             className={leafletMapContainerClassName}
             scrollWheelZoom={false}
             maxZoom={18}
             preferCanvas={false}
        >
            {() => {
                const MarkerClusterGroup = require('react-leaflet-markercluster').default;
                const L = require('leaflet');

                const myIcon = L.icon({
                    iconUrl: require('../assets/marker.svg'),
                    iconSize: [64,64],
                    iconAnchor: [32, 64],
                    popupAnchor: null,
                    shadowUrl: null,
                    shadowSize: null,
                    shadowAnchor: null
                });

                return (
                    <React.Fragment>
                        <TileLayer
                            url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                            attribution=''
                            setParams={true}
                        />
                        <MarkerClusterGroup>
                            {coordArray.map(item => {
                                return (
                                    <Marker icon={myIcon} key={item.toString()} position={[item.lat, item.lng]}>
                                        {item.title && <Popup>
                                            <span>{item.title}</span>
                                        </Popup>}
                                    </Marker>
                                )
                            })}
                        </MarkerClusterGroup>
                    </React.Fragment>
                );
            }}
        </Map>
于 2018-10-30T20:07:13.157 回答
4

你不需要使用require。而不是给 iconUrl = "../assets/name" 你只需要导入你的 png 或 svg 然后你可以给你的 iconUrl 源。看下面的例子:

// 首先导入你的图片或 svg

import heart from "../../images/other/love.svg";

// 为你的图标提供来源

let loveIcon = L.icon({
  iconUrl: heart,
  iconRetinaUrl: heart,
  iconAnchor: [5, 55],
  popupAnchor: [10, -44],
  iconSize: [25, 55],
});

// 只需将其添加到您的地图中

L.marker([28, 50], {
       icon: loveIcon,
     }).addTo(map);
于 2020-11-20T09:46:57.163 回答
2

我也遇到了同样的问题。这是我的工作解决方案:

`import L from 'leaflet';
import marker from '../assets/placer.svg';
const myIcon = new L.Icon({
    iconUrl: marker,
    iconRetinaUrl: marker,
    popupAnchor:  [-0, -0],
    iconSize: [32,45],     
});`
于 2021-01-16T12:06:11.050 回答
2

您可以组织不同的文件,并更改 Svg Compoment 属性,如颜色、高度宽度等...

  1. 我们将创建一个函数 React Component,注意我们必须将 {...props} 中的一个 spreat 传递给 svg 文件,这样我们就可以在执行时更改它:

import React from "react";
export default function PinMoto(props) {
return (
    //its a SVG example, it`s by half, or corrupted, to not occupy large caracter space here, use your SVG file here...
    <svg width="37" height="45" viewBox="0 0 26 34" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
        <path d="M13 0C6.0974 0 0.481453 5.83195 0.481453 13C0.481453 15.1519 0.999529 17.2855 1.98441 19.1779L12.3154 33.5811C12.4529 33.8397 12.715 34 13 34C13.285 34 13.547 33.8397 13.6846 33.5811L24.0194 19.1715C25.0005 17.2855 25.5185 15.1518 25.5185 12.9999C25.5185 5.83195 19.9026 0 13 0Z" fill="#DC462D" {...props}/>
        <g clip-Path="url(#clip0)">
        <path d="M19.0012 12.7109C17.3488 12.7109 16.0023 14.1322 16.0023 15.8763C16.0023 17.6204 17.3453 19.0417 19.0012 19.0417C20.6535 19.0417 22 17.6242 22 15.8763C22 14.1285 20.6535 12.7109 19.0012 12.7109ZM19.0012 18.2513C17.7602 18.2513 16.7512 17.1863 16.7512 15.8763C16.7512 14.5663 17.7602 13.5013 19.0012 13.5013C20.2422 13.5013 21.2512 14.5663 21.2512 15.8763C21.2512 17.1863 20.2422 18.2513 19.0012 18.2513Z" fill="white" />
            
        </g>
        <defs>
            <clippath id="clip0">
                <rect width="18" height="19" fill="white" transform="translate(4 4)" />
            </clippath>
        </defs>
    </svg>);
}

  1. 在另一个文件 Utils.js 中导入这个组件,在这个文件中我们可以找到一个函数,它返回一个实时修改的 React svg 组件:

import PinMoto from '../svg_pins/PinMoto'
import { ReactDOM } from 'react'
import { renderToStaticMarkup } from 'react-dom/server'
import { divIcon } from 'leaflet'

export const getRequiredSVGPinByCategory = (category,  myStyle) => { 
    let pin
    switch (category) {              
        case 'motorcycle':
            pin = <PinMoto {...myStyle}/>
            break;                                 
        case 'truck':
            pin = <PinCaminhao {...myStyle}/>
            break;                                                                
        default:
            //pin = <PinPadrao {...myStyle}/>
            break;
        }
    const iconMarkup = renderToStaticMarkup(
       pin
    )
    const customMarketIcon = divIcon({
        html: iconMarkup
    })
    return customMarketIcon
}

  1. 在包含 MapContainer 的主文件中,我们可以这样使用:

import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import L from 'leaflet';
import   { getRequiredSVGPinByCategory } from '../../utils/util'
    
//your jsx and codes...
    <MapContainer
        center={[-20.268589, -40.290479]}
        zoom={10}
        scrollWheelZoom={true}
        style={{height: 500, width: '100%'}}>
        <TileLayer
            attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
            url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
            <Marker position={[-20.268589, -40.290479]}
            icon={ getRequiredSVGPinByCategory('motorcycle', {fill: 'orange'} ) }>
            </Marker>
    </MapContainer>
//...

我希望这对你们有用。

于 2021-10-02T19:25:09.747 回答
0

在 react-leaflet v3 中,这对我来说效果很好:首先我制作了一个 SVG 图标,然后我对其进行了编码encodeURIComponent,最后我将它传递给了 Marker

    import React, {useEffect} from 'react';
    import {MapContainer, Marker, Popup, TileLayer} from 'react-leaflet';
    import Main from "../publicComponents/main";
    import L from "leaflet";
    
    const position = [35.72428729739558, 51.447000503540046]
    const Red_MARKER = `data:image/svg+xml;utf8,${encodeURIComponent(`<?xml version="1.0" encoding="iso-8859-1"?>
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="36.059" height="36.059" viewBox="0 0 36.059 36.059" style="transform:rotate(${0}deg)">
      <defs>
        <filter id="Path_10080" x="0" y="0" width="36.059" height="36.059" filterUnits="userSpaceOnUse">
          <feOffset input="SourceAlpha"/>
          <feGaussianBlur stdDeviation="2.5" result="blur"/>
          <feFlood flood-opacity="0.161"/>
          <feComposite operator="in" in2="blur"/>
          <feComposite in="SourceGraphic"/>
        </filter>
      </defs>
      <g id="Group_8038" data-name="Group 8038" transform="translate(5719.5 1106.5)">
        <rect id="Rectangle_2670" data-name="Rectangle 2670" width="21" height="21" transform="translate(-5712 -1099)" fill="none"/>
        <g transform="matrix(1, 0, 0, 1, -5719.5, -1106.5)" filter="url(#Path_10080)">
          <path id="Path_10080-2" data-name="Path 10080" d="M15.4,12.766a6.414,6.414,0,0,0,1.781-5.634l-.446-2.55-2.55-.446A6.414,6.414,0,0,0,8.553,5.916L6.746,7.723c.234-.232-.845.866-.626.626l-2.96,2.96a2.644,2.644,0,0,0,0,3.735l3.114,3.114a2.644,2.644,0,0,0,3.735,0l2.96-2.96Z" transform="translate(19.2 2.96) rotate(45)" fill="${"red"}"/>
        </g>
      </g>
    </svg>
    `)}`;

    const BoatIcon = L.icon({
        iconUrl: Red_MARKER,
        iconSize: [40, 40],
        iconAnchor: [12, 12],
        popupAnchor: [0, 0],
    });
    

    const Index = () => {
        return (<Main>
                <MapContainer center={position} zoom={13}
                              style={{width: "100%", height: "calc(100vh - 80px)", overflow: "hidden"}}>
                    <TileLayer
                        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                    />
                    <Marker position={position} icon={BoatIcon}>
                        <Popup>
                            A pretty CSS3 popup. <br/> Easily customizable.
                        </Popup>
                    </Marker>
                </MapContainer></Main>
        );
    };
    
    export default Index;
于 2022-02-13T06:36:40.183 回答