Gesture Events on Canvas Shapes

Get last news, demos, posts from Konva

How to listen to swipe, pinch zoom, rotate and other multitouch gesture events on Konva shapes?

By default Konva supports only basic touch events such as touchstart, touchmove, touchend.

You have to implement gesture events manually from that touch events.

But I was able to slightly change Hammer.js to make it work with Konva!

You can find modified hammer.js source code here.

Instructions: you can try different gestures on the rectangle such as swipe, rotate, zoom, drag&drop, press.

For desktop browsers you can hold Shift key to emulate touch events.

Note: this demo is experimental.

Konva Touch Gestures Demoview raw
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/[email protected]/konva.min.js"></script>
<!-- emulate touches on desktop -->
<script src="https://cdn.rawgit.com/hammerjs/touchemulator/master/touch-emulator.js"></script>
<!-- 3-rd party library for gesture events -->
<script src="/js/hammer-konva.js"></script>

<meta charset="utf-8" />
<title>Konva Touch Gestures Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #f0f0f0;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
TouchEmulator();
Konva.hitOnDragEnabled = true;
Konva.captureTouchEventsEnabled = true;

var width = window.innerWidth;
var height = window.innerHeight;

var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});

var layer = new Konva.Layer();
stage.add(layer);

var originalAttrs = {
x: stage.width() / 2,
y: stage.height() / 2,
scaleX: 1,
scaleY: 1,
draggable: true,
rotation: 0
};

var group = new Konva.Group(originalAttrs);
layer.add(group);

var size = 200;

var rect = new Konva.Rect({
width: size,
height: size,
fill: 'yellow',
offsetX: size / 2,
offsetY: size / 2,
cornerRadius: 5,
shadowBlur: 10,
shadowColor: 'grey'
});
group.add(rect);

var defaultText = 'Try\ndrag, swipe, pinch zoom, rotate, press...';
var text = new Konva.Text({
text: defaultText,
x: -size / 2,
width: size,
align: 'center'
});
group.add(text);
layer.draw();

// attach modified version of Hammer.js
// "domEvents" property will allow triggering events on group
// instead of "hammertime" instance
var hammertime = new Hammer(group, { domEvents: true });

// add rotate gesture
hammertime.get('rotate').set({ enable: true });

// now attach all possible events
group.on('swipe', function(ev) {
text.text('swiping');
group.to({
x: group.x() + ev.evt.gesture.deltaX,
y: group.y() + ev.evt.gesture.deltaY,

onFinish: function() {
group.to(Object.assign({}, originalAttrs));
text.text(defaultText);
}
});
});

group.on('press', function(ev) {
text.text('Under press');
rect.to({
fill: 'green'
});
});

group.on('touchend', function(ev) {
rect.to({
fill: 'yellow'
});

setTimeout(() => {
text.text(defaultText);
layer.batchDraw();
}, 300);
});

group.on('dragend', () => {
group.to(Object.assign({}, originalAttrs));
});

var oldRotation = 0;
var startScale = 0;
group.on('rotatestart', function(ev) {
oldRotation = ev.evt.gesture.rotation;
startScale = rect.scaleX();
group.stopDrag();
group.draggable(false);
text.text('rotating...');
});

group.on('rotate', function(ev) {
var delta = oldRotation - ev.evt.gesture.rotation;
group.rotate(-delta);
oldRotation = ev.evt.gesture.rotation;
group.scaleX(startScale * ev.evt.gesture.scale);
group.scaleY(startScale * ev.evt.gesture.scale);
layer.batchDraw();
});

group.on('rotateend rotatecancel', function(ev) {
group.to(Object.assign({}, originalAttrs));
text.text(defaultText);
group.draggable(true);
layer.batchDraw();
});
</script>
</body>
</html>
Next