Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript SVG旋转未按预期工作_Javascript_Svg - Fatal编程技术网

JavaScript SVG旋转未按预期工作

JavaScript SVG旋转未按预期工作,javascript,svg,Javascript,Svg,我正在编写一个SVG操作库,我正在尝试实现转换。经过一点阅读,我想我应该深入底层的SVGMatrix对象,并使用它的转换方法。到目前为止,我已经实现了translate和flip方法,并且按照我的预期工作,但是我无法让旋转方法工作。嗯,不完全是这样,rotate可以工作,我可以看到我正在测试的对象(rect)在我的屏幕上疯狂地旋转。我似乎无法使用的是rotateFromVector方法。到目前为止,我已经尝试将它链接到rotate方法之后,但它没有按预期工作(我希望rect围绕其“中心”旋转)

我正在编写一个SVG操作库,我正在尝试实现转换。经过一点阅读,我想我应该深入底层的
SVGMatrix
对象,并使用它的转换方法。到目前为止,我已经实现了
translate
flip
方法,并且按照我的预期工作,但是我无法让旋转方法工作。嗯,不完全是这样,
rotate
可以工作,我可以看到我正在测试的对象(
rect
)在我的屏幕上疯狂地旋转。我似乎无法使用的是
rotateFromVector
方法。到目前为止,我已经尝试将它链接到
rotate
方法之后,但它没有按预期工作(我希望
rect
围绕其“中心”旋转)

我猜可能传递给
rotateFromVector
cx
cy
值必须以某种方式预先计算,我不能只传递原始值

如果有人能看看下面的代码,让我知道我遗漏了什么,我将不胜感激。JavaScript是从TypeScript编译而来的,以防有人想知道为什么会是这样

var Matrix = (function () {
    function Matrix(element) {
        this.ctm = element.getScreenCTM();
        this.element = element;
    }
    Matrix.prototype.apply = function () {
        this.element.setAttribute("transform", "matrix(" + this.ctm.a + "," + this.ctm.b + "," + this.ctm.c + "," + this.ctm.d + "," + this.ctm.e + "," + this.ctm.f + ")");
    };
    Matrix.prototype.flip = function (x, y) {
        if (x) {
            this.ctm = this.ctm.flipX();
        }
        if (y) {
            this.ctm = this.ctm.flipY();
        }
        this.apply();
    };
    Matrix.prototype.rotate = function (a, cx, cy) {
        if (a === void 0) { a = 0; }
        this.ctm = this.ctm.rotate(a);
        if (cx && cy) {
            this.ctm = this.ctm.rotateFromVector(cx, cy);
        }
        this.apply();
    };
    Matrix.prototype.translate = function (x, y) {
        if (x === void 0) { x = 0; }
        if (y === void 0) { y = 0; }
        this.ctm = this.ctm.translate(x, y);
        this.apply();
    };
    return Matrix;
})();
rotateFromVector()
不是您想要在这里使用的。它没有做你认为它是。这是为了另一个目的

如果要围绕点(cx、cy)旋转,则需要执行以下步骤:

  • 将原点移动到cx,cy-即平移(cx,cy)
  • 轮换
  • 将原点移回原来的位置-即平移(-cx,-cy)
因此,旋转函数应为:

Matrix.prototype.rotate = function (a, cx, cy) {
    if (a === void 0) { a = 0; }
    if (cx && cy) {
        this.ctm = this.ctm.translate(cx, cy);
    }
    this.ctm = this.ctm.rotate(a);
    if (cx && cy) {
        this.ctm = this.ctm.translate(-cx, -cy);
    }
    this.apply();
};
此外,您应该能够稍微优化一下
apply()
函数

Matrix.prototype.apply = function () {
    var svg = this.element.ownerSVGElement;
    var tf = svg.createSVGTransformFromMatrix(m);
    this.element.transform.baseVal.appendItem(tf);
};
这应该比使用字符串化版本的矩阵设置属性更有效。

rotateFromVector()
不是您想要在这里使用的。它没有做你认为它是。这是为了另一个目的

