如果您从一开始就遵循此系列,那么您现在应该对形状,组和图层非常满意。 您还应该能够使用Konva在画布上轻松绘制一些基本和复杂的形状 。 如果计划使用Konva创建一些交互式应用程序或游戏,那么下一步将是学习如何将事件绑定到舞台上的不同形状。
在本教程中,您将学习如何使用Konva将事件绑定到任何形状。 您还将了解事件委托和传播。 有时,您可能需要以编程方式控制形状的击中区域以及火灾事件。 我们还将讨论这两个主题。
将事件绑定到形状
您可以在on()
方法的帮助下将不同的事件绑定到使用Konva创建的任何形状。 您要做的就是将事件名称作为第一个参数,将事件发生时要执行的函数作为第二个参数。 您可以使用Konva来检测mouseup
, mousedown
, mouseenter
, mouseleave
, mouseover
, mousemove
, click
和dblclick
。 此外,Konva允许您检测wheel
, dragstart
, dragmove
和dragend
事件。
这是一个检测常规多边形(六边形)上的mousedown
和mouseleave
事件的示例。 同样,较小的圆圈绑定到mouseover
和mouseup
事件,而较大的圆圈绑定到mouseenter
, mouseleave
和mousemove
事件。
var canvasWidth = 600;
var canvasHeight = 400;
var stage = new Konva.Stage({
container: "example",
width: canvasWidth,
height: canvasHeight
});
var layerA = new Konva.Layer();
var polyA = new Konva.RegularPolygon({
x: 125,
y: 125,
sides: 6,
radius: 80,
fill: "yellow",
stroke: "black",
strokeWidth: 5
});
var circA = new Konva.Circle({
x: 275,
y: 225,
height: 100,
fill: "orange",
stroke: "black"
});
var circB = new Konva.Circle({
x: 475,
y: 275,
radius: 100,
fill: "red",
stroke: "black"
});
layerA.add(polyA, circA, circB);
stage.add(layerA);
polyA.on("mousedown", function() {
polyA.sides(polyA.sides() + 1);
layerA.draw();
});
polyA.on("mouseleave", function() {
var totalSides = polyA.sides();
if(totalSides > 3) {
polyA.sides(polyA.sides() - 1);
}
layerA.draw();
});
circA.on("mouseover", function() {
circA.strokeWidth(10);
layerA.draw();
});
circA.on("mouseup", function() {
circA.strokeWidth(5);
layerA.draw();
});
circB.on("mouseenter", function() {
stage.container().style.cursor = "crosshair";
});
circB.on("mouseleave", function() {
stage.container().style.cursor = "default";
});
circB.on("mousemove", function() {
var pointerPos = stage.getPointerPosition();
var r = pointerPos.x % 255;
var g = pointerPos.y % 255;
circB.fill("rgb(" + r + ", " + g + ", 100)");
layerA.draw();
});
如果用户在光标位于常规多边形内时按下任意鼠标按钮,我们会将多边形的边数增加1。可以使用sides()
方法而无需使用参数来获取多边形的边数或使用使用一个参数来设置多边形的边数。 您也可以边用数字getSides()
并使用设置边的数量setSides()
每当鼠标光标离开多边形时,多边形的边就会减少一。
对于较小的圆, mouseover
事件用于将笔划宽度值设置为mouseup
事件将笔划宽度值更改为5。请记住, mouseup
事件必须在圆自身内部发生。 例如,如果您在圆内按下鼠标按钮,然后仅在光标位于圆外之后才释放它,则笔划宽度不会更改为5。
对于较大的圆圈,我们使用mousemove
事件更改其fill
颜色。 每当光标stage.container().style.cursor
或移出圆圈时,我们还使用stage.container().style.cursor
更改较大圆圈的光标。
您应该牢记的重要一件事是,如果任何形状的事件侦听器导致诸如填充颜色,笔触宽度等属性的更改,则必须在相应层上调用draw()
方法。否则,更改不会反映在画布上。
您不必一次将一个事件绑定到一个形状。 您还可以将包含多个事件类型的以空格分隔的字符串传递给on()
方法。 这会将字符串中列出的所有事件绑定到该特定形状。
Konva还支持所有这些事件的相应移动版本。 例如,您可以使用Konva在移动设备上注册touchstart
, touchmove
, touchend
, tap
, dbltap
, dragstart
, dragmove
和dragend
。
您还可以使用fire()
方法针对特定形状触发这些事件中的任何一个。 同样,Konva允许您触发自定义事件,例如throwStones
。
删除事件监听器
您可以借助Konva中的off()
方法删除附加到形状的任何事件侦听器。 您只需要指定您不想听的事件名称即可。
您还可以为单个形状创建多个事件绑定。 例如,假设您有一个圆,并且您希望每次鼠标光标越过该圆时将圆的半径增加到一定限制。 您可能还想在每个mouseover
事件上更改圆圈的填充颜色。
一种选择是在单个mouseover
事件侦听器中完成这两项任务,并稍后停止更新半径。 另一个选择是创建两个具有不同名称空间的mouseover
事件侦听器以标识它们。 这样,您将能够独立增加半径和更改填充颜色。
circA.on("mouseover.radius", function() {
var curRadius = circA.radius();
if(curRadius < 150) {
circA.radius(curRadius + 5);
layerA.draw();
} else {
circA.off('mouseover.radius');
}
});
circA.on("mouseover.fillcolor", function() {
var h = Math.floor(Math.random()*360);
var color = "hsl(" + h + ", 60%, 60%)";
circA.fill(color);
layerA.draw();
});
您应该注意,我在两个监听器中都添加了layerA.draw()
。 如果您无法将其添加到mouseover.fillcolor
侦听器中,则半径一旦变为150,颜色就会停止更新。
您也可以使用setListening()
方法停止监听绑定到形状的所有事件,而不是一次删除一个事件监听器。 你可以通过true
和false
,以便把事件侦听器,以这种方法on
和off
。 请记住,你也会有通过调用重绘受影响层的命中图drawHit()
方法就在你打电话后setListening()
活动委托和传播
除了将事件直接绑定到图层上存在的所有形状之外,还可以将事件绑定到图层本身。 之后,您可以使用事件对象的target
属性确定触发事件的形状。 这样,Konva允许您有效地将事件从父级委派给其子级。
假设您正在听Konva图层上绘制的圆上的单击事件。 相同的click事件传播到包含组以及包含层。 这可能是预期的行为,也可能不是预期的行为。 如果要防止事件在形状内冒泡到包含层,可以将事件对象的cancelBubble
属性设置为true
。
var canvasWidth = 600;
var canvasHeight = 400;
var stage = new Konva.Stage({
container: "example",
width: canvasWidth,
height: canvasHeight
});
var layerA = new Konva.Layer();
var circA = new Konva.Circle({
x: 300,
y: 200,
height: 100,
fill: "orange",
stroke: "black",
name: "Orange Circle"
});
var starA = new Konva.Star({
x: 125,
y: 125,
innerRadius: 25,
outerRadius: 75,
rotation: 90,
fill: "blue",
stroke: "black",
name: "Blue Star"
});
var ringA = new Konva.Ring({
x: 475,
y: 275,
innerRadius: 25,
outerRadius: 75,
fill: "brown",
stroke: "black",
name: "Brown Ring"
});
var textA = new Konva.Text({
text: "",
fontFamily: "Calibri",
fontSize: 24,
fill: "black",
x: 10,
y: 10
});
layerA.add(circA, starA, ringA, textA);
stage.add(layerA);
layerA.on("click", function(e) {
var shapeName = e.target.attrs.name;
textA.setText(shapeName);
layerA.draw();
});
我已经使用name
属性为每个形状分配一个名称。 然后使用setText()
方法将textA
内的文本更改为我们刚刚单击的形状的名称。
自定义热门地区
在上面的示例中,当内圈和外圈之间发生喀哒声时,戒指在其上登记了喀哒声。 如果您也想在较小的圆圈内注册点击该怎么办? Konva允许您使用hitFunc
属性定义自定义命中区域。 此属性接受一个函数作为其值,并且此函数用于绘制自定义匹配区域。
下面的示例向您展示如何创建自定义匹配区域。 现在,您应该可以在星状尖峰之间单击区域,并且仍然可以单击。 借助自定义匹配区域,您可以确保用户不必单击确切位置即可注册点击事件。 在处理较小或更复杂的形状时,这可以带来更好的用户体验。
var starA = new Konva.Star({
x: 125,
y: 125,
innerRadius: 25,
outerRadius: 75,
rotation: 90,
fill: "blue",
stroke: "black",
name: "Blue Star",
hitFunc: function(context) {
context.beginPath();
context.arc(0, 0, this.getOuterRadius(), 0, Math.PI * 2, true);
context.closePath();
context.fillStrokeShape(this);
}
});
var ringA = new Konva.Ring({
x: 475,
y: 275,
innerRadius: 25,
outerRadius: 75,
fill: "brown",
stroke: "black",
name: "Brown Ring",
hitFunc: function(context) {
context.beginPath();
context.arc(0, 0, this.getOuterRadius(), 0, Math.PI * 2, true);
context.closePath();
context.fillStrokeShape(this);
}
});
最后的想法
在本教程中,我们介绍了可以绑定到Konva中任何形状的不同移动事件和桌面事件。 您可以一次附加一个事件,也可以一次附加多个事件。 Konva还允许您使用fire()
方法以编程方式触发自己的自定义事件。 本教程的最后一部分向您展示了如何定义自己的命中区域,以便检测可能大于或小于原始形状的区域中的命中。
将本教程的知识与该系列的其他知识相结合,您现在应该能够在画布上绘制各种形状,并允许用户与其交互。
如果您对本教程有任何疑问,请随时在评论中让我知道。
翻译自: https://code.tutsplus.com/tutorials/manipulating-html5-canvas-using-konva-part-5-events--cms-29874