Search code examples
javascriptopenlayersopenlayers-7

Is there a way to change the scale of a feature after it has been placed in openlayers 7?


Is there a way to update the scale of an icon being placed on an openlayers map after it's been placed there?

I have map with a marker icon on it. I'd like the user to be able to make the icon larger/smaller using a slider.

I've been trying to figure it out using getStyle or setStyle but can't seem to get the scale to change.

var london = [-0.1276474, 51.507321899999994];
var isOnMap = true;  

    const baseMapTile = new ol.layer.Tile({
            source: new ol.source.OSM(),
            visible: true,
            title: 'OSMStandard'
    });
    
    
    const marker = new ol.Feature({
        geometry: new ol.geom.Point(ol.proj.fromLonLat(london)),
        name: 'Somewhere near Nottingham',
    });
    
    
    const map = new ol.Map({
    view: new ol.View({
            
      center: (ol.proj.fromLonLat(london)),
      zoom: 15,
    }),
        layers: [
            baseMapTile,
            new ol.layer.Vector({
                source: new ol.source.Vector({
                    features: [marker]
                }),
                style: new ol.style.Style({
                    image: new ol.style.Icon({
                        anchor: [0.5, 1],
                        scale: 1,
                        src: 'https://openlayers.org/en/latest/examples/data/icon.png'
                    })
                })
            })
        ],
    target: 'map'
    
  });

var translate = new ol.interaction.Translate({
    features: new ol.Collection([marker])
});

map.addInteraction(translate);

document.getElementById('markerSlider').oninput = function() {
    newScale = document.getElementById('markerSlider').value / 100;
  console.log(newScale);
    document.getElementById('newScale').innerHTML = newScale;
}


/*
translate.on('translating', function (evt) {});
map.getView().on(['change:center', 'change:resolution', 'change:rotation'], function() {});
*/
#map{
    width: 300px;
    height: 300px;
    border: 1px solid black;
    padding: 5px;
    float: left;

}
#info{
width: calc(100% - 330px);
margin-left: 5px;
padding: 5px;
height: 100px;
    border: 1px solid black;
    float: left;
}
.info h2{
    font-size: small;
    text-decoration: underline;
    font-weight: 600;
    margin: 0 0 10px 0;
}
#newScale{
    font-size: larger;
    margin: 5px 0 0 15px;;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/ol.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ol.js"></script>
<div id="map" class="map"></div>    
<div id="info" class="info">
    <h2>Change Marker Size</h2>
    <input type='range' min='50' max='150' value='100' class='markerSlider' id='markerSlider'><br>
    <span id='newScale'>1</span>
</div>


Solution

  • After some help and some more experimenting I figured it out. The required lines of code were:

    markerStyle.getImage().setScale([parseFloat(newScale),parseFloat(newScale)]);
    marker.changed();
    

    The first ling of code gets the image associated with the marker and sets the new scale ratio. The second line is required to update the change on the map output.

    var london = [-0.1276474, 51.507321899999994];
    var isOnMap = true; 
    var availableMarkers = [ ['https://testing.52weekdog.com/images/markers/marker_marker01_black.svg', 0.1, [0.5,1]],
                                                        ['https://testing.52weekdog.com/images/markers/marker_marker02_black.svg', 0.1, [0,0]],
                                                        ['https://testing.52weekdog.com/images/markers/marker_pin01_black.svg', 0.1, [0,0]],
                                                        ['https://testing.52weekdog.com/images/markers/marker_house01_black.svg', 0.1, [0,0]]
                                                 ];
    
        const baseMapTile = new ol.layer.Tile({
                source: new ol.source.OSM(),
                visible: true,
                title: 'OSMStandard'
        });
        
        
        const marker = new ol.Feature({
            geometry: new ol.geom.Point(ol.proj.fromLonLat(london)),
            name: 'Somewhere near Nottingham',
        });
        
        const markerStyle = new ol.style.Style({
            image: new ol.style.Icon({
                anchor: availableMarkers[0][2],
                scale: availableMarkers[0][1],
                src: availableMarkers[0][0]
            })
        });
        
        
        
    const vectorSource = new ol.layer.Vector({
                    source: new ol.source.Vector({
                        features: [marker]
                    }),
                    style: markerStyle
                });
    
    
        
        
        marker.setStyle([markerStyle]);
        
        
        const map = new ol.Map({
        view: new ol.View({         
          center: (ol.proj.fromLonLat(london)),
          zoom: 15,
        }),
            layers: [baseMapTile, vectorSource],
        target: 'map'
        
      });
    
    var translate = new ol.interaction.Translate({
        features: new ol.Collection([marker])
    });
    
    map.addInteraction(translate);
    
    document.getElementById('markerSlider').oninput = function() {
        newScale = document.getElementById('markerSlider').value / 100 * 0.1;
      
        document.getElementById('newScale').innerHTML = (newScale * 1000).toFixed();
        markerStyle.getImage().setScale([parseFloat(newScale),parseFloat(newScale)]);
        marker.changed();
    }
    
    //markerStyle.getImage().setSrc('test');
        //console.log(markerStyle.getImage().getSrc());
    
    
    
    /*
    translate.on('translating', function (evt) {});
    map.getView().on(['change:center', 'change:resolution', 'change:rotation'], function() {});
    */
    #map{
        width: 300px;
        height: 300px;
        border: 1px solid black;
        padding: 5px;
        float: left;
    
    }
    #info{
    width: calc(100% - 330px);
    margin-left: 5px;
    padding: 5px;
    height: 100px;
        border: 1px solid black;
        float: left;
    }
    .info h2{
        font-size: small;
        text-decoration: underline;
        font-weight: 600;
        margin: 0 0 10px 0;
    }
    #newScale{
        font-size: larger;
        margin: 5px 0 0 15px;;
    }
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/ol.css" rel="stylesheet"/>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/ol.js"></script><div id="map" class="map"></div>   
    <div id="info" class="info">
        <h2>Change Marker Size</h2>
        <input type='range' min='50' max='150' value='100' class='markerSlider' id='markerSlider'><br>
        <span id='newScale'>100</span>
    </div>