I want to implement the functionality like svg-edit on rectangle element
Rotating the SVG rectangle it works fine, but when I want to resize the rectangle it has a problem. The coordinates are not working right; I use the transform matrix to rotate targetelement.setAttribute(transform,rotate(45,cx,cy))
but when the element has been rotated the coordinates are moved. I'm also using inverse
function to inverse the transform matrix it resolves the problem but its not working with drag function.
The transform attribute defines a list of transform definitions that are applied to an element and the element's children. Note: As of SVG2, transform is a presentation attribute, meaning it can be used as a CSS property.
For each given element, the accumulation of all transformations that have been defined on the given element and all of its ancestors up to and including the element that established the current viewport (usually, the 'svg' element which is the most immediate ancestor to the given element) is called the current ...
For all elements, SVG uses a coordinate system or grid system similar to the one used by canvas (and by a whole lot of other computer drawing routines). That is, the top left corner of the document is considered to be the point (0,0), or point of origin.
Just use the element type selector and add the transform: rotate(180deg) property to it like in the below snippet. Show activity on this post. Inline you would do it like this: x-axis flip : transform="scale(-1 1)"
I have created a working example of what I believe you are describing on my site here:
http://phrogz.net/svg/drag_under_transformation.xhtml
In general, you convert the mouse cursor into the local space of an object by:
Creating a mousemove
event handler:
var svg = document.getElementsByTagName('svg')[0]; document.documentElement.addEventListener('mousemove',function(evt){ ... },false);
In that event handler, convert the mouse coordinates (in pixels) into the global space of your SVG document:
var pt = svg.createSVGPoint(); pt.x = evt.clientX; pt.y = evt.clientY; var globalPoint = pt.matrixTransform(svg.getScreenCTM().inverse());
Convert the global point into the space of the object you are dragging:
var globalToLocal = dragObject.getTransformToElement(svg).inverse(); var inObjectSpace = globalPoint.matrixTransform( globalToLocal );
For Stack Overflow posterity, here's the full source of my SVG+XHTML demo (in case my site is down):
<!DOCTYPE HTML> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head> <meta http-equiv="content-type" content="application/xhtml+xml;charset=utf-8"/> <title>Dragging Transformed SVG Elements</title> <style type="text/css" media="screen"> html, body { background:#eee; margin:0; user-select:none; -moz-user-select:none; -webkit-user-select:none; } p { margin:0.5em; text-align:center } svg { position:absolute; top:5%; left:5%; width:90%; height:90%; background:#fff; border:1px solid #ccc } svg rect { stroke:#333 } svg .drag { cursor:move } svg .sizer { opacity:0.3; fill:#ff0; stroke:#630;} #footer { position:absolute; bottom:0.5em; margin-bottom:0; width:40em; margin-left:-20em; left:50%; color:#666; font-style:italic; font-size:85% } #dragcatch { position:absolute; left:0; right:0; top:0; bottom:0; z-index:-1} </style> </head><body> <p>Showing how to drag points inside a transformation hierarchy.</p> <svg viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full"> <g transform="scale(1.2,0.8)"> <rect transform="translate(50,20) rotate(30)" class="drag resize" x="50" y="30" width="50" height="30" fill="#69c" /> <rect class="drag resize" x="5" y="5" width="90" height="50" fill="#c66" /> </g> </svg> <p id="footer"> Copyright © 2011 <a href="mailto:[email protected]">Gavin Kistner</a>. Comments/criticisms welcome. </p> <script type="text/javascript"><![CDATA[ var svg = document.getElementsByTagName('svg')[0]; var svgNS = svg.getAttribute('xmlns'); var pt = svg.createSVGPoint(); function createOn(root,name,prop){ var el = document.createElementNS(svgNS,name); for (var a in prop) if (prop.hasOwnProperty(a)) el.setAttribute(a,prop[a]); return root.appendChild(el); } function rectCorner(rect){ pt.x = rect.x.animVal.value + rect.width.animVal.value; pt.y = rect.y.animVal.value + rect.height.animVal.value; return pt.matrixTransform(rect.getTransformToElement(svg)); } function pointIn(el,x,y){ pt.x = x; pt.y = y; return pt.matrixTransform(el.getTransformToElement(svg).inverse()); } function cursorPoint(evt){ pt.x = evt.clientX; pt.y = evt.clientY; return pt.matrixTransform(svg.getScreenCTM().inverse()); } // Make all rects resizable before drag, so the drag handles become drag for (var a=svg.querySelectorAll('rect.resize'),i=0,len=a.length;i<len;++i){ (function(rect){ var dot = createOn(svg,'circle',{'class':'drag sizer',cx:0,cy:0,r:5}); var moveDotToRect = function(){ var corner = rectCorner(rect); dot.setAttribute('cx',corner.x); dot.setAttribute('cy',corner.y); } moveDotToRect(); rect.addEventListener('dragged',moveDotToRect,false); dot.addEventListener('dragged',function(){ var rectXY = pointIn(rect,dot.cx.animVal.value,dot.cy.animVal.value); var w = Math.max( rectXY.x-rect.x.animVal.value, 1 ); var h = Math.max( rectXY.y-rect.y.animVal.value, 1 ); rect.setAttribute('width', w); rect.setAttribute('height',h); },false); })(a[i]); } for (var a=svg.querySelectorAll('.drag'),i=0,len=a.length;i<len;++i){ (function(el){ var onmove; // make inner closure available for unregistration el.addEventListener('mousedown',function(e){ el.parentNode.appendChild(el); // move to top var x = el.tagName=='circle' ? 'cx' : 'x'; var y = el.tagName=='circle' ? 'cy' : 'y'; var mouseStart = cursorPoint(e); var elementStart = { x:el[x].animVal.value, y:el[y].animVal.value }; onmove = function(e){ var current = cursorPoint(e); pt.x = current.x - mouseStart.x; pt.y = current.y - mouseStart.y; var m = el.getTransformToElement(svg).inverse(); m.e = m.f = 0; pt = pt.matrixTransform(m); el.setAttribute(x,elementStart.x+pt.x); el.setAttribute(y,elementStart.y+pt.y); var dragEvent = document.createEvent("Event"); dragEvent.initEvent("dragged", true, true); el.dispatchEvent(dragEvent); }; document.body.addEventListener('mousemove',onmove,false); },false); document.body.addEventListener('mouseup',function(){ document.body.removeEventListener('mousemove',onmove,false); },false); })(a[i]); } ]]></script> <div id="dragcatch"></div> </body></html>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With