【问题标题】:custom marker icon with react-leaflet带有反应传单的自定义标记图标
【发布时间】:2018-05-23 06:10:49
【问题描述】:

我尝试了我在网络上找到的所有东西,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 };

MarkerPinPerson

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>
      );
  }
}

真的在寻求您的帮助!

【问题讨论】:

    标签: icons maps leaflet marker react-leaflet


    【解决方案1】:

    我终于找到了 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 };
    

    【讨论】:

    • 没有require 就无法渲染,这正是我所需要的。
    • 我不会使用 leaflet-div-icon 类。它将呈现带边框的白色背景。
    【解决方案2】:

    我是在试图弄清楚如何呈现自定义图标服务器端(使用 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>
    

    【讨论】:

    • 我如何以这种方式使用 react-icon?
    【解决方案3】:

    你不需要使用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);
    

    【讨论】:

    • 对我来说,它使用 iconUrl: heart.src 在 next.js v11.1.0 上工作,否则它会将一个对象放入 img src。
    【解决方案4】:

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

    1. 我们将创建一个函数 React 组件,注意我们必须将 {...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>
    //...

    希望对大家有用。

    【讨论】:

      【解决方案5】:

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

      `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],     
      });`
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-28
        • 1970-01-01
        • 2022-08-14
        • 2011-10-04
        • 2016-10-18
        相关资源
        最近更新 更多