Native Point On Transformed Element: getCTM vs getScreenCTM

http://svgdiscovery.com/E/Ed.htm

http://www.carto.net/svg/eventhandling/

http://stackoverflow.com/questions/5901607/svg-coordiantes

 

 

 

Native Point On Transformed Element: getCTM vs getScreenCTM

When an element has been transformed, either individually, and/or inside a tranformed container, it is important to be able to find native points on the transformed element. These 'native' points can then be referenced to svg 'image' points, and visa versa. getCTM used to obtain points in the transformed element and operate on them. getScreenCtM used to obtain a points in the transformed element , and use it within the transformed element.
Scenerio:
1.) SVG image is inline, contained in a DIV.
2.) The blue rect element is contained in a <g>.
3.) The <g> element has been transformed.
4.) The maroon rect resides in a different viewPort.
5.) The orange circle have been transformed.
5.) The red circle is not transformed.
6.) Click at element to show its native point.
*Get Element Point - getCTM:
redCircle clicked: black circle to its center.
blueRect clicked: black circle to its corner.
maroonRect clicked: black circle to its corner.
orangeCircle clicked: black circle to its center.
*This feature works only if the SVG ViewBox,
or its width/height is the same size as the DIV
getScreenCTM:
The black circle receive the transform of the clicked element,
and it will be placed at the 'native' point clicked.
  Target:
htmX: htmY:
SvgX: SvgY:
Clicked native point on element
NatX: NatY:

SVG Source:

Javascript:

 

Native Point On Transformed Element: getCTM vs getScreenCTM

When an element has been transformed, either individually, and/or inside a tranformed container, it is important to be able to find native points on the transformed element. These 'native' points can then be referenced to svg 'image' points, and visa versa. getCTM used to obtain points in the transformed element and operate on them. getScreenCtM used to obtain a points in the transformed element , and use it within the transformed element.

 

Scenerio:
1.) SVG image is inline, contained in a DIV.
2.) The blue rect element is contained in a <g>.
3.) The <g> element has been transformed.
4.) The maroon rect resides in a different viewPort.
5.) The orange circle have been transformed.
5.) The red circle is not transformed.
6.) Click at element to show its native point.
*Get Element Point - getCTM:
redCircle clicked: black circle to its center.
blueRect clicked: black circle to its corner.
maroonRect clicked: black circle to its corner.
orangeCircle clicked: black circle to its center.
*This feature works only if the SVG ViewBox,
or its width/height is the same size as the DIV
getScreenCTM:
The black circle receive the transform of the clicked element,
and it will be placed at the 'native' point clicked.
  Target:
htmX: htmY:
SvgX: SvgY:
Clicked native point on element
NatX: NatY:


<svg id="mySVG" width="400" height="400" onclick="showCTM(evt)" onmousemove="svgCursor(evt)">
<rect id="bbRect" stroke="black" stroke-width="1" fill="yellow" fill-opacity=".5"></rect>
<circle id="redCircle" cx="120" cy="180" r="40" fill="red" stroke="black" stroke-width="2"></circle>
<circle transform="matrix(0.5, 1.15195, 0, 0.9, 180, -260)" id="orangeCircle" cx="200" cy="200" r="40" fill="orange" stroke="black" stroke-width="2"></circle>
<svg viewBox="0 100 800 800">
<rect id="maroonRect" x="200" y="200" width="160" height="60" fill="maroon" stroke="black" stroke-width="2"></rect>
</svg>
<g transform="matrix(1.08446, 0.815207, -0.316712, 0.68404, 69.5454, -107.056)" id="myG">
<rect id="blueRect" x="220" y="250" width="60" height="60" fill="blue" stroke="black" stroke-width="2"></rect>
</g>
<circle id="blackCircle" r="10" fill="black"></circle>
</svg>

 



document.onmousemove = htmCursor
//---'event' is the html event object---
function htmCursor(event)
{
    var event = event || window.event;
    myMouseX=event.clientX;
    myMouseY=event.clientY;

    htmlOffsetXValue.value = myMouseX + document.documentElement.scrollLeft;
    htmlOffsetYValue.value = myMouseY + document.documentElement.scrollTop;
}

//---mouse move---

//---'evt' is the svg event object--
function svgCursor(evt)
{
    var pnt = mySVG.createSVGPoint();
    pnt.x = evt.clientX;
    pnt.y = evt.clientY;
    var svgCTM=mySVG.getScreenCTM();
    var iPNT = pnt.matrixTransform(svgCTM.inverse());
    SvgXValue.value=rnd2(iPNT.x)
    SvgYValue.value=rnd2(iPNT.y)
}

