cdubbs
cdubbs

Reputation: 93

Resizing a container while transforming the contents

I'm looking to put a Mapbox map into a container that is X,Y in size. Then I need to have a slider that, when adjusted, will simultaneously resize the div and scale the map at an inverse proportion. This might sound like simple zooming in on a map, but the desired effect is that the div appears to remain the same size but a wider portion of the map comes into view while maintaining the same zoom level on the map, effectively I'm widening the view port of the map, but keeping the container's viewport on the page the same size.

My initial thoughts on the implementation would be something like this:

    #map{ width: 250px; height: 250px; }

then the slider input value of .5, we would perform a transform: scale(0.5); and simultaneously increase the div to 500px,500px

I've created testbed here if anyone has some thoughts: http://jsfiddle.net/cdubbs/91uj9ce7/

Is something like this even possible? Or is there an alternative way to do this (whether it would perform faster or be more widely compatible)?

Upvotes: 0

Views: 896

Answers (1)

hopkins-matt
hopkins-matt

Reputation: 2823

I'm not gonna lie... this solution is kind of "hack"-y, but it works.

Update: Now works with Firefox & IE(Only tested on IE11)

DEMO: http://jsfiddle.net/hopkins_matt/91uj9ce7/13/

HTML:

<div id="map" style="width: 250px; height: 250px;"></div>

<input type="range" min="10" max="100" value="100" class="scale" step="1" oninput="scaleMap(value)" onchange="scaleMap(value)" id="scale">
<output for="fader" id="percentage">100</output>  

JS:

mapboxgl.accessToken = '* insert access token *';
var map = new mapboxgl.Map({
  container: 'map', // container id
  style: 'https://www.mapbox.com/mapbox-gl-styles/styles/outdoors-v7.json', //stylesheet location
  center: [40, -74.50], // starting position
  zoom: 9 // starting zoom
});

function scaleMap(percentage) {
    document.querySelector('#percentage').value = percentage;
    var mapDiv = document.getElementById("map");
    var initialWidth = mapDiv.offsetWidth;
    var initialHeight = mapDiv.offsetHeight;
    var mapCanvas = document.getElementsByTagName("canvas");
    function divSize(multiplier) {
        return (100 / percentage) * multiplier;
    }
    var mapScale = (percentage / 100);
    mapDiv.style.width = divSize(initialWidth) + "px";
    mapDiv.style.height = divSize(initialHeight) + "px";
    mapCanvas[0].style.width = divSize(initialWidth) + "px";
    mapCanvas[0].style.height = divSize(initialHeight) + "px";
    mapCanvas[0].width = divSize(initialWidth);
    mapCanvas[0].height = divSize(initialHeight);
    map.resize();
    mapCanvas[0].style.transform = "scale(" +mapScale+")";
    mapCanvas[0].style.marginLeft = (((divSize(initialWidth) - initialWidth) / 2) * -1) + "px";
    mapCanvas[0].style.marginTop = (((divSize(initialHeight) - initialHeight) / 2) * -1) + "px";
    document.getElementById("map").style.width = initialWidth + "px";

CSS:

#map {
    overflow: hidden;
    position:relative;
}

#map div canvas {
    padding: 0;
    margin: auto;
    display: block;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

Upvotes: 1

Related Questions