JSFiddle - React, Tailwind, and code Playground

HTML

<script src="http://kineticjs.com/download/kinetic-v4.0.2.min.js"></script>
<p>Scroll to zoom, drag to pan</p>

<div id="canvas"></div>

CSS

body {
  -webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

#canvas {
  background: #322;
  width: 500px;
  cursor: pointer;
  cursor: grab;
  cursor: -webkit-grab;
  cursor: -moz-grab;
}
#canvas:active {
  cursor: pointer;
  cursor: grabbing;
  cursor: -webkit-grabbing;
  cursor: -moz-grabbing;
}

p {
  position: absolute;
  top: 10px;
  left: 10px;
  color: white;
  font: bold 12px Arial, sans-serif;
  text-transform: uppercase;
  z-index: 10;
}

JavaScript

var stage = new Kinetic.Stage({
    container: "canvas",
    width: 500,
    height: 500
});

var draggableLayer = new Kinetic.Layer();
draggableLayer.setDraggable("draggable");

//a large transparent background to make everything draggable
var background = new Kinetic.Rect({
    x: -1000,
    y: -1000,
    width: 2000,
    height: 2000,
    fill: "#000000",
    opacity: 0
});

draggableLayer.add(background);


//don't mind this, just to create fake elements
var addCircle = function(x, y, r){
  draggableLayer.add(new Kinetic.Circle({
        x: x*700,
        y: y*700,
        radius: r*20,
        fill: "rgb("+ parseInt(255*r) +",0,0)"
    })
  );
}

var circles = 300
while (circles) {
  addCircle(Math.random(),Math.random(), Math.random())
  circles--;
}

var zoom = function(e) {
  var zoomAmount = e.wheelDeltaY*0.001;
  stage.setOffset ( e.pageX, e.pageY );
  stage.setScale(stage.getScale().x+zoomAmount);
  stage.setX ( e.pageY );
  stage.setY ( e.pageY );
  stage.draw();
}

document.addEventListener("mousewheel", zoom, false)

stage.add(draggableLayer)