Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Path drawing and resizing with Mouse

Tags:

javascript

svg

I am trying to rotate SVG path with mouse. Fiddle. But I have few problems with it,

  1. The origin of rotation is wrong
  2. When I stop rotation and rotate again it is starting from different starting angle instead of starting from the previous angle.
  3. Not sure how to update the position of circle after rotation.

Code here:

var svgns = 'http://www.w3.org/2000/svg';
var path = document.getElementById('path-element');
var angle = 0;
function getRotationPoint() {
  var bRect = path.getBoundingClientRect();
  var rotationPoint = [bRect.left + (bRect.width / 2), bRect.top - 20];
  return rotationPoint;
}
var rotationPoint = getRotationPoint();
var circle = document.createElementNS(svgns, 'circle');
circle.setAttribute('style', 'fill: #DCDCDC; stroke: red; stroke-width: 2; pointer-events: visiblePainted');
circle.setAttribute('cx', rotationPoint[0]);
circle.setAttribute('cy', rotationPoint[1]);
circle.setAttribute('r', 4);
document.querySelector('svg').appendChild(circle);

var mousedown = false, mouse_start = null;

circle.addEventListener('mousedown', function(event) {
  mousedown = true;
  initial_position = getRotationPoint();
  mouse_start = {
    x: event.clientX,
    y: event.clientY
  };
});

document.addEventListener('mousemove', function(event) {
  if (mousedown) {
    var x = event.clientX,
      y = event.clientY;
    var _angle = Math.atan2(y - mouse_start.y, x - mouse_start.x) * 180 / Math.PI;
    var transform = "rotate(" + _angle + "," + rotationPoint[0] + "," + rotationPoint[1] + ")";
    path.setAttribute('transform', transform);
  }
});

document.addEventListener('mouseup', function(event) {
  mousedown = false;
});

Please let me know, if any other information is needed.

var svgns = 'http://www.w3.org/2000/svg';
var path = document.getElementById('path-element');
var angle = 0;

function getRotationPoint() {
  var bRect = path.getBoundingClientRect();
  var rotationPoint = [bRect.left + (bRect.width / 2), bRect.top - 20];
  return rotationPoint;
}

var rotationPoint = getRotationPoint();


circle = document.createElementNS(svgns, 'circle');

circle.setAttribute('style', 'fill: #DCDCDC; stroke: red; stroke-width: 2; pointer-events: visiblePainted');
circle.setAttribute('cx', rotationPoint[0]);
circle.setAttribute('cy', rotationPoint[1]);
circle.setAttribute('r', 4);

document.querySelector('svg').appendChild(circle);


var mousedown = false,
  mouse_start = null;

circle.addEventListener('mousedown', function(event) {
  mousedown = true;
  initial_position = getRotationPoint();
  mouse_start = {
    x: event.clientX,
    y: event.clientY
  };
});

document.addEventListener('mousemove', function(event) {
  if (mousedown) {
    var x = event.clientX,
      y = event.clientY;
    var _angle = Math.atan2(y - mouse_start.y, x - mouse_start.x) * 180 / Math.PI;
    var transform = "rotate(" + _angle + "," + rotationPoint[0] + "," + rotationPoint[1] + ")";
    path.setAttribute('transform', transform);
  }
});

document.addEventListener('mouseup', function(event) {
  mousedown = false;
});
html,
body {
  height: 100%;
  width: 100%;
  margin: 0px;
}
<svg class="design-review-container" version="1.1" baseProfile="full" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none">
  <path id="path-element" style="fill: none; stroke: rgb(33, 150, 243); stroke-width: 3; pointer-events: visiblePainted; transform-origin: 50% 50%;" d="M109,100 C110.33333333333333,98.33333333333333,112.66666666666667,92,117,90 C121.33333333333333,88,128.83333333333334,82.83333333333333,135,88 C141.16666666666666,93.16666666666667,145,111.5,154,121 C163,130.5,177.83333333333334,140.5,189,145 C200.16666666666666,149.5,214,149.66666666666666,221,148 C228,146.33333333333334,229.33333333333334,137.16666666666666,231,135"></path>
</svg>
like image 331
Exception Avatar asked Oct 31 '16 13:10

Exception


1 Answers

The reason your centre is wrong is because you are using getBoundingClientRect(). This returns the location of the path on the page. Not within the SVG. When you take those rect coordinates and use them for the position of your new <circle>, it gets positioned in the wrong place. That's because the SVG is not positioned at the very top left of the page.

You should be using getBBox() to get the bounds of the path in SVG coordinates.

However if you do that, you will also need to convert your mouse coordinates to SVG coordinates. Otherwise your rotational dragging will not work properly.

See this SO question to see how to convert mouse coords to SVG coords.

like image 178
Paul LeBeau Avatar answered Nov 15 '22 08:11

Paul LeBeau