javascript - SVG Rotate and Scale Transform Issue -
i trying re-size, rotate , drag svg elements using transformations. if rotate object, re-size it, , rotate again, on last rotation element gets displaced wrongly.
resizing done way
var matrix = svg.createsvgmatrix() .translate(x,y) .scalenonuniform(sx,sy) .translate(-x,-y); var newmatrix = svg.createsvgtransformfrommatrix(ctm.multiply(matrix)); element.transform.baseval.initialize(newmatrix);
rotation done way
var matrix = svg.createsvgmatrix() .translate(cx,cy) .rotate(angle) .translate(-cx,-cy); var newmatrix = svg.createsvgtransformfrommatrix(ctm.multiply(matrix)); element.transform.baseval.initialize(newmatrix);
is there idea resolve issue?
i use combination of getbbox element identify center no matter transforms applied. also, track element's transformed center, enclose in svg wrapper, , bounding box. use matrix transforms , consolidate() on each transform.
the following example on how used move element desired point:
<!doctype html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>native center transforms wrapper</title> <meta http-equiv="content-type" content="text/html; charset=utf-8"> </head> <body style='padding:10px;font-family:arial'> <center> <h4>native center transforms wrapper</h4> <div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:6px;'> <b>native center</b> center of element's bounding box. remains constant no matter transforms has been applied element. therefore center point there can used <b>reference point</b> stable rotation, scale, , skew transforms. use of svg <b>wrapper</b>, element can translated center point moves target point. </div> <table><tr> <td> <div style="padding:10px;width:400px;text-align:justify"> <b>scenerio:</b><br /> rect element has been translated original location (dashed rect). further scale, rotate, , skew transforms can use rect's original bounding box center (black circle): <b>nativecenterx, nativecentery</b>.<br /><br /> also, folowing scale. rotate, skew..<br /> center of element can <b>moved to</b> specific target point (maroon circle) using center point of it's svg <b>wrapper</b> <br /><br /> <i>click buttons 1 or more times transform rect.</i> </div> </td> <td> <div id="svgdiv" style='background-color:lightgreen;width:400px;height:400px;'> <svg id="mysvg" width="400" height="400"> <rect id="myrect" fill=red stroke="none" x="10" y="60" width=150 height=80 transform="translate(110,50)" /> <rect id="bbrect" fill=none stroke="black" stroke-width="1" stroke-dasharray="10 10" /> <circle id=nativecenter r=5 fill="black" stroke="none" /> <circle id=movetotarget r=5 fill="maroon" cx=240 cy=330 stroke="none" /> </svg> </div> <center> <button onclick=rotaterect()>rotate</button> <button onclick=scalerect()>scale</button> <button onclick=skewxrect()>skewx</button> <button onclick=skewyrect()>skewy</button> then...<button onclick=movetorect()>move to</button> </center> </td> </tr></table> <br />svg source:<br /> <textarea id=svgsourcevalue style='font-size:110%;font-family:lucida console;width:90%;height:200px'></textarea> <br />javascript:<br /> <textarea id=jsvalue style='border-radius:26px;font-size:110%;font-weight:bold;color:midnightblue;padding:16px;background-color:beige;border-width:0px;font-size:100%;font-family:lucida console;width:90%;height:400px'></textarea> </center> <div id='browserdiv' style='padding:5px;position:absolute;top:5px;left:5px;background-color:gainsboro;'>ok in:ie11/ch32/ff23<br /></div> <script id=myscript> var nativecenterx var nativecentery var transformrequestobj var transformlist //---translate target--- var targetx var targety //---onload--- function initbbox() { var bb=myrect.getbbox() var bbx=bb.x var bby=bb.y var bbw=bb.width var bbh=bb.height nativecenterx=bbx+.5*bbw nativecentery=bby+.5*bbh bbrect.x.baseval.value=bbx bbrect.y.baseval.value=bby bbrect.width.baseval.value=bbw bbrect.height.baseval.value=bbh nativecenter.cx.baseval.value=nativecenterx nativecenter.cy.baseval.value=nativecentery targetx=movetotarget.cx.baseval.value targety=movetotarget.cy.baseval.value //--- transform myrect objs--- transformrequestobj=mysvg.createsvgtransform() var animtransformlist=myrect.transform transformlist=animtransformlist.baseval } //---button--- function rotaterect() //---15 degrees { transformrequestobj.setrotate(15,nativecenterx,nativecentery) transformlist.appenditem(transformrequestobj) transformlist.consolidate() svgsourcevalue.value=svgdiv.innerhtml } function scalerect() //---.8--- { transformrequestobj.settranslate(nativecenterx,nativecentery ) transformlist.appenditem(transformrequestobj) transformlist.consolidate() transformrequestobj.setscale(.8,.8) transformlist.appenditem(transformrequestobj) transformlist.consolidate() transformrequestobj.settranslate(-nativecenterx,-nativecentery ) transformlist.appenditem(transformrequestobj) transformlist.consolidate() svgsourcevalue.value=svgdiv.innerhtml } function skewxrect() { transformrequestobj.settranslate(nativecenterx,nativecentery ) transformlist.appenditem(transformrequestobj) transformlist.consolidate() transformrequestobj.setskewx(10) transformlist.appenditem(transformrequestobj) transformlist.consolidate() transformrequestobj.settranslate(-nativecenterx,-nativecentery ) transformlist.appenditem(transformrequestobj) transformlist.consolidate() svgsourcevalue.value=svgdiv.innerhtml } function skewyrect() { transformrequestobj.settranslate(nativecenterx,nativecentery ) transformlist.appenditem(transformrequestobj) transformlist.consolidate() transformrequestobj.setskewy(10) transformlist.appenditem(transformrequestobj) transformlist.consolidate() transformrequestobj.settranslate(-nativecenterx,-nativecentery ) transformlist.appenditem(transformrequestobj) transformlist.consolidate() svgsourcevalue.value=svgdiv.innerhtml } var ns="http://www.w3.org/2000/svg" //---move transformed rect specific point(targetx,targety)-- function movetorect() { //---build temp wrapper--- var wrapper=document.createelementns(ns,"svg") mysvg.appendchild(wrapper) //---temp place rect in wrapper--- wrapper.appendchild(myrect) var bb=wrapper.getbbox() //---return myrect previous location--- mysvg.insertbefore(myrect,bbrect) //---remove temp wrapper--- mysvg.removechild(wrapper) var bbx=bb.x var bby=bb.y var bbw=bb.width var bbh=bb.height //---center of svg srapper--- var wcx=bbx+.5*bbw var wcy=bby+.5*bbh //---bind target point current matrix--- var pnt = myrect.nearestviewportelement.createsvgpoint(); pnt.x = targetx; pnt.y = targety; var sctm = myrect.getctm(); pnt1 = pnt.matrixtransform(sctm.inverse()); //---bind wrapper center current matrix-- var pnt = myrect.nearestviewportelement.createsvgpoint(); pnt.x = wcx; pnt.y = wcy ; var sctm = myrect.getctm(); pnt2 = pnt.matrixtransform(sctm.inverse()); //---translate rect's center target--- var transx=pnt1.x-pnt2.x var transy=pnt1.y-pnt2.y transformrequestobj.settranslate(transx,transy) transformlist.appenditem(transformrequestobj) transformlist.consolidate() svgsourcevalue.value=svgdiv.innerhtml } </script> <script> document.addeventlistener("onload",init(),false) function init() { initbbox() svgsourcevalue.value=svgdiv.innerhtml jsvalue.value=myscript.text } </script> </body> </html>
Comments
Post a Comment