0

I have a requirement to enable a user to Rotate a single feature they've added to the map. The feature is part of a geojson FeatureCollection and styled as a symbol with layout properties.

Obviously i can set the layers icon rotation globally but that's not the requirement. The requirement is per feature rotation. Data driven styling isn't supported for the layout properties so i'm wondering if anyone has found a way to do this that doesn't involve creating a layer definition for each rotation option and moving the features to the right layer to render the correct rotation?

3 Answers 3

1

Thanks Andrew. I found an approach a few hours ago that i think is pretty much where you were going. I update the layout to include the following:

"layout": {
  "icon-image": "transformer",
  "icon-size": 1.5,
  "icon-allow-overlap": true,
  "icon-rotate": {
    "property": "rotation",
    "type": "categorical",
    "stops": [
        [30, 30],
        [60, 60],
        [90, 90],
        [120, 120],
        [150, 150],
        [180, 180],
        [210, 210],
        [240, 240],
        [270, 270],
        [300, 300],
        [330, 330],
        [360, 360]
    ],
    "default": 0
}

Then i update the 'rotation' property via my handler, something like this:

feature.properties.rotation = feature.properties.rotation < 360 ? 
feature.properties.rotation + 30 : 0;
const source = map.getSource('transformer');
source && source.setData(createGeojson([feature]));

I'll improve that to increment by values from the stop but it's working. Thanks for the reply.

0

Although "feature-state" data expressions are not supported with layout properties, meaning you can't use feature states to set a per feature rotation, can can still use regular driven styling with icon-rotate[1].

So if you use setData to update your FeatureCollection and set a rotation property you can use data driven styles based on that property.

[1] https://www.mapbox.com/mapbox-gl-js/style-spec/#layout-symbol-icon-rotate

0

To add drone I used:

this._state.map.loadImage('../../../assets/img/mapbox/drone.png', (error, image) => {
    if (error) throw error;
    this._map.droneMarker[id] = image;
    this._state.map.addImage('cat', image);
    this._state.map.addLayer({
        "id": "points" + id,
        "type": "symbol",
        "source": {
            "type": "geojson",
            "data": {
                "type": "FeatureCollection",
                "features": [{
                    "type": "Feature",
                    "geometry": {
                        "type": "Point",
                        "coordinates": [message.longitude, message.latitude]
                    }
                }]
            }
        },
        "layout": {
            "icon-image": "cat",
            "icon-size": 0.50,
            // "icon-rotate": 90
            "icon-allow-overlap": true,
            "icon-rotate": ["get", "rotate"],
        }
    });
});

and for rotation:

let data = {
    "type": "FeatureCollection",
    "features": [{
        "type": "Feature",
        "geometry": {
            "type": "Point",
            "coordinates": [message.longitude, message.latitude]
        },
        "properties": {
            "rotate": this._state.drones_state[id].yaw
        }
    }]
}
console.log(this._state.drones_state[id].yaw);
this._state.map.getSource('points' + id).setData(data);
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.