• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

使用Konva操作 HTML5 Canvas:第5部分

在本教程中,您将学习如何使用 Konva 将事件绑定到任何形状。您还将了解事件委托和传播。有时,您可能需要以编程方式控制形状的命中区域以及火灾事件我们也将讨论这两个主题。

将事件绑定到形状

您可以借助该 on()方法将不同的事件绑定到使用 Konva 创建的任何形状。您所要做的就是将事件的名称作为第一个参数传递,将事件发生时要执行的函数作为第二个参数传递。您可以使用 Konva 检测mouseupmousedownmouseentermouseleavemouseovermousemoveclick, 和dblclick此外,Konva 允许您检测wheeldragstartdragmovedragend事件。

这是一个在正多边形(六边形)上检测mousedown和事件的示例。mouseleave类似地,小圆圈绑定到 mouseoverandmouseup事件,大圆圈绑定到 mouseentermouseleave, andmousemove事件。

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每当光标移入和移出圆圈时,我们也会更改较大圆圈 的光标。

使用Konva操作 HTML5 Canvas:第5部分  第1张

您应该记住的一件重要事情是,draw()如果任何形状的事件***器导致填充颜色、笔触宽度等属性发生变化,则必须调用相应图层上的方法。否则,更改不会反映在画布上。

您不必一次将一个事件绑定到一个形状。您还可以将包含多种事件类型的空格分隔字符串传递给该on()方法。这会将字符串中列出的所有事件绑定到该特定形状。

Konva 还支持所有这些事件的相应移动版本。例如,您可以在移动设备上注册touchstarttouchmovetouchendtapdbltapdragstartdragmovedragend使用 Konva。

fire()您还可以使用该方法为特定形状或形状触发任何这些事件。同样,Konva 允许您触发自定义事件,例如throwStones.

删除事件监听器

off()您可以借助Konva中的方法移除任何附加到形状的事件*** 器。您只需指定不想收听的事件名称。

您还可以为单个形状创建多个事件绑定。例如,假设您有一个圆,并且您希望每次鼠标光标移过它时都增加圆的半径,直至达到一定限度。您可能还想在每个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,颜色就会停止更新。

使用Konva操作 HTML5 Canvas:第5部分  第2张

setListening()除了一次删除一个事件***器之外,您还可以使用该方法停止***绑定到某个形状的所有事件。您可以将trueand传递false给此方法以打开事件***器onoff请记住,您还必须通过在调用 drawHit()后立即调用该方法来重绘受影响层的命中图setListening()

事件委托和传播

除了将事件直接绑定到图层上的所有形状之外,您还可以将事件绑定到图层本身。之后,您可以使用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操作 HTML5 Canvas:第5部分  第3张

自定义命中区域

在上面的例子中,当点击发生在内圈和外圈之间时,环注册了一次点击。如果您也想在较小的圆圈内注册点击怎么办?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操作 HTML5 Canvas:第5部分  第4张

最后的想法

在本教程中,我们介绍了可以绑定到 Konva 中任何形状的不同移动和桌面事件。您可以一次附加一个事件,也可以一次附加多个事件。Konva 还允许您使用该fire()方法以编程方式触发您自己的自定义事件。本教程的最后一部分向您展示了如何定义自己的命中区域,以检测可能大于或小于原始形状的区域上的命中。


文章目录
  • 将事件绑定到形状
  • 删除事件监听器
  • 事件委托和传播
  • 自定义命中区域
  • 最后的想法