JavaScript SVG旋转没有按预期工作
JavaScript SVG rotation not working as expected
我正在编写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)旋转,那么您需要执行的步骤是:
- 将原点移动到x, cy - ie。翻译(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);
相关文章:
- 如何使用javascript操作SVG节点,使其在MS Edge中工作
- 异步加载的SVG过滤器feColorMatrix在Chrome中工作,而不是在Safari或Firefox中
- 对链接的 svg 进行动画处理不起作用;内联时工作正常
- SVG和Javascript在Chrome中无法“在线”工作
- 如何将悬停事件添加到 SVG 中的多个路径?并让它在IE9中工作
- SVG网格线在Google Chrome中缩放时模糊,但在Mozilla Firefox中工作正常
- createElementNS是否始终如一地离线工作?特别是使用 SVG 命名空间
- Snap.svg延迟的动画无法工作
- 让一个脉冲SVG在IE中工作
- 高库存滚动条没有'不能在svg foreignObject中工作
- 可点击的Svg与html内联不在Safari中工作,但独立工作
- 代码在Codepen中工作,而不是在浏览器中工作:JavaScript在鼠标滚轮上缩放SVG
- canvas不能与已经放置在body中的SVG一起工作
- JavaScript SVG世界地图库离线工作
- 鼠标处理重叠的SVG元素没有按预期工作
- 将SVG附加到DOM不工作-重新加载资产管道
- 触摸事件是否与SVG一起工作
- 不要让AngularJS和D3工作- SVG元素在那里,但没有生成图表
- 一些CSS样式不能在SVG上工作
- 用javascript创建SVG文本不能像预期的那样工作