繁体   English   中英

svg旋转,缩放和用鼠标翻译

[英]svg rotation, scale and translate with mouse

尝试在SVG元素上使用鼠标应用旋转,移动和调整大小。 在这里你可以测试一下。

目前我从事南方控制,中心控制和旋转控制。

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

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

请帮帮我。 我在这里错过了一些调整。

注意:首先,您使用鼠标绘制一些路径以获取控件。

 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> 

仅使用这三个变换函数,您无法轻松处理所有三个变换操作(平移,缩放和旋转)。 你实际应该使用四个功能。

你应该记住元素的原始中心点。 我们称之为ocx和ocy。 然后执行以下操作:

  1. 将原始中心点转换为原点
  2. 执行规模
  3. 执行旋转
  4. 将中心转换回新的(当前)中心位置。

所以transform字符串看起来像这样:

transform="translate(ncx,ncy) rotate(rot) scale(sx,sy) translate(-ocx,-ocy)"

这样,您可以将所有操作保持隔离状态,并且在更改时不需要更改其他操作。

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

小提琴

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

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 + ")";

        ...
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM