【发布时间】:2016-07-19 07:23:49
【问题描述】:
这不是另一个问题的重复。
我发现 this 谈论使用 XML 的中心旋转,尝试使用像 rotate(45, 60, 60) 这样的 vanilla JavaScript 来实现相同的功能,但对我不起作用。
与我一起使用的方法是下面 sn-p 中的方法,但发现矩形没有完全围绕其中心旋转,并且它正在移动一点,矩形应该在第一次点击时开始旋转,并且应该停止第二次点击,我觉得很好。
任何想法,为什么项目正在移动,以及如何修复它。
var NS="http://www.w3.org/2000/svg";
var SVG=function(el){
return document.createElementNS(NS,el);
}
var svg = SVG("svg");
svg.width='100%';
svg.height='100%';
document.body.appendChild(svg);
class myRect {
constructor(x,y,h,w,fill) {
this.SVGObj= SVG('rect'); // document.createElementNS(NS,"rect");
self = this.SVGObj;
self.x.baseVal.value=x;
self.y.baseVal.value=y;
self.width.baseVal.value=w;
self.height.baseVal.value=h;
self.style.fill=fill;
self.onclick="click(evt)";
self.addEventListener("click",this,false);
}
}
Object.defineProperty(myRect.prototype, "node", {
get: function(){ return this.SVGObj;}
});
Object.defineProperty(myRect.prototype, "CenterPoint", {
get: function(){
var self = this.SVGObj;
self.bbox = self.getBoundingClientRect(); // returned only after the item is drawn
self.Pc = {
x: self.bbox.left + self.bbox.width/2,
y: self.bbox.top + self.bbox.height/2
};
return self.Pc;
}
});
myRect.prototype.handleEvent= function(evt){
self = evt.target; // this returns the `rect` element
this.cntr = this.CenterPoint; // backup the origional center point Pc
this.r =5;
switch (evt.type){
case "click":
if (typeof self.moving == 'undefined' || self.moving == false) self.moving = true;
else self.moving = false;
if(self.moving == true){
self.move = setInterval(()=>this.animate(),100);
}
else{
clearInterval(self.move);
}
break;
default:
break;
}
}
myRect.prototype.step = function(x,y) {
return svg.createSVGTransformFromMatrix(svg.createSVGMatrix().translate(x,y));
}
myRect.prototype.rotate = function(r) {
return svg.createSVGTransformFromMatrix(svg.createSVGMatrix().rotate(r));
}
myRect.prototype.animate = function() {
self = this.SVGObj;
self.transform.baseVal.appendItem(this.step(this.cntr.x,this.cntr.y));
self.transform.baseVal.appendItem(this.rotate(this.r));
self.transform.baseVal.appendItem(this.step(-this.cntr.x,-this.cntr.y));
};
for (var i = 0; i < 10; i++) {
var x = Math.random() * 100,
y = Math.random() * 300;
var r= new myRect(x,y,10,10,'#'+Math.round(0xffffff * Math.random()).toString(16));
svg.appendChild(r.node);
}
更新
我发现问题在于使用self.getBoundingClientRect() 计算rect 的中心点,总是有4px extra in each side,这意味着宽度增加8px,高度增加8px,以及x 和y 被移动了 4 px,我发现 this 在谈论同样的事情,但设置 self.setAttribute("display", "block"); 或 self.style.display = "block"; 对我都不起作用。
所以,现在我有两种选择之一:
- 找到每边额外 4px 的解决方案(即 x 和 y 移动 4px,宽度和高度总共额外增加 8px),
-
或使用以下方法计算中点:
self.Pc = { x: self.x.baseVal.value + self.width.baseVal.value/2, y: self.y.baseVal.value + self.height.baseVal.value/2 };
第二个选项(计算中点的另一种方法对我来说很好,因为它是矩形,但如果使用其他形状,则方法不一样,我会寻找找到中点的通用方法-point 无论对象是什么,即寻找第一个选项,它正在解决self.getBoundingClientRect() 问题。
【问题讨论】:
-
这是一个经常被回答的事情……诀窍:平移对象,使旋转/缩放的中心位于原点,旋转,平移回来。所有这三个步骤都可以组合在一个变换矩阵中。
-
对了……写es6类的时候,不用这个
Object.defineProperty(myRect.prototype …,因为可以直接创建类的成员方法,翻译成这个prototype的东西是什么…… -
@philipp 我指的是您提供的链接,在我的问题本身中,它不是重复的,而且这种方式对我不起作用:(关于
Object.defineProperty...,我使用它是因为我更喜欢将我的所有声明都放在主class { }之外 -
@philipp 问题出在第三步,即当我翻译回来时,它不会回去!
标签: javascript svg