watergis/mapbox-gl-export

Markers in the Map are not printed

Opened this issue · 4 comments

I was using react-map-gl which is a suite of React components for Mapbox GL JS-compatible libraries. I wanted to implement the exact same functionality as this library but the problem is that the markers in my map are not printed . I tried to use Mapbox GL JS and also added a sample marker just to see if the marker is printed but to no avail .

  useEffect(() => {
    mapRef.current = mapRef.current.getMap().addControl(
      new MapboxExportControl({
        PageSize: Size.A3,
        PageOrientation: PageOrientation.Portrait,
        Format: Format.PNG,
        DPI: DPI[96],
        Crosshair: true,
        PrintableArea: true,
        accessToken: process.env.REACT_APP_MAPBOX_TOKEN,
      }),
      "top-right"
    );

    const marker = new mapboxgl.Marker()
      .setLngLat([8.5, 50])
      .addTo(mapRef.current);

    return () => (mapRef.current = null);
  }, []);
  return (
    <div className={styles.Container}>
      <ReactMapGL
        {...viewport}
        ref={mapRef}
        width="100%"
        height="100%"
        onViewportChange={setViewport}
        mapboxApiAccessToken={process.env.REACT_APP_MAPBOX_TOKEN}
        dragRotate={false}
        mapStyle="mapbox://styles/mapbox/streets-v10"
        preserveDrawingBuffer={true}
      >
        <Pins data={Places} onClick={onSelectPlace} />
        <ScaleControl style={scaleControlStyle} />
        <NavigationControl style={navStyle} />
      </ReactMapGL>
    </div>
  );

The getMap() exposes the Mapbox API here as stated in the documentation of react map gl.

I also printed the map object (mapRef.current) and as we can see the map does contain the marker in it but is not printed.

MicrosoftTeams-image (3)

As far as i see the library only prints the lower layer of map but i also want to print the Pins(Markers) which get populated when the api is called. Can you please help ?

@TARMAH Thank you for reporting the issue. This issue is quite similar to #2 and #31. This plugin is currently only supporting layers which are contained in style.json. If you add other layers such as FeatureState, ICON and marker after loading style.json, it will not be appeared PNG image through this plugin.

The plugin restore layers from map.getStyle() at the following source code.

const renderMap = new MapboxMap({
accessToken: this.accesstoken || accessToken,
container,
center: this.map.getCenter(),
zoom: this.map.getZoom(),
bearing: this.map.getBearing(),
pitch: this.map.getPitch(),
interactive: false,
preserveDrawingBuffer: true,
fadeDuration: 0,
attributionControl: false,
// hack to read transfrom request callback function
transformRequest: (this.map as any)._requestManager._transformRequestFn,
});
const style = this.map.getStyle();
if (style && style.sources) {
const sources = style.sources;
Object.keys(sources).forEach((name) => {
const src = sources[name];
Object.keys(src).forEach((key) => {
// delete properties if value is undefined.
// for instance, raster-dem might has undefined value in "url" and "bounds"
if (!src[key]) delete src[key];
});
});
}
renderMap.setStyle(style);

I think it also requires to restore markers after this part. If do so, I assume markers will be exported to an image. Currently, I don't have enough time to do this, but welcome any pull request to implement this feature to the export plugin.

Hi ... Although I didn't have time to look into and add this feature,I did come up with another solution for printing markers.

`

useEffect(() => {

    setPopupInfo(null)

    setViewport((viewport) => ({
        ...viewport,
        latitude: 51.5,
        longitude: 10.5,
        zoom: 5.5,
        transitionInterpolator: new FlyToInterpolator({ speed: 1.5 }),
        transitionDuration: "auto",
    }));

    //removes the previous layers of points
    prevPlaces?.forEach((x, i) => {
        mapRef.current = mapRef.current.removeLayer(`point${i}`);
        mapRef.current = mapRef.current.removeSource(`point${i}`);
    });

    setprevPlaces(Places);

    //add new layers of points
    Places?.forEach((x, i) => {
        mapRef.current = mapRef.current.addSource(`point${i}`, {
            type: "geojson",
            data: {
                type: "Point",
                coordinates: [x.position.lng, x.position.lat],
            },
        });

        mapRef.current = mapRef.current.addLayer({
            id: `point${i}`,
            source: `point${i}`,
            type: "circle",
            paint: {
                "circle-radius": 8,
                "circle-color": "red",
                "circle-stroke-width": 1,
                "circle-blur": 0.5,
            },
        });
    });
}, [Places]);

`

I am adding layers with circles dynamically each time the data changes. So now my markers look like this .
image

So as you can see there are markers along with circle layers. And when you print the circles are printed like this .
map (5)

@TARMAH Thank you for sharing your solution. Yes, your solution, which adds vector layers and sources into Map object instead of using Marker objects, can work well with this plugin.

Why hasn't this been resolved? Seems like a pretty logical requirement to show the markers on the map that is printed.