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

Odebírat
Upozornit na
guest
1 Komentář
Nejstarší
Nejnovější Nejvíce hlasů
juraj

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

AI přepracovala 300 tisíc řádků Street Fighteru III. Hlídal ji hash každého snímku

‐ AI ‐
Komentáře: 0
AI agenti za tři týdny přepracovali dekompilovaný kód Street Fighteru III: 3rd Strike a podle metriky CodeScene dosáhli nejvyššího možného skóre kvality. Shoda s původní verzí se ověřovala přehráváním herních záznamů a porovnáním hashe herního stavu po každém snímku. Taková kontrola je přísnější než běžné testy, zachytí ale jen to, co do hashe vstupuje.

DressCode si vezme váš PHP kód do parády

‐ PHP ‐
Komentáře: 0
Napsat nové pravidlo do PHP CS Fixeru nebo PHP_CodeSnifferu je za trest. David Grudl to zkusil kvůli jedinému řádku `use function` a místo pravidla z toho vznikl nový nástroj DressCode, postavený nad stromem, který ze zdrojáku nic nezahodí. Ukážeme si, jak ho nasadit, nastavit a zapojit do práce AI agenta.