Přejít k navigační liště

Zdroják » JavaScript » Dotýkejte se, prosím, na více místech

Dotýkejte se, prosím, na více místech

Články JavaScript, Webdesign

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.

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://seblee­delisle.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 requestAnimati­onFrame. 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 requestAnimati­onFrame, 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.

Komentáře

Subscribe
Upozornit na
guest
1 Komentář
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
juraj

requestAnimati­onFrame nemozete predsa nahradzat setIntervalom, pretoze RAF spusta svoj prvy argument iba raz, nie cyklicky. Chcelo by to setTimeout.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.