svg旋转,缩放和用鼠标翻译 [英] svg rotation, scale and translate with mouse

查看:73
本文介绍了svg旋转,缩放和用鼠标翻译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试在SVG元素上使用鼠标应用旋转,移动和调整大小。 此处您可以对此进行测试。

Trying to apply rotation, move and resize using mouse on SVG element. Here you can test this.

目前我参与了南方控制,中控和旋转控制。

Currently I worked on South control, Center control and Rotate control.


  1. 旋转工作完全正常,我可以旋转,停止并再次旋转。但是在我通过拖动中心点移动元素后,旋转第一次闪烁,旋转起点不同。我相信这是因为翻译后中心位置发生了变化。我尝试重新计算中心位置,但它没有用。

  1. Rotation works perfectly fine, I can rotate, stop and again rotate. But after I move the element by dragging center point, the rotation flickers first time and rotation starting point is different. I belive this is because center position is changed after translate. I tried recalculating center position but it did not work.

缩放是移动元素而不是增加大小。

And scaling is moving the element instead of increasing the size.

请帮我解决这个问题。我在这里缺少一些调整。

Please help me on this. I am missing some adjustments here.

注意:首先你用鼠标绘制一些路径来获取控件。

Note: First you have draw some path with mouse to get controls on it.

var svg = document.querySelector('.container');
var svgns = 'http://www.w3.org/2000/svg';

var path = document.createElementNS(svgns, 'path');
svg.appendChild(path);

var points = [];
var Resizer_Instance = null;

var boundingBox = svg.getBoundingClientRect();

var toSVGPath = function(points) {
  var SVGPath = '';
  for (var i = 0; i < points.length; i++) {
    var prefix = (i == 0) ? 'M' : 'L';
    SVGPath += prefix + points[i].x + ' ' + points[i].y + ' ';
  }
  return SVGPath;
};

var create_mousedown = false;

var createStart = function(event) {
  create_mousedown = true;
};

var creating = function(event) {
  if (create_mousedown) {
    var point = svg.createSVGPoint();
    point.x = event.clientX - boundingBox.left;
    point.y = event.clientY - boundingBox.top;
    var t = point.matrixTransform(svg.getScreenCTM().inverse());
    points.push(t);
    path.setAttributeNS(null, 'd', toSVGPath(points));
  }
};

var createEnd = function(event) {
  create_mousedown = true;
  svg.removeEventListener('mousedown', createStart);
  svg.removeEventListener('mousemove', creating);
  svg.removeEventListener('mouseup', createEnd);
  setTimeout(function functionName() {
    Resizer_Instance = new Resizer(path, svg);
  }, 500);
};

svg.addEventListener('mousedown', createStart);
svg.addEventListener('mousemove', creating);
svg.addEventListener('mouseup', createEnd);


