在 svg (Raphael.js) 上调整大小和旋转会产生跳跃

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

本文关键字:旋转 跳跃 调整 svg Raphael js      更新时间:2023-09-26

我已经研究这个问题好几天了。 我正在尝试为 svgs 实现一个"自由转换"工具。 类似于Raphael.FreeTransform或如何在MS Word中移动/旋转/缩放图像。 (是的,我知道有图书馆)以下jSFiddle显示我的问题:https://jsfiddle.net/hLjvrep7/12/

jsFiddle 中有 5 个函数:rotate-t. shrink-t、grow-t、shrink、grow。 后缀为"-t"的函数也应用当前旋转变换。 例如:

成长-T

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

成长

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

旋转 svg 后,再缩放。 如果您尝试再次旋转 svg(缩放后),svg 会跳跃。 要看到这一点,请转到小提琴顶部:

  1. 点击旋转-t 两次。 Svg 应从矩形原点总共旋转 30 度。
  2. 点击增长(不是增长-t)两次。 请注意,svg 的左上角位置保持不变
  3. 点击旋转-t 一次。 请注意,svg 跳到不同的位置,然后旋转。
  4. 请注意,随后点击 rotate-t 将继续围绕原点旋转图像(这是我第一次单击 rotate-t 时想要的)

我有一个解决方案是在更改高度和宽度时应用当前的旋转变换。 这解决了我之前的问题,但引入了另一个问题。 要查看这方面的示例,请转到小提琴,然后:

  1. 点击旋转-t 两次。
  2. 打几次嘶吼。 请注意,svg 会增长,但矩形的左上角位置会移动。这对我来说是个问题。 我希望 svg 在没有左上角移动的情况下增长。

使用 jsFiddle 的注意事项:

旋转-t、

增长-t、收缩-t 的任何组合都将表现出理想的旋转行为(关于原点,无跳跃)。 但这也表明了不希望的增长和收缩(当 svg 处于角度时左上角位置移动)。

任何组合 pf rotate-t、增长、收缩都将表现出理想的缩放行为(svg 的左上角不会移动)。 但这也证明了不需要的旋转属性(在不同的旋转和缩放后会跳来跳去)。

底线:我希望svg能够围绕原点旋转。 然后放大图像,而左上角的位置保持不变。 然后再次旋转 svg,围绕原点旋转,没有任何跳跃。

我知道变换函数如何影响 svg 的局部坐标系。 我倾向于使用 rotate-t、增长、收缩组合,并简单地应用一些 x-y 偏移来消除"跳跃"效果。 我想一定有某种偏移可以应用以避免在旋转或缩放过程中跳跃或移动,但我不清楚如何计算这种偏移。 任何帮助将不胜感激。

请不要犹豫,再问问题了。 就像我说的,我已经深入研究了好几天了。 显然,我并不完全理解,但对正在发生的事情有些亲密,并乐于更详细地解释任何事情。

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();
            }
        }
    };