如何使用Snap.SVG为单个SVG元素做出唯一响应

How to make unique responses for individual SVG elements with Snap.svg?

本文关键字:SVG 唯一 响应 元素 单个 何使用 Snap      更新时间:2023-09-26

我已经找了几个小时了,但没有任何东西(包括相关的StackOverflow线程)能让我更接近。这个问题看起来很简单,但它显然不是基于缺乏我能找到的信息。

我正在尝试用Snap.svg制作一架交互式钢琴,在那里你可以点击每个键,它就会播放各自的音符。到目前为止,我已经尝试了两种方法:

方法1:一个简单的FOR循环,它生成所有rect并添加一个事件侦听器。

<script>
  window.onload=init();
  var S=Snap(500,100);
  var w=15;  var h=100;
  function init() {
    for (i=0;i<10;i++) {
      S.rect(i*w,0,w,h).attr{(id:i)}.click(console.log(this.id));
    }
  }
</script>

"未定义"是我单击时得到的内容。

方法2:我尝试将SVG元素封装在JS对象中。

<script>
  window.onload=init();
  S=Snap(500,100);
  var h=15;  var w=100;
  var notes=['A','B','C',...];
  function Key(id, x, note) {
    this.id=id;
    this.x=x;
    this.note=note;
    this.drawSvg=function() {
            var keyImg=S.rect(x,0,w,h);
            keyImg.attr({ ... });
            keyImg.click(callback);
            return keyImg;
          }
    var callback=function() {
           console.log(this.note, "clicked!");
           return 0;
         } 
  }//Key() 
  function init() {
    var keys=[];
    for (i=0;i<10;i++) {
       keys[i]=new Key(i,i*w,notes[i%12]);
     }
    for (j=0;j<keys.length;j++) {
       keys[j].drawSvg();
     }
  }
</script>

这几乎奏效了。它画得很好,但我点击的每一个键都会被"未定义"点击。

我知道这是因为callback()中的"this"与Key构造函数中的"this"不同。

所以我的问题是:我如何让callback()函数"知道"它是从哪个对象调用的,以便在回调中使用该对象自己的属性?

感谢您的帮助。谢谢

这是一种包含2个方法的方法。在第一个例子中,括号中的attr错误。

此外,单击处理程序必须将函数作为arg,这样"this"才是正确的。所以。。。

jsfiddle

编辑:我添加了两种可以从不同角度使用的方法。

 r.data('key', new Key( i )); 

将对象作为数据元素与捕捉对象相关联。

 r.click( clickHandler.bind(r, key2));

将对象绑定到处理程序,以便将其作为arg传递。

这是全部。根据哪种方法效果最好,您可以将其缩短一点。

var w=15;  var h=100;
function altKey( id ) {
   this.id='anotherkeymethod ' + id;
};
function Key(id ) {
    this.id='key' + id;
};
function init() {
    var r, key2;
    for (i=0;i<10;i++)      {
        key2 = new altKey( i );
        r = S.rect(i*w,0,w,h)
             .attr({ id:i, fill: 'blue' });
        r.data('key', new Key( i ));          // Method 1
        r.click( clickHandler.bind(r, key2)); // Method 2
    }
  }
function clickHandler( myKeyEl ) {
    console.log(this.id, this.data('key'), myKeyEl);
};
init();