OpenLayers 6 Map Click – How to Add Marker

openlayersreact

I want to implement adding icon/marker on map click. It should work like this (Leaflet example). https://codesandbox.io/s/add-onclick-on-mapcontainer-in-react-leaflet-v-3x-4r7tc

I am using OpenLayers 6.5 and React (java script tip would be fine enough thought). My current code looks like this. My idea was to use Draw Api to style the point to Icon manner but it failed to work. Line and Polygons are styled correctly thought. Is there any efficient way to do this or any workarounds?

Additional it would be ideal to swap current default point style to my Icon (following cursor movement).

const drawSource = new VectorSource({ wrapX: false });

class PublicMap extends Component {
  constructor(props) {
    super(props);

    this.state = {
      center: [0, 0],
      zoom: 1,
      draw: null,
      drawVectorLayer: new VectorLayer({
        source: drawSource,
        style: new Style({
          fill: new Fill({
            color: `rgba(4, 149, 106, 1)`,
          }),
          stroke: new Stroke({ color: "blue" }),
          image: new Icon({
            anchor: [16, 48],
            imgSize: [32, 48],
            src: "http://openlayers.org/en/v3.20.1/examples/data/icon.png",
            zIndex: "10",
          }),
        }),
      }),
    };


    this.olmap = new Map({
      layers: [
        new Tile({
          source: new OSM(),
        }),
        this.state.drawVectorLayer,
      ],
      view: new View({
        center: [0, 0],
        zoom: 2,
      }),
      target: null,
    });
  }

  componentDidMount() {
    this.olmap.setTarget("map");
  }

  addInteraction(e) {
    this.olmap.removeInteraction(this.state.draw);

    if (e.target.value === "None") {
      this.setState({ draw: null });
      return;
    }
    this.setState(
      { draw: new Draw({ source: drawSource, type: e.target.value }) },
      () => {
        this.olmap.addInteraction(this.state.draw);
      }
    );
  }

  undoLastPoint() {
    this.state.draw.removeLastPoint();
  }

  render() {
    return (
      <>
        <div id="map" style={{ width: "100%", height: "800px" }}></div>
        <form class="form-inline">
          <label for="type">Geometry type: &nbsp;</label>
          <select id="type" onChange={this.addInteraction.bind(this)}>
            <option value="None">None</option>
            <option value="Point">Point</option>
            <option value="Polygon">Polygon</option>
            <option value="Circle">Circle</option>
          </select>
          <input
            type="button"
            value="Undo last drawn point while drawing polygon. "
            id="undo"
            onClick={this.undoLastPoint.bind(this)}
          />
        </form>
      </>
    );
  }
}

export default PublicMap;

Best Answer

Either the anchor should be specified as fractions of the image size (the default option)

      image: new Icon({
        anchor: [0.5, 1],
        imgSize: [32, 48],
        src: "https://openlayers.org/en/v3.20.1/examples/data/icon.png",
      }),

or the units must be specified as pixels

      image: new Icon({
        anchor: [16, 48],
        anchorXUnits: 'pixels',
        anchorYUnits: 'pixels',
        imgSize: [32, 48],
        src: "https://openlayers.org/en/v3.20.1/examples/data/icon.png",
      }),
Related Question