如果要围绕点(cx、cy)旋转,则需要执行以下步骤:

  • 将原点移动到cx,cy-即平移(cx,cy)
  • 轮换
  • 将原点移回原来的位置-即平移(-cx,-cy)
因此,旋转函数应为:

Matrix.prototype.rotate = function (a, cx, cy) {
    if (a === void 0) { a = 0; }
    if (cx && cy) {
        this.ctm = this.ctm.translate(cx, cy);
    }
    this.ctm = this.ctm.rotate(a);
    if (cx && cy) {
        this.ctm = this.ctm.translate(-cx, -cy);
    }
    this.apply();
};
此外,您应该能够稍微优化一下
apply()
函数

Matrix.prototype.apply = function () {
    var svg = this.element.ownerSVGElement;
    var tf = svg.createSVGTransformFromMatrix(m);
    this.element.transform.baseVal.appendItem(tf);
};

这应该比使用字符串化版本的矩阵设置属性更有效。

我最终找到了答案。结果是我不能直接通过一个度数,它必须先转换成弧度,然后再进行计算。下面是正确的代码:

var MatrixInfo = (function () {
    function MatrixInfo(a, b, c, d, e, f) {
        if (a === void 0) { a = 1; }
        if (b === void 0) { b = 0; }
        if (c === void 0) { c = 0; }
        if (d === void 0) { d = 1; }
        if (e === void 0) { e = 0; }
        if (f === void 0) { f = 0; }
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;
        this.e = e;
        this.f = f;
    }
    MatrixInfo.parse = function (element) {
        var ctm = element.getScreenCTM();
        return new MatrixInfo(ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f);
    };
    return MatrixInfo;
})();

var SvgBase = (function () {
    function SvgBase() {
    }
    SvgBase.prototype.attr = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i - 0] = arguments[_i];
        }
        if (typeof (args[0]) === "object") {
            for (var _a = 0, _b = Object.keys(args[0]); _a < _b.length; _a++) {
                var k = _b[_a];
                this.attr(k, args[0][k]);
            }
            return this;
        }
        if (args[1] === null) {
            this.element.removeAttribute(args[0]);
            return this;
        }
        if (!args[1]) {
            return this.element.getAttribute(args[0]);
        }
        if (args[0] === "href") {
            this.element.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#" + args[1]);
        }
        else {
            this.element.setAttribute(args[0], args[1]);
        }
        return this;
    };
    return SvgBase;
})();

