这不是其他问题的重复。
我发现这篇文章讨论了使用XML围绕中心旋转的方法,我尝试使用原生JavaScript实现类似的方法,如
我成功的方法在下面的片段中,但发现矩形没有完全围绕其中心旋转,并且有些移动。矩形应该在第一次点击后开始旋转,在第二次点击时停止旋转,这个功能我已经实现了。
你有什么想法,为什么物品会移动,如何解决这个问题。
rotate(45, 60, 60)
,但这对我来说不起作用。我成功的方法在下面的片段中,但发现矩形没有完全围绕其中心旋转,并且有些移动。矩形应该在第一次点击后开始旋转,在第二次点击时停止旋转,这个功能我已经实现了。
你有什么想法,为什么物品会移动,如何解决这个问题。
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
的中心点时,每个边上都会有额外的4像素,这意味着宽度和高度都多出8像素,x和y方向都向右下移动了4像素,我在这里找到了相关信息。但是无论是设置self.setAttribute("display", "block");
还是self.style.display = "block";
,都没有解决我的问题。
所以,现在我有两种选择:
- 找到解决边缘多出4像素的办法(即x和y方向各移动4像素,宽度和高度各多出8像素);
或者使用以下方式计算中心点:
self.Pc = { x: self.x.baseVal.value + self.width.baseVal.value/2, y: self.y.baseVal.value + self.height.baseVal.value/2 };
第二个选项(另一种计算中心点的方法)对我来说很好用,因为这是一个矩形,但如果使用其他形状,则不是相同的方式,我将寻找通用的方法来找到中心点,无论对象是什么,即寻找第一种选项,即解决self.getBoundingClientRect()
问题。
Object.defineProperty(myRect.prototype ...
,因为您可以直接创建类的成员方法,这就是所谓的prototype
。 - philippObject.defineProperty...
,我使用它是因为我更喜欢将所有声明放在主class { }
之外。 - Hasan A Yousef