Pan and Zoom

Click and drag to scroll across the map. Also use the mousewheel to scroll in and out. Works for any contents of div.

by 20yco

HTML

<script src="https://raw.github.com/MadLittleMods/jQuery-Scripts/master/jquery.mousewheel.js"></script>
<div class="wrapper">
    <div class="results">
        <div>
            Click Pos: (<span class="clickPosX">null</span>,
            <span class="clickPosY">null</span>)
        </div>
        <div>
            Move Pos: (<span class="moveClickPosX">null</span>,
            <span class="moveClickPosY">null</span>)
        </div>
        <div>
            Dragging: <span class="draggingIndicator">no</span>
        </div>
        <div>
            Zoom: <span class="zoomIndicator">100%</span>
        </div>
        <div>
            <small>Map generated using <a href="http://richy1913.byethost22.com/projects/perlin-noise-map-generator/">Richy's Map Generator</a>.</small>
        </div>
    </div>
    <div class="map_overlay">
        <div class="map_outline"></div>
    </div>
    
    <div class="canvas">
        <img src="http://source.visualpulse.net/images/12_qkg0xbzw6xyma4vs5bm6roj2puo19cafa3dxqqmc.png" alt="map" />
    </div>
</div>

CSS

html, body
{
    width: 100%;
    height: 100%;   

    font-family: Calibri, Candara, Segoe, "Segoe UI", Optima, Arial, sans-serif;
    
    margin: 0;
    padding: 0;
}

.wrapper
{
    width: 100%;
    height: 100%;
    position: relative;
}

.results
{
    position: absolute;
    background: rgba(255, 255, 255, .4);
    pointer-events: none;
    
    width: 160px;
    padding: 2px 4px;
    -webkit-border-bottom-right-radius: 4px;
    -moz-border-radius-bottomright: 4px;
    border-bottom-right-radius: 4px;
}

.map_overlay
{
    background: url(http://source.visualpulse.net/images/12_qkg0xbzw6xyma4vs5bm6roj2puo19cafa3dxqqmc.png);
    background-size: 100%;
    background-repeat: no-repeat;
    
    position: absolute;
    left: 0;
    bottom: 0;
    pointer-events: none;
    opacity: 0.4;
}

.map_outline
{
    position: absolute;
    border: 2px solid #dd0000;
}

.canvas
{
    width: 100%;
    height: 100%;
    cursor: url(https://mail.google.com/mail/images/2/openhand.cur), default;
    
    zoom: 100%;
    overflow: scroll;       
}

.cursordrag
{
    cursor: url(https://mail.google.com/mail/images/2/closedhand.cur), default !important;
}

JavaScript

var clickPosX = null;
var clickPosY = null;
var movePosX = null;
var movePosY = null;

var oldPosX = null;
var oldPosY = null;

var dragging = false;

var mapZoom = 1;

function updateMap(basedFromElement, mapElement, mapSizePercentage, firstRun) {
    var elementWidth = basedFromElement.find(">:first-child").width();
    var elementHeight = basedFromElement.find(">:first-child").height();
    var viewportWidth = basedFromElement.width();
    var viewportHeight = basedFromElement.height();
    
    if(firstRun)
    {
        mapElement.width(elementWidth * mapSizePercentage);
        mapElement.height(elementHeight * mapSizePercentage);
        
        mapElement.find(">:first-child").width(viewportWidth * mapSizePercentage * mapZoom);
        mapElement.find(">:first-child").height(viewportHeight * mapSizePercentage * mapZoom);
    }
    else
    {
        mapElement.find(">:first-child").width(viewportWidth * mapSizePercentage * mapZoom);
        mapElement.find(">:first-child").height(viewportHeight * mapSizePercentage * mapZoom);
        console.log(viewportWidth + " " + mapSizePercentage + " " + mapZoom);
        
        mapElement.find(">:first-child").css('top', basedFromElement.scrollTop() * mapSizePercentage);
        mapElement.find(">:first-child").css('left', basedFromElement.scrollLeft() * mapSizePercentage);
    }
}
updateMap($('.canvas'), $('.map_overlay'), 0.1, true);

// Drag around
$('.canvas').on('mousedown', function(e) {
    clickPosX = e.pageX;
    clickPosY = e.pageY;
    $('.clickPosX').html(clickPosX);
    $('.clickPosY').html(clickPosY);
    
    oldPosX = e.pageX;
    oldPosY = e.pageY;
    
    dragging = true;
    $('.draggingIndicator').html('yes');
    
    e.originalEvent.preventDefault(); // prevents the browser from adding their own cursor
    $(this).addClass('cursordrag'); // Adds the custom grabbing hand cursor
    updateMap($('.canvas'), $('.map_overlay'), 0.1, false); // Update Map
}).on('mousemove', function(e) {
   ...