var Resizer = (function() {

  function Resizer(element) {
    var that = this;
    that.element = element;
    createSelector.call(that);

    document.addEventListener('mousemove', dragging);
    document.addEventListener('mouseup', dragend);

  }

  var RAD2DEG = 180 / Math.PI;

  function angleBetweenPoints(p1, p2) {
    var angle = null;
    if (p1.x == p2.x && p1.y == p2.y)
      angle = Math.PI / 2;
    else
      angle = Math.atan2(p2.y - p1.y, p2.x - p1.x);
    return (angle * RAD2DEG) + -90;
  }

  function controlPositions(el) {
    var pt = svg.createSVGPoint();
    var bbox = el.getBoundingClientRect();
    var matrix = el.getScreenCTM().inverse();
    var halfWidth = bbox.width / 2;
    var halfHeight = bbox.height / 2;
    var placements = {};

    pt.x = bbox.left;
    pt.y = bbox.top;

    placements['nw'] = pt.matrixTransform(matrix);
    pt.x += halfWidth;
    placements['n'] = pt.matrixTransform(matrix);
    pt.x += halfWidth;
    placements['ne'] = pt.matrixTransform(matrix);
    pt.y += halfHeight;
    placements['e'] = pt.matrixTransform(matrix);
    pt.y += halfHeight;
    placements['se'] = pt.matrixTransform(svg.getScreenCTM().inverse());
    pt.x -= halfWidth;
    placements['s'] = pt.matrixTransform(matrix);
    pt.x -= halfWidth;
    placements['sw'] = pt.matrixTransform(matrix);
    pt.y -= halfHeight;
    placements['w'] = pt.matrixTransform(matrix);
    pt.x += halfWidth;
    placements['center'] = pt.matrixTransform(matrix);
    pt.y -= (halfHeight + 30);
    placements['rot'] = pt.matrixTransform(matrix);

    return placements;
  }

  var dragging_element = null;

  var dragstart = function(event) {
    var box = this;
    var context = box.context;
    var rootContext = context.rootContext;
    rootContext.current_handle_inaction = context.direction;
    dragging_element = box;
  };

  var dragging = function(event) {
    if (!dragging_element) return;
    var box = dragging_element;
    var context = box.context;
    var rootContext = context.rootContext;
    var currentHandle = rootContext.current_handle_inaction;
    var control_points = rootContext.control_points;

    if (currentHandle === context.direction) {
      var point = svg.createSVGPoint();
      point.x = event.clientX;
      point.y = event.clientY;
      var element = rootContext.element;
      var transformed = point.matrixTransform(svg.getScreenCTM().inverse());

      var centerPosition = context.center;

      rootContext.angle = rootContext.angle || 0;
      rootContext.hMove = rootContext.hMove || 0;
      rootContext.vMove = rootContext.vMove || 0;
      rootContext.scaleX = rootContext.scaleX || 1;
      rootContext.scaleY = rootContext.scaleY || 1;

      switch (currentHandle) {
        case "rot":
          rootContext.angle = angleBetweenPoints(transformed, centerPosition);
          break;
        case "center":
          rootContext.hMove = transformed.x - centerPosition.x;
          rootContext.vMove = transformed.y - centerPosition.y;
          break;
        case "s":
          var startPos = control_points[currentHandle];
          var vMove = transformed.y - startPos.y;
          rootContext.scaleY += (vMove > 0 ? -1 : 1) * 0.001;
          break;
      }

      var move_transform = "translate(" + rootContext.hMove + " " + rootContext.vMove + ")";
      var rotate_transform = "rotate(" + rootContext.angle + ", " + centerPosition.x + ", " + centerPosition.y + ")";
      var scale_transform = "scale(" + rootContext.scaleX + ", " + rootContext.scaleY + ")";

      var transform = [move_transform, rotate_transform, scale_transform].join(' ');

      rootContext.element.setAttribute('transform', transform);
      rootContext.controlGroup.setAttribute('transform', transform);
    }
  };

  var dragend = function() {
    if (!dragging_element) return;
    var box = dragging_element;
    var context = box.context;
    var rootContext = context.rootContext;
    delete rootContext.current_handle_inaction;
    // createSelector.call(rootContext);
    dragging_element = null;
  };

  var adjustPositions = function() {
    var that = this;
    var control_points = that.control_points;
    var controlGroup = that.controlGroup;
    var point = svg.createSVGPoint();
    for (var direction in control_points) {
      var dP = control_points[direction];
      point.x = dP.x;
      point.y = dP.y;
      debugger;
      control_points[direction] = point.matrixTransform(controlGroup.getScreenCTM().inverse());
    }
    return control_points;
  };

  var Deg2Rad = 0.017453292519943295;

  var createSelector = function() {
    var that = this;
    var points = that.control_points;
    if (points) {
      points = adjustPositions.call(that);
    } else {
      points = controlPositions(that.element, svg);
    }
    that.control_points = points;
    var existingBoxes = {};
    var controlGroup = that.controlGroup;

    if (!controlGroup) {
      controlGroup = document.createElementNS(svgns, 'g');
      that.controlGroup = controlGroup;
      svg.appendChild(controlGroup);
    }

    that.control_boxes = that.control_boxes || {};

    var line_name = "connecting-line",
      line_element = that.control_boxes['connecting-line'];

    var line_route = ["nw", "n", "rot", 'n', "ne", "e", "se", "s", "sw", "w", "nw"];

    if (!line_element) {
      line_element = document.createElementNS(svgns, 'path');
      line_element.style.cssText = "fill: none; stroke: #f41542; opacity: 0.5";

      that.control_boxes[line_name] = line_element;
      controlGroup.appendChild(line_element);

      var pathString = "";

      line_route.forEach(function(direction) {
        var point = points[direction];
        var command = pathString.length === 0 ? "M" : " L ";
        pathString += (command + point.x + " " + point.y);
      });

      line_element.setAttribute('d', pathString);
    }

    Object.keys(points).forEach(function(direction) {
      var point = points[direction];
      var box = that.control_boxes[direction];
      if (!box) {
        box = document.createElementNS(svgns, 'circle');
        box.style.cssText = "fill: #5AABAB";

        that.control_boxes[direction] = box;
        box.setAttributeNS(null, 'r', 3);
        box.setAttribute('handle', direction);

        box.addEventListener('mousedown', dragstart.bind(box));

        controlGroup.appendChild(box);
      }

      box.setAttributeNS(null, 'cx', point.x);
      box.setAttributeNS(null, 'cy', point.y);

      box.context = {
        point: point,
        direction: direction,
        rootContext: that,
        center: points.center
      };

    });


  };

  var prototype = {
    constructor: Resizer
  };
  Resizer.prototype = prototype;
  return Resizer;
})();