var SvgMatrixBuilder = (function (_super) {
    __extends(SvgMatrixBuilder, _super);
    function SvgMatrixBuilder() {
        _super.call(this);
        this.mI = new MatrixInfo();
    }
    SvgMatrixBuilder.prototype.apply = function () {
        this.attr("transform", "matrix(" + this.mI.a + "," + this.mI.b + "," + this.mI.c + "," + this.mI.d + "," + this.mI.e + "," + this.mI.f + ")");
    };
    SvgMatrixBuilder.prototype.refresh = function (element) {
        this.element = element;
        return this;
    };
    SvgMatrixBuilder.prototype.rotate = function (a, cx, cy) {
        var radian = .017453292519943295 * a, cos = Math.cos(radian), sin = Math.sin(radian);
        if (!cx && !cy) {
            var eI = ElementInfo.parse(this.element);
            cx = eI.width / 2 + eI.iX;
            cy = eI.height / 2 + eI.iY;
        }
        this.mI.a = cos;
        this.mI.b = sin;
        this.mI.c = -sin;
        this.mI.d = cos;
        this.mI.e = -cx * cos + cy * sin + cx;
        this.mI.f = -cx * sin - cy * cos + cy;
        this.apply();
    };
    SvgMatrixBuilder.prototype.translate = function (tx, ty) {
        if (tx === void 0) { tx = 0; }
        if (ty === void 0) { ty = 0; }
        this.mI.e = tx;
        this.mI.f = ty;
        this.apply();
    };
    return SvgMatrixBuilder;
})(SvgBase);
var MatrixInfo=(函数(){
函数矩阵信息(a,b,c,d,e,f){
如果(a==void 0){a=1;}
如果(b==void 0){b=0;}
如果(c==void 0){c=0;}
如果(d==void 0){d=1;}
如果(e==void 0){e=0;}
如果(f==void 0){f=0;}
这个a=a;
这个.b=b;
这个.c=c;
这个。d=d;
这个。e=e;
这个。f=f;
}
MatrixInfo.parse=函数(元素){
var ctm=element.getScreenCTM();
返回新的矩阵信息(ctm.a、ctm.b、ctm.c、ctm.d、ctm.e、ctm.f);
};
返回MatrixInfo;
})();
var SvgBase=(函数(){
函数SvgBase(){
}
SvgBase.prototype.attr=函数(){
var args=[];
对于(var_i=0;_i
最后我终于弄明白了。结果是我不能直接通过一个度数,它必须先转换成弧度,然后再进行计算。下面是正确的代码:

var MatrixInfo = (function () {
    function MatrixInfo(a, b, c, d, e, f) {
        if (a === void 0) { a = 1; }
        if (b === void 0) { b = 0; }
        if (c === void 0) { c = 0; }
        if (d === void 0) { d = 1; }
        if (e === void 0) { e = 0; }
        if (f === void 0) { f = 0; }
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;
        this.e = e;
        this.f = f;
    }
    MatrixInfo.parse = function (element) {
        var ctm = element.getScreenCTM();
        return new MatrixInfo(ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f);
    };
    return MatrixInfo;
})();

var SvgBase = (function () {
    function SvgBase() {
    }
    SvgBase.prototype.attr = function () {
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i - 0] = arguments[_i];
        }
        if (typeof (args[0]) === "object") {
            for (var _a = 0, _b = Object.keys(args[0]); _a < _b.length; _a++) {
                var k = _b[_a];
                this.attr(k, args[0][k]);
            }
            return this;
        }
        if (args[1] === null) {
            this.element.removeAttribute(args[0]);
            return this;
        }
        if (!args[1]) {
            return this.element.getAttribute(args[0]);
        }
        if (args[0] === "href") {
            this.element.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#" + args[1]);
        }
        else {
            this.element.setAttribute(args[0], args[1]);
        }
        return this;
    };
    return SvgBase;
})();

var SvgMatrixBuilder = (function (_super) {
    __extends(SvgMatrixBuilder, _super);
    function SvgMatrixBuilder() {
        _super.call(this);
        this.mI = new MatrixInfo();
    }
    SvgMatrixBuilder.prototype.apply = function () {
        this.attr("transform", "matrix(" + this.mI.a + "," + this.mI.b + "," + this.mI.c + "," + this.mI.d + "," + this.mI.e + "," + this.mI.f + ")");
    };
    SvgMatrixBuilder.prototype.refresh = function (element) {
        this.element = element;
        return this;
    };
    SvgMatrixBuilder.prototype.rotate = function (a, cx, cy) {
        var radian = .017453292519943295 * a, cos = Math.cos(radian), sin = Math.sin(radian);
        if (!cx && !cy) {
            var eI = ElementInfo.parse(this.element);
            cx = eI.width / 2 + eI.iX;
            cy = eI.height / 2 + eI.iY;
        }
        this.mI.a = cos;
        this.mI.b = sin;
        this.mI.c = -sin;
        this.mI.d = cos;
        this.mI.e = -cx * cos + cy * sin + cx;
        this.mI.f = -cx * sin - cy * cos + cy;
        this.apply();
    };
    SvgMatrixBuilder.prototype.translate = function (tx, ty) {
        if (tx === void 0) { tx = 0; }
        if (ty === void 0) { ty = 0; }
        this.mI.e = tx;
        this.mI.f = ty;
        this.apply();
    };
    return SvgMatrixBuilder;
})(SvgBase);
var MatrixInfo=(函数(){
函数矩阵信息(a,b,c,d,e,f){
如果(a==void 0){a=1;}
如果