user1361529
user1361529

Reputation: 2697

zooming an image results in issues with pageX/pageY to SVG conversions

I am trying to move a SVG circle that sits in the center of an HTML image. If you mouse down on the image and drag the circle it works great.

However, if I zoom the image (tap on + button in the codepen), pageX and pageY to SVG co-ordinate translation messes up.

How should I be handling this correctly ? (My complete code handles both touch and mouse events for SVG - I've simplified it to just mouse for this example)

My codepen: http://codepen.io/pliablepixels/pen/EZxyRN

Here is how I am getting co-ordinates (please see codepen for a runnable example):

 // map to SVG view so I can move the circle
  function recompute(ax,ay)
  {
   // alert ("Here");
        var svg=document.getElementById('zsvg');
        var pt = svg.createSVGPoint();
        pt.x = ax;
        pt.y = ay;
        var svgP = pt.matrixTransform(svg.getScreenCTM().inverse());
        $scope.cx = Math.round(svgP.x);
        $scope.cy = Math.round(svgP.y);


  }

  function moveit(event)
  {

     if (!isDrag) return;
     var status = "Dragging with X="+event.pageX+" Y="+event.pageY;

    $timeout (function(){$scope.status = status; recompute(event.pageX, event.pageY)});
  }

The relevant SVG:

<svg   id = "zsvg" class="zonelayer" viewBox="0 0 400 200" width="400" height="300" >
  <circle id="c1" ng-attr-cx="{{cx}}" ng-attr-cy="{{cy}}" r="20" stroke="blue" fill="purple"  />
</svg>

Upvotes: 0

Views: 597

Answers (1)

Paul LeBeau
Paul LeBeau

Reputation: 101860

Firstly, you would normally use clientX and clientY rather than pageX and pageY.

Secondly, the Ionic(?) zoomTo() function you are using is applying a 3D transform to the container div. Ie.

style="transform: translate3d(-791.5px, -173px, 0px) scale(2);"

I don't expect getScreenCTM() handles 3D transforms. Even ones that are effectively 2D because they do nothing in the Z axis.

You'll need to either:

  1. do the zoom a different way. IOW handle it yourself so you can do it in a getScreenCTM()-friendly way. Or multiply the zoom factor in directly. or
  2. find a way of getting the details of the transform that Ionic has applied and updating your transformed mouse coords appropriately.

Update:

The definition of getScreenCTM() has changed in SVG 2. In SVG 1.1 it was fairly loosely defined. In SVG 2 the definition has been updated to explicitly define how the result is calculated. Although it does not specify how 3D transforms on ancestor elements should be handled.

I have experimented a little on Chrome and Firefox. It appears that Chrome has implemented the SVG2 definition, but it has a bug. It is not returning the correct transform matrix. However Firefox has not yet been updated. It is not including any transforms on ancestor elements.

I now believe the bug in Chrome is the reason your sample is not working there. However if you want to be cross-browser, my advice to handle zoom yourself - and adjust the transform (or coords) - still holds.

Upvotes: 2

Related Questions