多重事件
一个处理器同时响应多种事件,只要把事件名写在同一个字符串里。
用法
要使用Konva将多个事件绑定到单个处理程序,我们可以使用on()方法,并传递一个包含多个事件类型用空格开的字符串。
说明:鼠标经过,鼠标按下和鼠标弹起在圆上,观察 每个事件都执行绑定到圆上的函数。
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva@10/konva.min.js"></script>
<meta charset="utf-8">
<title>Konva Multi-Event Binding Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #F0F0F0;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
function writeMessage(message) {
text.setText(message);
layer.draw();
}
var stage = new Konva.Stage({
container: 'container',
width: 300,
height: 300
});
var layer = new Konva.Layer();
var text = new Konva.Text({
x: 10,
y: 10,
fontFamily: 'Calibri',
fontSize: 20,
text: '',
fill: 'black'
});
var numEvents = 0;
var circle = new Konva.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2 + 10,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4
});
circle.on('mouseover mousedown mouseup', function() {
writeMessage('Multi-event binding! Events: ' + (++numEvents));
});
circle.on('mouseout', function() {
writeMessage('');
});
layer.add(circle);
layer.add(text);
// add the layer to the stage
stage.add(layer);
</script>
</body>
</html>
常见问题
多个事件共用处理器,怎么知道是哪个触发的?
读 e.type:
shape.on('mouseover mouseout', (e) => {
const entering = e.type === 'mouseover';
});
如果每种事件的逻辑差别很大,与其在一个处理器里分支,不如分开绑定—— 合并的意义在于逻辑相同,不在于少写几行。
能和命名空间一起用吗?
可以,每个事件名各带各的命名空间:
node.on('click.menu dblclick.menu', handler);
node.off('.menu');
一次 off('.menu') 就能把这一组全部移除,不用逐个列举事件名。
组件卸载时这个写法很省事,详见通过名称移除事件。
绑定多个事件会影响性能吗?
基本不会。监听器本身极轻,真正的开销在命中检测——而那取决于有多少图形在监听, 与每个图形监听了几种事件无关。
换句话说,一个图形绑十种事件,和绑一种,命中检测的成本是一样的。
想省这部分开销要用 listening(false)。
与其他方案的取舍
合并绑定适合逻辑完全相同的场景,最典型的是桌面与触屏的事件对:
click tap、mousedown touchstart。这类情况下合并不只是省事,
Konva 还会做去重,避免触屏上同一次操作执行两遍。
如果只是「恰好都要改同一个状态」,分开绑定往往更清楚—— 后续某一种事件的逻辑要单独调整时,不必先把合并的处理器拆开。
判断标准:这些事件在语义上是不是同一件事的不同表达形式。是,就合并; 只是碰巧做了类似的事,就分开。