Dragging SVG

Arrastrar un SVG dentro de su viewport con el ratón

by Diego Buendia

HTML

<div style="position: relative;top: 50px;left: 20px; width: 300px; height: 300px; background-color:  bisque">
  <svg version="1.1" id="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="300" width="300" viewBox="0 0 300 300">
    <rect id="rect_1" x="0" y="0" width="50" height="50" fill="red" transform="translate(25,50)" />
    <rect id="rect_2" x="0" y="0" width="50" height="20" fill="blue" transform="translate(225,150)" />
    <rect id="rect_3" x="0" y="0" width="80" height="30" fill="green" transform="translate(75,200)" />

  </svg>
</div>
<div id="texto" style="position:absolute; top:10px; left:10px">
  HOLA
</div>

JavaScript

addEventListener('mousedown', mousedown, false);

var mainsvg = document.getElementById('svg');
var texto = document.getElementById('texto');
var xy0;

function getSvgCordinates(event) {

  var m = mainsvg.getScreenCTM();
  var p = mainsvg.createSVGPoint();

  var x, y;

  x = event.pageX;
  y = event.pageY;

  p.x = x;
  p.y = y;
  p = p.matrixTransform(m.inverse());

  x = p.x;
  y = p.y;

  x = parseFloat(x.toFixed(3));
  y = parseFloat(y.toFixed(3));

  return {
    x: x,
    y: y
  };
}

function mousedown(event) {
  xy0 = getSvgCordinates(event);
  texto.innerText = event.target.id;
  addEventListener('mousemove', drag, false);
  addEventListener('mouseup', mouseup, false);
}

function drag(event) {
  var viewBox = svg.getAttribute('viewBox');
  viewBox = viewBox.split(' ');
  var vwx = parseFloat(viewBox[0]);
  var vwy = parseFloat(viewBox[1]);

  var xy = getSvgCordinates(event);
  var x = xy.x;
  var y = xy.y;

  var x0 = xy0.x;
  var y0 = xy0.y;

  var dx = (x - x0);
  var dy = (y - y0);
  var xnew, ynew;

  var xnew = vwx - dx;
  var ynew = vwy - dy;

  var s = 'XY0 (coord.click): ' + x0 + ',' + y0 + '\n' +
    'XY (coord.drag): ' + x + ',' + y + '\n' +
    'VW (coord.viewport): ' + vwx + ',' + vwy + '\n' +
    'XY-XY0: ' + dx + ',' + dy + '\n' +
    'VMNEW: ' + xnew + ',' + ynew;
  texto.innerText = s;

  viewBox = xnew + ' ' + ynew + ' ' + viewBox[2] + ' ' + viewBox[3];
  svg.setAttribute('viewBox', viewBox);
}

function mouseup(event) {
  removeEventListener('mousemove', drag, false);
  removeEventListener('mouseup', mouseup, false);
}