Статьи

Управление холстом HTML5 с помощью Konva: часть 5, события

Если вы следили за этой серией с самого начала, теперь вам должно быть удобно с фигурами, группами и слоями . Вы также можете легко рисовать некоторые базовые и сложные фигуры на холсте, используя Konva. Если вы планируете использовать Konva для создания интерактивного приложения или игр, следующим логическим шагом будет изучение того, как связать события с различными фигурами на сцене.

В этом уроке вы узнаете, как связывать события с любой формой, используя Konva. Вы также узнаете о делегировании и распространении событий. Иногда вам может понадобиться программно контролировать область попадания фигуры, а также события пожара. Мы также будем обсуждать эти две темы.

Вы можете привязать различные события к любой фигуре, созданной с помощью Konva, с помощью метода on() . Все, что вам нужно сделать, это передать имя события в качестве первого параметра и функцию, которая будет выполняться, когда событие происходит, как второй параметр. Вы можете использовать Konva для определения mouseup , mousedown , mouseenter , mouseleave , mouseover , mousemove , click и dblclick . Кроме того, Konva позволяет обнаруживать dragstart dragmove wheel , dragmove , dragend и dragend .

Вот пример, который обнаруживает события mousedown и mouseleave на правильном многоугольнике (шестиугольник). Аналогично, меньший круг связан с событиями mouseover и mouseup а больший круг связан с mouseenter , mouseleave и mousemove .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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 всякий раз, когда курсор перемещается stage.container().style.cursor и наружу круга.

Важно помнить, что необходимо вызывать метод draw() на соответствующем слое, если прослушиватели событий для любой фигуры приводят к изменению таких атрибутов, как цвет заливки, ширина обводки и т. Д. В противном случае изменения не будет отражено на холсте.

Вам не нужно привязывать одно событие за раз к фигуре. Вы также можете передать строку с разделителем пробелом, содержащую несколько типов событий, в метод on() . Это свяжет все события, перечисленные в строке, с этой конкретной формой.

Konva также поддерживает соответствующие мобильные версии всех этих событий. Например, вы можете зарегистрировать touchstart , touchmove , touchend , tap , dbltap , dragstart , dragmove и dragend используя Konva на мобильных устройствах.

Вы также можете запустить любое из этих событий для определенной фигуры или формы, используя метод fire() . Точно так же Konva позволяет вам запускать пользовательские события, такие как throwStones .

Вы можете удалить любые прослушиватели событий, прикрепленные к фигуре, с помощью метода off() в Konva. Вам просто нужно указать название события, которое вы не хотите слушать.

Вы также можете создать несколько привязок событий для одной фигуры. Например, допустим, у вас есть круг, и вы хотите увеличивать радиус круга каждый раз, когда курсор мыши проходит над ним, до определенного предела. Вы также можете изменить цвет заливки круга при каждом событии mouseover .

Одним из вариантов является выполнение обеих этих задач внутри одного прослушивателя событий при mouseover и прекращение обновления радиуса позже. Другой вариант — создать два прослушивателя событий mouseover с разными пространствами имен для их идентификации. Таким образом, вы сможете увеличить радиус и самостоятельно изменить цвет заливки.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
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 этому методу, чтобы включить и off прослушиватели событий. Имейте в виду, что вам также придется перерисовывать график попаданий затронутого слоя, вызывая метод drawHit() сразу после вызова setListening() .

Вместо привязки событий непосредственно ко всем фигурам, присутствующим на слое, вы также можете привязать событие к самому слою. После этого вы можете определить, какая фигура вызвала событие, используя свойство target объекта события. Таким образом, Konva позволяет эффективно делегировать события от родителя его дочерним элементам.

Допустим, вы слушаете события щелчка по кругу, нарисованному на слое в Konva. Это же событие щелчка распространяется и на содержащую группу, и на содержащий слой. Это может или не может быть предполагаемым поведением. Если вы хотите предотвратить cancelBubble события внутри фигуры на содержащий слой, вы можете установить для свойства cancelBubble объекта события значение true .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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 . Это свойство принимает функцию в качестве значения, и эта функция используется для рисования пользовательской области попадания.

В следующем примере показано, как создавать собственные области попадания. Теперь вы должны быть в состоянии щелкнуть в области между шипами звезд и по-прежнему регистрировать щелчок. С помощью пользовательских областей попадания вы можете быть уверены, что вашим пользователям не нужно нажимать точные местоположения, чтобы зарегистрировать событие щелчка. Это может привести к улучшению взаимодействия с пользователем при работе с более мелкими или более сложными фигурами.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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() . В последнем разделе руководства показано, как определить свои собственные области попадания, чтобы обнаружить попадания в области, которая может быть больше или меньше исходной формы.

Объединяя знания этого урока с другими участниками серии, вы теперь сможете рисовать различные формы на холсте и позволять своим пользователям взаимодействовать с ними.

Если у вас есть какие-либо вопросы, связанные с этим учебником, не стесняйтесь сообщать мне в комментариях.