为 Stage click 设置监听器

Set listener for Stage click

警告:在 运行 片段之前调低音量!

我希望能够在舞台上点击添加一个'module'形状。但我发现单击 'module' 形状本身会创建另一个形状,这意味着 stage.click 侦听器在不应该被触发的时候被触发。

如何才能让 stage.click 侦听器在我单击形状时不会错误触发?

var width = window.innerWidth;
var height = window.innerHeight;

var rectButtonClicked  = false;

var stage = new Konva.Stage({
  container: 'container',
  width: width,
  height: height
});

var layer = new Konva.Layer();

var group = new Konva.Group({
  draggable: true
});

stage.on('contentClick', function() {
  createModule();
});

function createModule() {

  var mouseX = stage.getPointerPosition().x;
  var mouseY = stage.getPointerPosition().y;

  var rect = new Konva.Rect({ //module rect
    x: mouseX,
    y: mouseY,
    width: 100,
    height: 50,
    cornerRadius: 5,
    fill: '#BEDBDD',
    stroke: '#807C7B',
    strokeWidth: 2,
    draggable: true
  });
  group.add(rect);

    var buttonRect = new Konva.Rect({ //button
    x: mouseX+80,
    y: mouseY+20,
    width: 10,
    height: 10,
    cornerRadius: 1,
    fill: 'blue',
    stroke: '#807C7B',
    strokeWidth: 1,
  });
  group.add(buttonRect)

  var text = new Konva.Text({  //text on module
    x: mouseX + 20,
    y: mouseY + 20,
    //fontFamily: 'Calibri',
    fontSize: 16,
    text: 'OSC',
    fill: 'black'
  });
  group.add(text);

  var randomFreq = getRandomInt();
  var osc = new Tone.Oscillator(randomFreq, "sawtooth");
  layer.add(group);
  stage.add(layer);

  buttonRect.on('click', function() {
    rectButtonClicked = !rectButtonClicked;
    if(rectButtonClicked){    
    osc.toMaster().start();
    this.setFill('red');
    }  else {
    osc.stop();
    this.setFill('blue');
    }  
});
}

function getRandomInt() {
  min = Math.ceil(100);
  max = Math.floor(1000);
  return Math.floor(Math.random() * (max - min)) + min;
}

var width = window.innerWidth;
var height = window.innerHeight;

//var drag = false;
var rectButtonClicked  = false;

var stage = new Konva.Stage({
  container: 'container',
  width: width,
  height: height
});

var layer = new Konva.Layer();

var group = new Konva.Group({
  draggable: true
});

stage.on('contentClick', function() {
  createModule();
});

function createModule() {

  var mouseX = stage.getPointerPosition().x;
  var mouseY = stage.getPointerPosition().y;

  var rect = new Konva.Rect({ //module rect
    x: mouseX,
    y: mouseY,
    width: 100,
    height: 50,
    cornerRadius: 5,
    fill: '#BEDBDD',
    stroke: '#807C7B',
    strokeWidth: 2,
    draggable: true
  });
  group.add(rect);
  
    var buttonRect = new Konva.Rect({ //button
    x: mouseX+80,
    y: mouseY+20,
    width: 10,
    height: 10,
    cornerRadius: 1,
    fill: 'blue',
    stroke: '#807C7B',
    strokeWidth: 1,
  });
  group.add(buttonRect)
  
  var text = new Konva.Text({  //text on module
    x: mouseX + 20,
    y: mouseY + 20,
    //fontFamily: 'Calibri',
    fontSize: 16,
    text: 'OSC',
    fill: 'black'
  });
  group.add(text);
  
  var randomFreq = getRandomInt();
  var osc = new Tone.Oscillator(randomFreq, "sawtooth");
  layer.add(group);
  stage.add(layer);
  
  buttonRect.on('click', function() {
    rectButtonClicked = !rectButtonClicked;
    if(rectButtonClicked){    
    osc.toMaster().start();
    this.setFill('red');
    }  else {
    osc.stop();
    this.setFill('blue');
    }  
});
}

