如果您從一開始就專注於本系列,那麼您現在應該對形狀、群組和圖層非常熟悉。您還應該能夠使用 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
事件用於將描邊寬度值設為 10。 mouseup
事件將描邊寬度值變更為 5。請記住mouseup
事件必須發生在圓本身內部。例如,如果在圓內按下滑鼠按鈕,然後在遊標移至圓外後才放開滑鼠按鈕,則描邊寬度不會變更為 5。
對於較大的圓圈,我們使用 mousemove
事件來更改其 fill
顏色。每當遊標移入和移出圓圈時,我們也會使用 stage.container().style.cursor
來改變較大圓圈的遊標。
您應該記住的一件重要的事情是,如果任何形狀的事件偵聽器導致諸如fill 之類的屬性發生更改,則必須在相應圖層上調用draw()
方法顏色、描邊寬度等。否則,更改將不會反映在畫布上。
您不必一次將一個事件綁定到一個形狀。您也可以將包含多個事件類型的空格分隔字串傳遞給 on()
方法。這會將字串中列出的所有事件綁定到該特定形狀。
Konva 也支援所有這些活動的相應行動版本。例如,您可以註冊touchstart
,
touchmove
, touchend
, tap
,
在行動裝置上使用 Konva 的 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
。请记住,您还必须在调用 setListening()
后立即调用 drawHit()
方法来重新绘制受影响图层的命中图。 p>
您还可以将事件绑定到图层本身,而不是将事件直接绑定到图层上的所有形状。之后,您可以使用事件对象的 target
属性确定哪个形状触发了事件。通过这种方式,Konva 允许您有效地将事件从父级委托给其子级。
假设您正在监听 Konva 图层上绘制的圆圈上的单击事件。相同的单击事件会传播到包含组以及包含图层。这可能是也可能不是预期的行为。如果要防止事件在形状内部冒泡到包含层,可以将事件对象的 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()
方法以编程方式触发自己的自定义事件。本教程的最后一部分向您展示了如何定义自己的命中区域,以便检测可能大于或小于原始形状的区域上的命中。
将本教程的知识与本系列中其他教程的知识相结合,您现在应该能够在画布上绘制各种形状并允许用户与它们进行交互。
如果您对本教程有任何疑问,请随时在评论中告诉我。
以上是Konva 的 HTML5 Canvas 事件:第 5 部分,操作的詳細內容。更多資訊請關注PHP中文網其他相關文章!