Stage 事件
点击画布空白处不会触发任何图形事件。要响应它,有两种思路。
用法
所有事件都从图形开始。 因此,如果您点击画布上的空白空间,点击事件将不会触发图层,甚至没有触发阶段对象。 但是如果你真的需要监控在Konva.Stage上空的空间点击(或任何其他类似的事件),你可以:
- 创建与
Stage相同大小的透明矩形,并添加到形状的底部 - 或特意监听
content事件。 支持的content事件:
contentMouseover,contentMousemove,contentMouseout,contentMousedown,contentMouseup,
contentClick,contentDblclick,contentTouchstart,contentTouchmove,contentTouchend,
contentTap,contentDblTap.
说明:点击任何地方,然后查看控制台.
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva@10/konva.min.js"></script>
<meta charset="utf-8">
<title>Konva Stage Events Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #F0F0F0;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var layer = new Konva.Layer();
// add the layer to the stage
stage.add(layer);
var circle = new Konva.Circle({
x: stage.width() / 2,
y: stage.height() / 2,
fill: 'blue',
radius: 30
});
layer.add(circle).draw();
// don't trigger on empty space
stage.on('click', function() {
console.log('usual click on ' + JSON.stringify(stage.getPointerPosition()));
});
// trigger every where
stage.on('contentClick', function() {
console.log('content click on ' + JSON.stringify(stage.getPointerPosition()));
});
</script>
</body>
</html>
常见问题
为什么点空白处什么都没发生?
Konva 的事件从图形开始冒泡。空白处没有图形,命中检测返回空, 自然不会有事件沿着链条往上传。
这不是 bug,而是命中检测机制的直接结果——舞台不是一个「图形」, 它没有自己的可命中区域。
铺一个透明矩形是不是最简单的办法?
通常是。做一个和舞台等大的 Konva.Rect,放在最底层,
给它绑事件即可:
const bg = new Konva.Rect({ width: stage.width(), height: stage.height() });
layer.add(bg);
bg.moveToBottom();
注意不要设 fill——不填充的图形不参与命中检测,那样又点不中了。
要透明又可点,设 fill: 'rgba(0,0,0,0)' 或者给它一个 hitFunc。
另外舞台尺寸变化时要同步更新这个矩形的大小。
content 事件和图形事件有什么区别?
contentClick、contentMousemove 这类事件由舞台直接派发,
不参与图形的冒泡链,因此也拿不到有意义的 e.target。
它们在整个舞台范围内都会触发——点在图形上也会触发 contentClick,
和图形自己的 click 并行发生。如果两边都绑了处理器,一次点击会走两套逻辑。
所以它适合「不关心点到了什么,只要知道舞台被点了」的场景, 比如记录坐标、关闭浮层。
与其他方案的取舍
透明矩形的优点是它就是个普通图形——参与冒泡、有 e.target、
可以用事件委托统一处理。缺点是要自己维护尺寸,
而且它会出现在 find() 的结果里,遍历时得记得排除。
content 事件不需要额外节点,也不用管尺寸。但它与图形事件是两套并行的机制, 混用时容易出现「一次点击触发两处逻辑」,需要自己协调。
判断依据:需要区分点到了空白还是图形,用透明矩形加 e.target 判断最直接;
只是想在舞台任意位置捕获坐标,用 content 事件更轻。