javascript - svg rotation, scale and translate with mouse -
trying apply rotation, move , resize using mouse on svg element. here can test this.
currently worked on south control, center control , rotate control.
rotation works fine, can rotate, stop , again rotate. after move element dragging center point, rotation flickers first time , rotation starting point different. belive because center position changed after translate. tried recalculating center position did not work.
and scaling moving element instead of increasing size.
please me on this. missing adjustments here.
note: first have draw path mouse 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 = ''; (var = 0; < 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 = 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 = this; var control_points = that.control_points; var controlgroup = that.controlgroup; var point = svg.createsvgpoint(); (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 = 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 calculating angle in relation initial center of figure (the 1 when have drawn it). wrong - need calculate angle in relation center of figure after previous move.
i've stripped parts didn't change.
var dragging = function(event) { ... if (currenthandle === context.direction) { ... var initialcenterposition = context.center, // use coordinates saved after last move or // initial coordinates if there 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 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 + ")"; ... } }
Comments
Post a Comment