//---mouse click---
function showCTM(evt)
{
    var target=evt.target
    elemIdValue.value=target.id

    var pnt = mySVG.createSVGPoint();
    pnt.x = evt.clientX;
    pnt.y = evt.clientY;


    var SCTM = target.getScreenCTM();
    var iPNT = pnt.matrixTransform(SCTM.inverse());


    SCTMXValue.value=rnd2(iPNT.x)
    SCTMYValue.value=rnd2(iPNT.y)

    if(ctmRadio.checked==true)
        placeBlackCircle(target)
    else if(sctmRadio.checked==true)
        sendBlackCircle(evt)

}
//---this feature works only if the svg viewBox is same as DIV width/height--
function placeBlackCircle(target)
{
    blackCircle.removeAttribute("transform")
    var pnt = mySVG.createSVGPoint();
    if(target.id=="redCircle" ||target.id=="orangeCircle")
    {
        pnt.x=parseFloat(target.getAttribute("cx"))
        pnt.y=parseFloat(target.getAttribute("cy"))
    }
    if(target.id=="blueRect" ||target.id=="maroonRect")
    {
        pnt.x=parseFloat(target.getAttribute("x"))
        pnt.y=parseFloat(target.getAttribute("y"))
    }

    var CTM=target.getCTM()
    //---get related svg image x,y---
    var PNT = pnt.matrixTransform(CTM);

    blackCircle.setAttribute("cx",PNT.x)
    blackCircle.setAttribute("cy",PNT.y)
}

function sendBlackCircle(evt)
{
    blackCircle.removeAttribute("transform")
    var target=evt.target;

    //---initialize a point in its respective viewport--
    if(target.nearestViewportElement) //--must click on an element not svg root--
    {
        var pnt = target.nearestViewportElement.createSVGPoint();
        //---client area click point---
        pnt.x = evt.clientX;
        pnt.y = evt.clientY;

        var sCTM = target.getScreenCTM();
        //---return viewport's Pnt.x, Pnt.y---
        PNT = pnt.matrixTransform(sCTM.inverse());
        //----place blackDot on top in viewport and locate it---
        target.nearestViewportElement.appendChild(blackCircle)
        blackCircle.setAttribute("cx",PNT.x)
        blackCircle.setAttribute("cy",PNT.y)

        if(target.parentNode.nodeName=="g")
        {
            target.parentNode.appendChild(blackCircle)
        }
        if(target.getAttribute("transform"))
        {
            var transform=target.getAttribute("transform")
            blackCircle.setAttribute("transform",transform)
        }
        else
            blackCircle.removeAttribute("transform")
    }
}

function rnd2(num)
{
  return Math.round(num*100)/100
}


//---onload---
function initTransforms()
{
//---place some transforms on the elements---

    //--- transform orange circle---
    var transformRequestObj=mySVG.createSVGTransform()
    var animTransformList=orangeCircle.transform
    var transformList=animTransformList.baseVal
    //---translate---
    transformRequestObj.setTranslate(180,-260)
    transformList.appendItem(transformRequestObj)
    transformList.consolidate()
    //----scale---
    transformRequestObj.setScale(.5,.9)
    transformList.appendItem(transformRequestObj)
    transformList.consolidate()
    //----skewY---
    transformRequestObj.setSkewY(52)
    transformList.appendItem(transformRequestObj)
    transformList.consolidate()

    //--init Transform on myG---
    var transformRequestObj=mySVG.createSVGTransform()
    var animTransformList=myG.transform
    var transformList=animTransformList.baseVal
    //---translate---
    transformRequestObj.setTranslate(-50,-80)
    transformList.appendItem(transformRequestObj)
    transformList.consolidate()
    //----skewX---
    transformRequestObj.setSkewX(15)
    transformList.appendItem(transformRequestObj)
    transformList.consolidate()
    //----skewY---
    transformRequestObj.setSkewY(20)
    transformList.appendItem(transformRequestObj)
    transformList.consolidate()
    //---rotate---
    transformRequestObj.setRotate(30,200,200)
    transformList.appendItem(transformRequestObj)
    transformList.consolidate()

}


posted @ 2014-11-25 15:01  alxe_yu  阅读(608)  评论(0)    收藏  举报