All,
I have a SVG rectangle in my application which can be stretched horizontally by dragging the end bar (left & right) on either side of the rectangle. The rectangle can be
(1) resized (by stretching as per above),
(2)dragged,
(3)& rotated.
Everything works fine, however, one strange experience is that when I rotate the rectangle to a degree close to 90, & then try to resize the rectangle, it starts stretching from the opposite border of the rectangle instead of the original borders. (here is the image):
It appears to be getting confused between left and right when I use the rotate function.
Here is the revised HTML, JS & SVG:
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
<!-- <script type="text/javascript" src="CPolyline.js">
</script>-->
</head>
<body>
<object id="oo" data="rect2.svg" style="position:fixed;width: 800px;height:800px;bottom:-100px;right: 375px;">
</object>
path: <input type="button" id="path" onclick="X()">
path2: <input type="button" id="path2" onclick="Y()">
<input type="button" value="Rotate" onclick="Rotate1()">
<script type="text/javascript">
var ob=document.getElementById("oo")
var svgDoc=null;
var svgRoot=null;
var MyGroupObjectsObj = null;
var svgNS = "http://www.w3.org/2000/svg";
var dragTarget = null;
var rectTemplate = null;
var grabPoint = null;
var clientPoint = null;
var rectX = null;
var rectY = null;
var rectWidth = null;
var rectHeight = null;
var arr=new Array();
var resizingLeft = false;
var resizingRight = false;
var rectrot=null
ob.addEventListener("load", function(){
svgDoc=ob.contentDocument;
svgRoot=svgDoc.documentElement;
grabPoint = svgRoot.createSVGPoint();
clientPoint = svgRoot.createSVGPoint();
rectTemplate = svgDoc.getElementById('rectTemplate')
rectrot=svgDoc.getElementById("rect1")
}, false)
var angel=0
function Rotate1()
{
angel=angel+10
//alert(rectrot)
var c=rectTemplate.getAttribute("transform");
var widt=Number(rectTemplate.getAttribute("width"))/2;
var hie=Number(rectTemplate.getAttribute("height"))/2
var tran=c.match(/[\d\.]+/g);
var newxpo=Number(tran[0])+widt;
var newypo=Number(tran[1])+hie;
var r=Math.tan((newxpo)/(newypo))
rectTemplate.parentNode.setAttribute("transform","translate("+newxpo+" "+newypo+")"+"rotate("+angel+") translate("+(newxpo*-1)+" "+(newypo*-1)+")");
}
function MouseDown(evt)
{
var targetElement = evt.target;
var checkForResizeAttempt = false;
if (targetElement == rectTemplate)
{
//arr.push(cir ,cir1,rectTemplate)
dragTarget = targetElement;
checkForResizeAttempt = true;
var transMatrix = dragTarget.getCTM();
grabPoint.x = evt.clientX - Number(transMatrix.e);
grabPoint.y = evt.clientY - Number(transMatrix.f);
}
var transMatrix = dragTarget.getCTM();
//var transMatrix = dragTarget.getCTM().inverse();
grabPoint.x = evt.clientX - Number(transMatrix.e);
grabPoint.y = evt.clientY - Number(transMatrix.f);
if (window.console) console.log(grabPoint.x + " " + grabPoint.y);
if (window.console) console.log(evt.clientX + " " + evt.clientY);
if (checkForResizeAttempt)
{
clientPoint.x = evt.clientX;
clientPoint.y = evt.clientY;
rectX = Number(dragTarget.getAttributeNS(null, "x"));
rectY = Number(dragTarget.getAttributeNS(null, "y"));
rectWidth = Number(dragTarget.getAttributeNS(null, "width"));
rectHeight = Number(dragTarget.getAttributeNS(null, "height"));
if ((grabPoint.x - rectX) < 10)
{
resizingLeft = true;
}
else if (((rectX + rectWidth) - grabPoint.x) < 10)
{
resizingRight = true;
}
if (resizingLeft || resizingRight)
{
dragTarget.setAttributeNS(null,"stroke","green");
}
else
{
dragTarget.setAttributeNS(null,"stroke","black");
}
}
}
function MouseMove(evt)
{
evt.stopPropagation();
if (dragTarget == null)
{
return;
}
if (resizingLeft)
{
if (window.console) console.log(evt.clientX + " " + evt.clientY);
deltaX = (clientPoint.x - evt.clientX);
if (window.console) console.log("deltaX = " + deltaX);
dragTarget.setAttributeNS(null,"width",rectWidth + deltaX);
dragTarget.setAttributeNS(null,"x",rectX - deltaX);
}
else if (resizingRight)
{
deltaX = (clientPoint.x - evt.clientX);
if (window.console) console.log("rectWidth = " + rectWidth + " deltaX = " + deltaX);
dragTarget.setAttributeNS(null,"width",rectWidth - deltaX);
}
else
{
var newXX = evt.clientX-grabPoint.x;
var newYX = evt.clientY-grabPoint.y;
dragTarget.setAttributeNS(null,'transform','translate(' + newXX + ',' + newYX + ')');
}
}
function MouseUp(evt)
{
evt.stopPropagation();
if (dragTarget == null)
{
return;
}
resizingLeft = false;
resizingRight = false;
resizingTop = false;
resizingBottom = false;
// var transMatrix = dragTarget.getCTM().inverse();
dragTarget.setAttributeNS(null,"stroke","blue");
dragTarget = null;
}
</script>
</body>
</html>
--
=======SVG ====
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="612px" height="792px" xml:space="preserve"
onmousedown="ecmascript:top.MouseDown(evt)"
onmousemove="ecmascript:top.MouseMove(evt)"
onmouseup="ecmascript:top.MouseUp(evt)">
<g id="rect1">
<rect id="rectTemplate" x="0" y="0" stroke="blue" width="100" height="30" />
</g>
I have posted a sample of dragging and resizing transformed SVG rects in my answer here:
SVG coordinates with transform matrix
You can see the working example on my site here:
http://phrogz.net/svg/drag_under_transformation.xhtml
The key is to:
mousedown
) record the mouse location (in SVG global space).mousemove
) calculate the offset (in SVG global space) for the drag, and thenThis works regardless of the transformation hierarchy applied (as shown in my example).
Have you tried to change your code to rotate the shape around the center of the shape?
Here is an excerpt of the W3C draft on transform:
rotate(<rotate-angle> [<cx> <cy>]),
which specifies a rotation by <rotate-angle> degrees about a given point.
If optional parameters <cx> and <cy> are not supplied, the rotate is about the origin of the current user coordinate system.
The operation corresponds to the matrix [cos(a) sin(a) -sin(a) cos(a) 0 0].
If optional parameters <cx> and <cy> are supplied, the rotate is about the point (cx, cy).
The operation represents the equivalent of the following specification:
translate(<cx>, <cy>) rotate(<rotate-angle>) translate(-<cx>, -<cy>).
If you set cx and cy to the center of your ribbon, this may help from what context I can pick up from your code.
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