Dotýkejte se, prosím, na více místech
V předchozích dvou článcích jsme si ukazovali, jak lze obsloužit dotyková gesta a jak zpracovat jednotlivé body dotyku. Naznačili jsme si strukturu informací, které má aplikace k dispozici. V posledním pokračování si ukážeme, jak je využít pro sledování dotyků více prsty.
Seriál Dotykové ovládání a JavaScript
- Dotýkejte se, prosím...
- Dotýkejte se, prosím, jemněji...
- Dotýkejte se, prosím, na více místech
Ukážeme si na závěr jednoduchý příklad, jak sledovat dotyky více prsty najednou (příklad se hodí i jako jednoduchý test, zda zařízení, například tablet, podporuje multitouch).
Příklad vychází z kódu na adrese http://sebleedelisle.com/2011/04/multi-touch-game-controller-in-javascripthtml5-for-ipad/ od Seba Lee-Delisle)
Zdrojový kód:
<style>
…
canvas {
background-color:#111133;
display:block;
position:absolute;
}
#container {
width:auto;
text-align:center;
background-color:#ff0000;
}
</style>
<script>
"use strict";
var c, canvas, touches;
function touchstart(e){
touches = e.touches;
}
function touchmove(e){
e.preventDefault();
touches = e.touches;
}
function touchend(e){
touches = e.touches;
}
function draw() {
if (touches && touches.length>0) {
c.clearRect(0,0,canvas.width, canvas.height);
for(var i=0; i<touches.length; i++)
{
var touch = touches[i];
c.fillStyle = "white";
c.fillText("touch id : "+touch.identifier+" x:"+touch.clientX+" y:"+touch.clientY, touch.clientX+30, touch.clientY-30);
c.beginPath();
c.strokeStyle = "magenta";
c.lineWidth = "6";
c.arc(touch.clientX, touch.clientY, 40, 0, Math.PI*2, true);
c.stroke();
}
} else {
c.clearRect(0,0,canvas.width, canvas.height);
}
}
function resetCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
window.scrollTo(0,0);
}
function onload(){
canvas = document.getElementById( 'c' );
c = canvas.getContext( '2d' );
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.ontouchstart = touchstart;
canvas.ontouchmove = touchmove;
canvas.ontouchend = touchend;
window.onorientationchange = resetCanvas;
window.onresize = resetCanvas;
setInterval(draw, 1000/35);
}
</script>
</head>
<body onload="onload()">
<div id="container">
<canvas id="c"></canvas>
</div>
</body></html>
Obsluha událostí spočívá pouze v tom, že jsou aktuální souřadnice dotyků (e.touches) uloženy do globální proměnné. U pohybu je ještě zablokováno vykonávání systémové události. Pamatujte: obsluha událostí by měla být co nejrychlejší, což je tu dodrženo.
function touchstart(e){
touches = e.touches;
}
function touchmove(e){
e.preventDefault();
touches = e.touches;
}
function touchend(e){
touches = e.touches;
}
Na začátku (onload) je získán 2D kontext pro canvas. Canvas je přes celou plochu, proto navěsíme obsluhu touch událostí právě na něj. Důležité je periodické vyvolání funkce draw, která se postará o vizualizaci míst dotyku.
Funkce draw() vezme souřadnice dotyků (z globální proměnné) a vykreslí do patřičných míst kroužky a k nim připojí text s informacemi o souřadnicích a o ID dotykové události.
Vykreslení je implementováno „naivně“ – funkce se vyvolává pravidelně v daném intervalu, vždy smaže celý canvas a vykreslí vše znovu. Samotná animace je poměrně jednoduchá, takže „problikávání“ není vidět – pokud byste ale implementovali nějaké složitější vykreslování, bylo by samozřejmě na místě použít vyspělejší animační techniky (double / triple buffering atd.)
Poznámka k animaci
V době psaní této kapitoly bohužel ještě iOS nepodporoval animační novinku – JS funkci requestAnimationFrame(). Tato funkce je velmi podobná funkci setInterval() s tím rozdílem, že interval je daný „systémovou“ animační smyčkou, v níž systém vykonává např. CSS animace. Pokud řešíte animace v JavaScriptu, je výhodné použít právě tuto funkci. Prohlížeč ji pak vyvolává tak často jako ostatní animační rutiny, vykreslování je tedy synchronizované a s optimální rychlostí.
Vlastní kód lze upravit tak, aby byl připravený na okamžik, kdy iOS tuto funkci implementuje:
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
(function(x){setInterval(x,1000/60);});
requestAnimationFrame(draw);
Tento shim definuje funkci requestAnimationFrame. Pokud je systémová, použije ji. Pokud prohlížeč nabízí funkci s vendor prefixem, použije tu. Pokud nemá ani s prefixem, použije náhradní řešení se setInterval.
Pro podobné krátké kódy, které řeší problémy s kompatibilitou mezi prohlížeči, se vžilo označení shim. Kódy, které pomáhají používat nové funkce i v prohlížečích, kde nejsou implementované, se označují jako polyfill.
Ve chvíli, kdy prohlížeč Safari v iOS implementuje requestAnimationFrame, použije kód tuto implementaci, do té doby si vystačí se setInterval.
Autor děkuje společnosti Czech Computer za laskavé zapůjčení tabletu iPad 2.
Školení: Návrh a používání MySQL databáze

Naučte se používat jednu z nejrozšířenějších databází. Dozvíte se vše potřebné od návrhu až po samotné využití MySQL v projektech.
Školení pro všechny, kteří se chtějí naučit efektivně pracovat s MySQL nebo se v práci s touto databází zlepšit.
Přihláška a podrobné informace
Seriál Dotykové ovládání a JavaScript
- Dotýkejte se, prosím...
- Dotýkejte se, prosím, jemněji...
- Dotýkejte se, prosím, na více místech
Přehled názorů
Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.