Search code examples
javascripthtmlcsssvgpaperjs

Problems panning large svg in PaperJS


var path = new Path.Circle({
  center: view.center,
  radius: 10,
  strokeColor: 'red',
  strokeWidth: 3,
  applyMatrix: false,
  strokeScaling: false
});

var svgItem;

project.importSVG("https://svgshare.com/getbyhash/sha1-yxefOEotn9oAUgg+1qfc5gNw4Bs=", {
  onLoad : function (item) {
    item.center = view.center;
    svgItem = item;
  }
});

console.log(svgItem);

tool.onMouseMove = function(event) {
  //on mouse move the position of 'path' var changes to underneath cursor again
  path.position = event.point;
  //console.log(event.point); //debug
}

var toolSize = document.getElementById("tool");

console.log(toolSize);
toolSize.addEventListener("change", function(event) {
  console.log("Radius slider change detected! " + event.target.value + ". path.radius is: " + path.bounds.width);
  //path.radius = event.target.value;
  path.scaling = this.value;
});

tool.onMouseDrag = function(event) {
  //test to see of the shift key was held whilst a mouse drag action was peformed
  if (event.modifiers.shift)
  {
    //move the image the distance of the mouse drag
    svgItem.position = view.center + event.delta;
  }
}
body,
html {
  width: 100%;
  height: 100%;
  margin: 0px;
}

body {
  min-height: 100%;
}

main {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

canvas {
  width: 90vw;
  height: 90vh;
  border: 1px solid;
}

#opts {
  position: absolute;
  right: 10vw;
  bottom: 10vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.11.8/paper-full.js"></script>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width; initial-scale=1.0">
  <link href="svg_style.css" type="text/css" rel="stylesheet" />
</head>
<body>
  <div id="opts">
    <input id="tool" type="range" name="tool" min="1" max="10" value="1" step="1" id="toolSize" />
    <input id="smooth" type="range" name="flatten" min="1" max="10" value="1" step="1" id="smooth" />
    <input id="flatten" type="range" name="flatten" min="1" max="10" value="1" step="1" id="flatten" />
  </div>
  <main>
    <canvas id="canvas" resize></canvas>
  </main>
  <script type="text/paperscript" src="paper_script.js" canvas="canvas">
  </script>
</body>

</html>

I can't actually get my example to work anywhere except for on localhost but I have a large SVG inside of my paperJS canvas which extends out past the canvas bounds.

When I try to pan it by pressing shift and dragging the mouse the svg moves but ultimately snaps to a specific position and responds but always pings back to this place after that


Solution

  • Your error is in this line:

    svgItem.position = view.center + event.delta;
    

    Inside of a mousedrag event handler function, event.delta is actually representing the vector between the last point and the current point. You were wrongly calculating the desired position by simply adding this vector to view center point.

    What you want to do instead, is add this vector to item current position.

    svgItem.position += event.delta;
    

    Here is a sketch demonstrating the solution.

    // draw a circle
    var item = new Path.Circle({
        center: view.center,
        radius: 50,
        fillColor: 'orange'
    });
    
    // on mouse drag...
    function onMouseDrag(event) {
        // ...if shift is pressed...
        if (event.modifiers.shift) {
            // ...move item
            item.position += event.delta;
        }
    }
    
    // display instructions
    new PointText({
        content: 'press shift and drag to move the circle',
        point: view.center + [0, -50],
        justification: 'center'
    });