我甚至可以在广场上添加收听功能,提醒我这是我的名字'点击后。
我的问题是:
我需要执行animate
功能,而不是仅仅发出警报,以便每个项目在点击它时开始移动
var NS="http://www.w3.org/2000/svg";
var SVG=function(h,w){
var svg=document.createElementNS(NS,"svg");
svg.width=w;
svg.height=h;
return svg;
}
var svg=SVG(1200,1500);
document.body.appendChild(svg);
var rect=function(x,y,h,w,fill,name){
var SVGObj= document.createElementNS(NS,"rect");
SVGObj.x.baseVal.value=x;
SVGObj.y.baseVal.value=y;
SVGObj.width.baseVal.value=w;
SVGObj.height.baseVal.value=h;
SVGObj.setAttribute("height",h);
SVGObj.style.fill=fill;
SVGObj["my-name"] = name;
SVGObj.name = name;
return SVGObj;
}
for (var i = 0; i < 100; i++) {
var x = Math.random() * 500,
y = Math.random() * 300;
var r= rect(x,y,10,10,'#'+Math.round(0xffffff * Math.random()).toString(16),'this is my name');
r.addEventListener('click', ()=>alert(r.name)); // or r["my-name"]
svg.appendChild(r);
}
var animate=function(obj){
obj.x.baseVal.value+=1;
obj.y.baseVal.value+=1;
}
&#13;
答案 0 :(得分:1)
为了使这项工作正常,你应该将事件传递给回调函数,然后使用event.target
来获取被点击的元素。
您的初始代码不起作用的原因是您传递了r
变量,该变量未包含在任何函数范围内,因此当您实际单击矩形时r
始终等于最后添加的元素。
为了避免将来发生这种情况,您应该阅读closures和hoisting
var NS="http://www.w3.org/2000/svg";
var SVG=function(h,w){
var svg=document.createElementNS(NS,"svg");
svg.width=w;
svg.height=h;
return svg;
}
var svg=SVG(1200,1500);
document.body.appendChild(svg);
var rect=function(x,y,h,w,fill,name){
var SVGObj= document.createElementNS(NS,"rect");
SVGObj.x.baseVal.value=x;
SVGObj.y.baseVal.value=y;
SVGObj.width.baseVal.value=w;
SVGObj.height.baseVal.value=h;
SVGObj.setAttribute("height",h);
SVGObj.style.fill=fill;
SVGObj["my-name"] = name;
SVGObj.name = name;
return SVGObj;
}
for (var i = 0; i < 100; i++) {
var x = Math.random() * 500,
y = Math.random() * 300;
var r= rect(x,y,10,10,'#'+Math.round(0xffffff * Math.random()).toString(16),'this is my name');
r.addEventListener('click', (e)=>animate(e)); // or r["my-name"]
svg.appendChild(r);
}
var animate=function(e){
e.target.x.baseVal.value+=1;
e.target.y.baseVal.value+=1;
}
答案 1 :(得分:1)
您应该在animate(e.target)
内拨打r.addEventListener('click',(e)=>...)
,如下所示。您应该将e.target
作为参数传递给函数,否则您将自行传递事件,并且事件没有x
和y
属性。
var NS="http://www.w3.org/2000/svg";
var SVG=function(h,w){
var svg=document.createElementNS(NS,"svg");
svg.width=w;
svg.height=h;
return svg;
}
var svg=SVG(1200,1500);
document.body.appendChild(svg);
var rect=function(x,y,h,w,fill,name){
var SVGObj= document.createElementNS(NS,"rect");
SVGObj.x.baseVal.value=x;
SVGObj.y.baseVal.value=y;
SVGObj.width.baseVal.value=w;
SVGObj.height.baseVal.value=h;
SVGObj.setAttribute("height",h);
SVGObj.style.fill=fill;
SVGObj["my-name"] = name;
SVGObj.name = name;
return SVGObj;
}
for (var i = 0; i < 100; i++) {
var x = Math.random() * 500,
y = Math.random() * 300;
var r= rect(x,y,10,10,'#'+Math.round(0xffffff * Math.random()).toString(16),'this is my name');
r.addEventListener('click', function(e){
console.log(e.target.name);
console.log(e.target.x.baseVal.value);
animate(e.target); // Pass the event's target as argument
console.log(e.target.x.baseVal.value);
});
svg.appendChild(r);
}
var animate=function(obj){
obj.x.baseVal.value+=1;
obj.y.baseVal.value+=1;
}
我还添加了一些console.log()
语句来显示动画对象的结果,因为有时很难看到1px移动:
答案 2 :(得分:1)
感谢@Maksyum和@Angelos,我发现以下方法可以正常工作,因此我使用e.target
重新构建模块而不是this
。在为我的案例标记最合适的选项之前,我会进一步评估这两个选项,如果有人对此方法感兴趣或有任何意见,请在此处提及。
var NS="http://www.w3.org/2000/svg";
var SVG=function(h,w){
var svg=document.createElementNS(NS,"svg");
svg.width=w;
svg.height=h;
return svg;
}
var svg=SVG(1200,1500);
document.body.appendChild(svg);
function myRect(x,y,h,w,fill,name){
this.name=name;
this.SVGObj= document.createElementNS(NS,"rect");
this.SVGObj.x.baseVal.value=x;
this.SVGObj.y.baseVal.value=y;
this.SVGObj.width.baseVal.value=w;
this.SVGObj.height.baseVal.value=h;
this.SVGObj.style.fill=fill;
this.SVGObj.addEventListener("click",this,false);
this.handleEvent= function(evt){
switch (evt.type){
case "click":
// alert(this.name); // this.animate();
var move = setInterval(()=>this.animate(),100);
break;
}
}
/* Use either this.animate or myRect.prototype.animate for the animation, As I prefer using the prototype function the `this` method here is inactive
this.animate=function(){
this.SVGObj.x.baseVal.value+=1;
this.SVGObj.y.baseVal.value+=1;
}
*/
return this.SVGObj;
}
myRect.prototype.animate = function() {
this.SVGObj.x.baseVal.value+=1;
this.SVGObj.y.baseVal.value+=1;
};
for (var i = 0; i < 100; i++) {
var x = Math.random() * 500,
y = Math.random() * 300;
var r= new myRect(x,y,10,10,'#'+Math.round(0xffffff * Math.random()).toString(16),'this is my name');
svg.appendChild(r);
}
&#13;
<强>更新强> 我发现使用ES6(ECMAScript 2015)中提供的JavaScript类可以获得相同的内容,下面是使用类的完整代码:
var NS="http://www.w3.org/2000/svg";
var SVG=function(h,w){
var svg=document.createElementNS(NS,"svg");
svg.width=w;
svg.height=h;
return svg;
}
var svg=SVG(1200,1500);
document.body.appendChild(svg);
class myRect {
constructor(x,y,h,w,fill,name) {
this.name=name;
this.SVGObj= 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.addEventListener("click",this,false);
}
/* Use either get or Object.defineProperty of a prototype to make the getter / return of the shape/node, As i prefer using the prototype function the `get` method here is inactive
get node() {
return this.SVGObj;
}
*/
}
Object.defineProperty(myRect.prototype, "node", {
get: function() {
return this.SVGObj;
}
/* you can use this for making setter also if required, like below
,
set: function(value) {
name = value;
}
*/
});
/* OR another way to define getter / setter using Object property:
var pattern = {
get: function () {
return this.SVGObj;
},
set: function () {
name = value;
}
};
Object.defineProperty(myRect.prototype, 'node', pattern); // myRect.prototype === this
*/
myRect.prototype.handleEvent= function(evt){
self = this.SVGObj;
switch (evt.type){
case "click":
// alert(this.name); // this.animate();
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);
self.parentNode.removeChild(self);
}
break;
default:
break;
}
}
myRect.prototype.step = function(x,y) {
return svg.createSVGTransformFromMatrix(svg.createSVGMatrix().translate(x,y));
}
myRect.prototype.animate = function() {
self = this.SVGObj;
self.transform.baseVal.appendItem(this.step(1,1));
// Or the below can be used instead of the custom function `step`
// self.x.baseVal.value+=1;
// self.y.baseVal.value+=1;
};
for (var i = 0; i < 100; i++) {
var x = Math.random() * 500,
y = Math.random() * 300;
var r= new myRect(x,y,10,10,'#'+Math.round(0xffffff * Math.random()).toString(16),'this is my name');
svg.appendChild(r.node);
}
&#13;