path {
  fill: none;
  stroke: #42B6DF;
}
body,
html {
  height: 100%;
  width: 100%;
  margin: 0;
}

<svg class="container" version="1.1" baseProfile="full" style="position:absolute;left:0;top:0;height:100%;width:100%;-ms-transform:scale(1,1);transform:scale(1,1);-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-o-transform:scale(1,1);transform:scale(1,1);-ms-transform-origin:0, 0;-webkit-transform-origin:0, 0;-moz-transform-origin:0, 0;-o-transform-origin:0, 0;transform-origin:0, 0"
viewBox="-220.38356461849224 6442.3347962008365 454.7376658611161 114.54981723871151"></svg>

推荐答案

您当前正在计算相对于图形初始中心的角度(刚绘制时的角度)。这是错误的 - 您需要在上一次移动后计算相对于图形中心的角度。

You are currently calculating angle in relation to the initial center of the figure (the one when you have just drawn it). This is wrong - you need to calculate angle in relation to the center of the figure after previous move.

小提琴

我剥离了我没有改变的部分。

I've stripped the parts that I didn't change.

var dragging = function(event) {
    ...

    if (currentHandle === context.direction) {
        ...

        var initialCenterPosition = context.center,
            // use the coordinates saved after last move or
            // initial coordinates if there are none saved
            previousCenterPosition = rootContext.previousCenterPosition || initialCenterPosition;

        ...

        switch (currentHandle) {
            case "rot":
                rootContext.angle = angleBetweenPoints(transformed, previousCenterPosition);
                break;
            case "center":
                rootContext.hMove = transformed.x - initialCenterPosition.x;
                rootContext.vMove = transformed.y - initialCenterPosition.y;

                // remember the new center coordinates
                rootContext.previousCenterPosition = {
                    x: transformed.x,
                    y: transformed.y
                };
                break;
            case "s":
                ...
        }

        var move_transform = "translate(" + rootContext.hMove + " " + rootContext.vMove + ")";
        var rotate_transform = "rotate(" + rootContext.angle + ", " + initialCenterPosition.x + ", " + initialCenterPosition.y + ")";
        var scale_transform = "scale(" + rootContext.scaleX + ", " + rootContext.scaleY + ")";

        ...
    }
}

这篇关于svg旋转,缩放和用鼠标翻译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