function getRandomInt() {
  min = Math.ceil(100);
  max = Math.floor(1000);
  return Math.floor(Math.random() * (max - min)) + min;
}
<script src="https://tonejs.github.io/build/Tone.min.js"></script>
<script src="https://cdn.rawgit.com/konvajs/konva/1.7.6/konva.min.js"></script>
<div id="container"></div>

stage.contentClick() 侦听器是一种特殊情况,可在您希望舞台侦听舞台内容上的事件时使用。但是,cancelBubble() 函数不会阻止从点击形状到 stage.contentClick() 侦听器的事件冒泡。

为了获得您想要的效果,即给人一种在舞台上发生了点击的印象,您需要添加一个填充舞台的矩形并监听该矩形而不是舞台上的事件。

下面是一个工作示例。我特意添加的红色背景让你知道舞台上方还有其他东西。要删除它,请移除 clickRect 上的填充颜色。

我还修复了您的按钮,以便将内容正确分组并拖到一起。您几乎是正确的,但您需要在 createModule() 函数中创建组。你可以看到我还使组元素 dragabble = false 来完成这个过程。

我添加了几个控制台写入以显示事件何时触发。

[另外当我打开tone for tone时我也被吓了一跳]

var width = window.innerWidth;
var height = window.innerHeight;

//var drag = false;
var rectButtonClicked  = false;

var stage = new Konva.Stage({
  container: 'container',
  width: width,
  height: height
});

var layer = new Konva.Layer();
stage.add(layer);

var clickRect =  new Konva.Rect({ 
  x:0,
  y:0,
  width: width,
  height: height,
  fill: 'red',
  stroke: '#807C7B',
  strokeWidth: 2,
  listening: 'true'  
})
layer.add(clickRect);

clickRect.on('click', function() {
  console.log('Stage click');
  createModule();
});

function createModule() {
  var group = new Konva.Group({ // move group create into createModule
    draggable: true  // we will make the elements not draggable - we drag the group
  });

  var mouseX = stage.getPointerPosition().x;
  var mouseY = stage.getPointerPosition().y;

  var rect = new Konva.Rect({ //module rect
    x: mouseX,
    y: mouseY,
    width: 100,
    height: 50,
    cornerRadius: 5,
    fill: '#BEDBDD',
    stroke: '#807C7B',
    strokeWidth: 2,
    draggable: false // make the element not draggable - we drag the group
  });
  group.add(rect);
  
  rect.on('click', function(evt){
  console.log('Clicked on button');
  })
  
    var buttonRect = new Konva.Rect({ //button
    x: mouseX+80,
    y: mouseY+20,
    width: 10,
    height: 10,
    cornerRadius: 1,
    fill: 'blue',
    stroke: '#807C7B',
    strokeWidth: 1,
    listening: true,
    draggable: false  // make the element not draggable - we drag the group
  });
  group.add(buttonRect)

  var text = new Konva.Text({  //text on module
    x: mouseX + 20,
    y: mouseY + 20,
    //fontFamily: 'Calibri',
    fontSize: 16,
    text: 'OSC',
    fill: 'black',
    draggable: false  // make the element not draggable - we drag the group
  });
  group.add(text);
  
  var randomFreq = getRandomInt();
  var osc = new Tone.Oscillator(randomFreq, "sawtooth");
  layer.add(group);
  stage.add(layer);

  buttonRect.on('click', function(evt) {
    rectButtonClicked = !rectButtonClicked;
    if(rectButtonClicked){    
    osc.toMaster().start();
    this.setFill('red');
    }  else {
    osc.stop();
    this.setFill('blue');
    }  
});
}

function getRandomInt() {
  min = Math.ceil(100);
  max = Math.floor(1000);
  return Math.floor(Math.random() * (max - min)) + min;
}
stage.draw(); // draw so we can see click rect.
<script src="https://tonejs.github.io/build/Tone.min.js"></script>
<script src="https://cdn.rawgit.com/konvajs/konva/1.7.6/konva.min.js"></script>
<div id="container" style="background-color: gold;"></div>