tpdietz
tpdietz

Reputation: 1368

Resizing and rotation on svg (Raphael.js) creates jumping

I've been working on this problem for days. I am trying to implement a "free transform" tool for svgs. Similar to that of Raphael.FreeTransform or how you would move/rotate/scale images in MS Word. (Yes, I am aware there are libraries) The following jSFiddle displays my problem: https://jsfiddle.net/hLjvrep7/12/

There are 5 functions in the jsFiddle: rotate-t. shrink-t, grow-t, shrink, grow. The functions suffixed with '-t' also apply the current rotation transformation. e.g.:

grow-t

rect.attr({height : height * 1.25, width : width * 1.25}).transform('r' + degree);

grow

rect.attr({height : height * 1.25, width : width * 1.25});

Once an svg is rotated, then scaled. If you try to rotate the svg again (after scale), the svg jumps. To see this, go top the fiddle:

  1. Hit rotate-t twice. Svg should rotate a total of 30 degrees from the rectangles origin.
  2. Hit grow (not grow-t) twice. Note the top left position of the svg stays the same.
  3. Hit rotate-t once. Note the svg jumps to a different position, then rotates.
  4. Note hitting rotate-t subsequent times will continue to rotate the image around the origin (which is what I want the first time rotate-t is clicked)

One solution I had was to apply the current rotation transformation whenever changing the height and width. This fixes my previous problem, but introduces another problem. To see an example of this, go to the fiddle, and:

  1. Hit rotate-t twice.
  2. Hit grow-t a couple times. Notice the svg grows, but the top left position of the rectangle moves. That's a problem for me. I want the svg to grow without the top left corner to move.

Notes on using the jsFiddle:

Any combination of rotate-t, grow-t, shrink-t will exhibit the ideal rotation behavior (about the origin, no jumping). But this also demonstrates the undesired growing and shrinking (top left position moved when svg is on angle).

Any combination pf rotate-t, grow, shrink will exhibit the ideal scaling behavior (top left corner of svg doesn't move). But this also demonstrates the undesired rotation property (will jump around after different rotations and scales).

Bottom line: I want to be able to the svg rotate around the origin. Then grow the image, while the top left position remains the same. Then rotate the svg again, around the origin without any jumping.

I am aware the how the transform function impacts the local coordinate system of the svg. I'm leaning towards using rotate-t, grow, shrink combo and simply apply some x-y offsets to remove the "jumping" effect. I would imagine there must be some sort of offset I could apply to avoid jumping or shifting during rotation or scaling, but its not clear to me how to calculate such offsets. Any help would be appreciated.

Please don't hesitate to ask anymore questions. Like I said, I've been digging into this for days. Clearly, I don't understand it all, but am somewhat intimate with what's happening and happy to explain anything in more detail.

Upvotes: 0

Views: 403

Answers (1)

Ved
Ved

Reputation: 12093

My solutions for scale, rotate, move back and front etc:


   $scope.back = function () {
        if($scope.currentImage !==null) {
            if($scope.currentImage.prev!=undefined) {
                var bot =  $scope.currentImage.prev;
                $scope.currentImage.insertBefore(bot);
                ft.apply();

            }
        }
    };

    //Function for moving front
    $scope.front = function () {
        if($scope.currentImage !==null) {
            if($scope.currentImage.next!=undefined) {
                var top =  $scope.currentImage.next;
                if($scope.currentImage.next.node.localName == "image")
                    $scope.currentImage.insertAfter(top);
                ft.apply();

            }
        }
    };

//ZOOM
   $scope.zoomIn = function () {
        if ($scope.currentImage!= null) {
            var ft = paper.freeTransform($scope.currentImage);
            if(ft.attrs.scale.y<4) {
                $scope.currentImage.toFront();
                ft.attrs.scale.y = ft.attrs.scale.y  *(1.1);
                ft.attrs.scale.x = ft.attrs.scale.x  *(1.1);
                ft.apply();
                ft.updateHandles();

            }

        }
    };

Upvotes: 1

Related Questions