Skip to content

Offset the vanishing point using padding

Offset the center or vanishing point of the map to reduce distortion when floating elements are displayed over the map.

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Offset the vanishing point using padding</title>
    <meta property="og:description" content="Offset the center or vanishing point of the map to reduce distortion when floating elements are displayed over the map." />
    <meta charset='utf-8'>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel='stylesheet' href='https://unpkg.com/maplibre-gl@4.2.0/dist/maplibre-gl.css' />
    <script src='https://unpkg.com/maplibre-gl@4.2.0/dist/maplibre-gl.js'></script>
    <style>
        body { margin: 0; padding: 0; }
        html, body, #map { height: 100%; }
    </style>
</head>
<body>
<style>
    .rounded-rect {
        background: white;
        border-radius: 10px;
        box-shadow: 0 0 50px -25px black;
    }

    .flex-center {
        position: absolute;
        display: flex;
        justify-content: center;
        align-items: center;
    }

    .flex-center.left {
        left: 0px;
    }

    .flex-center.right {
        right: 0px;
    }

    .sidebar-content {
        position: absolute;
        width: 95%;
        height: 95%;
        font-family: Arial, Helvetica, sans-serif;
        font-size: 32px;
        color: gray;
    }

    .sidebar-toggle {
        position: absolute;
        width: 1.3em;
        height: 1.3em;
        overflow: visible;
        display: flex;
        justify-content: center;
        align-items: center;
    }

    .sidebar-toggle.left {
        right: -1.5em;
    }

    .sidebar-toggle.right {
        left: -1.5em;
    }

    .sidebar-toggle:hover {
        color: #0aa1cf;
        cursor: pointer;
    }

    .sidebar {
        transition: transform 1s;
        z-index: 1;
        width: 300px;
        height: 100%;
    }

    /*
  The sidebar styling has them "expanded" by default, we use CSS transforms to push them offscreen
  The toggleSidebar() function removes this class from the element in order to expand it.
*/
    .left.collapsed {
        transform: translateX(-295px);
    }

    .right.collapsed {
        transform: translateX(295px);
    }
</style>

<div id="map">
    <div id="left" class="sidebar flex-center left collapsed">
        <div class="sidebar-content rounded-rect flex-center">
            Left Sidebar
            <div
                class="sidebar-toggle rounded-rect left"
                onclick="toggleSidebar('left')"
            >
                &rarr;
            </div>
        </div>
    </div>
    <div id="right" class="sidebar flex-center right collapsed">
        <div class="sidebar-content rounded-rect flex-center">
            Right Sidebar
            <div
                class="sidebar-toggle rounded-rect right"
                onclick="toggleSidebar('right')"
            >
                &larr;
            </div>
        </div>
    </div>
</div>

<script>
    const center = [-77.01866, 38.888];
    const map = new maplibregl.Map({
        container: 'map',
        zoom: 12.5,
        center,
        pitch: 60,
        style:
            'https://api.maptiler.com/maps/streets/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL'
    });

    new maplibregl.Marker().setLngLat(center).addTo(map);

    function toggleSidebar(id) {
        const elem = document.getElementById(id);
        const classes = elem.className.split(' ');
        const collapsed = classes.indexOf('collapsed') !== -1;

        const padding = {};

        if (collapsed) {
            // Remove the 'collapsed' class from the class list of the element, this sets it back to the expanded state.
            classes.splice(classes.indexOf('collapsed'), 1);

            padding[id] = 300; // In px, matches the width of the sidebars set in .sidebar CSS class
            map.easeTo({
                padding,
                duration: 1000 // In ms, CSS transition duration property for the sidebar matches this value
            });
        } else {
            padding[id] = 0;
            // Add the 'collapsed' class to the class list of the element
            classes.push('collapsed');

            map.easeTo({
                padding,
                duration: 1000
            });
        }

        // Update the class list on the element
        elem.className = classes.join(' ');
    }

    map.on('load', () => {
        toggleSidebar('left');
    });
</script>
</body>
</html>