Проблемы с setTimeout с Javascript в холсте HTML5 на устройстве iOS

Я экспериментирую со сценарием и пытаюсь использовать его для устройства iOS. Поскольку не было возможности использовать событие onmousemove, я хочу использовать что-то, что имитировало бы прикосновение и перетаскивание. Самый простой способ, который я придумал, — это использовать таймер, чтобы всегда отображать эффект рисования, который у меня есть, с текущей позицией мыши, только если он был сначала переключен с помощью onmousedown и не переключен с помощью onmouseup.

Я ожидаю, что функция timeCount будет запущена, если я просто вызову ее вне какой-либо функции, но это не так, поэтому сначала я проверяю, является ли она нулевой внутри события onmousedown, и если это так, вызываю timedCount.

timeCount вызывается, и хотя я определил setTimeout, он вызывает timeCount только один дополнительный раз, и все. Итак, это моя первая проблема.

Во-вторых, как мне зафиксировать текущую точку касания (при условии, что палец пользователя находится где-то еще на экране) без события? Или нужно событие? Который из?

Код выглядит следующим образом. Это отредактированный пример с http://html5demos.com/canvas-grad:

<canvas height="600" width="600"></canvas>
<script>

var canvas = document.getElementsByTagName('canvas')[0],

ctx = null,
grad = null,
body = document.getElementsByTagName('body')[0],
color = 255;
var toggleDraw = 0;
var timer = null;



if (canvas.getContext('2d')) {

  ctx = canvas.getContext('2d');
  ctx.clearRect(0, 0, 600, 600);
  ctx.save();
  // Create radial gradient
  grad = ctx.createRadialGradient(0,0,0,0,0,600); 
  grad.addColorStop(0, '#000');
  grad.addColorStop(1, 'rgb(' + color + ', ' + color + ', ' + color + ')');

  // assign gradients to fill
  ctx.fillStyle = grad;

  // draw 600x600 fill
  ctx.fillRect(0,0,600,600);
  ctx.save();

}

canvas.onmousedown = функция (событие) { toggleDraw = 1; если (таймер == ноль) { timedCount(); } };

canvas.onmouseup = функция (событие) { toggleDraw = 0; };

функция timedCount () {

if(toggleDraw == 1){

    alert("yes");

    var width = window.innerWidth, 
    height = window.innerHeight, 
    x = event.clientX, 
    y = event.clientY,
    rx = 600 * x / width,
    ry = 600 * y / height;

    var xc = ~~(256 * x / width);
    var yc = ~~(256 * y / height);

    grad = ctx.createRadialGradient(rx, ry, 0, rx, ry, 600); 
    grad.addColorStop(0, '#000');
    grad.addColorStop(1, ['rgb(', xc, ', ', (255 - xc), ', ', yc, ')'].join(''));

    ctx.fillStyle = grad;
    ctx.fillRect(0,0,600,600);

}

timer=setTimeout("timedCount()",50);

}

I've also tried an alternative of using setInterval on the canvas mouse events and removing the setTimeout in the timeCount function, but the timeCount function is not called at all:

canvas.onmousedown = function (event) {
    toggleDraw = 1;
    timer=setInterval("timedCount()",50);
};

canvas.onmouseup = function (event) {
    toggleDraw = 0;
    clearInterval(timer);
};

Редактировать: даже с этим я не могу заставить его работать:

<script>
    var canvas = document.getElementsByTagName('canvas')[0],
    ctx = null,
    grad = null,
    body = document.getElementsByTagName('body')[0],
    color = 255;

    if (canvas.getContext('2d')) {
        ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, 600, 600);
        ctx.save();
        // Create radial gradient
        grad = ctx.createRadialGradient(0,0,0,0,0,600); 
        grad.addColorStop(0, '#000');
        grad.addColorStop(1, 'rgb(' + color + ', ' + color + ', ' + color + ')');

        // assign gradients to fill
        ctx.fillStyle = grad;

        // draw 600x600 fill
        ctx.fillRect(0,0,600,600);
        ctx.save();

        canvas.ontouchmove = function (event) {
            event.preventDefault();
            var width = window.innerWidth, 
            height = window.innerHeight, 
            x = event.clientX, 
            y = event.clientY,
            rx = 600 * x / width,
            ry = 600 * y / height;

            var xc = ~~(256 * x / width);
            var yc = ~~(256 * y / height);

            grad = ctx.createRadialGradient(rx, ry, 0, rx, ry, 600); 
            grad.addColorStop(0, '#000');
            grad.addColorStop(1, ['rgb(', xc, ', ', (255 - xc), ', ', yc, ')'].join(''));
            // ctx.restore();
            ctx.fillStyle = grad;
            ctx.fillRect(0,0,600,600);
            // ctx.save();
        };
    }
    </script>

Хорошо, вот рабочий скрипт!!

Крайне важно использовать сенсорный API Apple и отслеживать касание, которое вы хотите использовать:

<script>
    var canvas = document.getElementsByTagName('canvas')[0],
    ctx = null,
    grad = null,
    body = document.getElementsByTagName('body')[0],
    color = 255;

    if (canvas.getContext('2d')) {
        ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, 600, 600);
        ctx.save();
        // Create radial gradient
        grad = ctx.createRadialGradient(0,0,0,0,0,600); 
        grad.addColorStop(0, '#000');
        grad.addColorStop(1, 'rgb(' + color + ', ' + color + ', ' + color + ')');

        // assign gradients to fill
        ctx.fillStyle = grad;

        // draw 600x600 fill
        ctx.fillRect(0,0,600,600);
        ctx.save();


    }

    canvas.ontouchmove = function (event) {
        event.preventDefault();

        if(event.touches.length == 1){
            var touch = event.touches[0];
        }

        var width = window.innerWidth, 
        height = window.innerHeight, 
        //x = event.clientX, 
        //y = event.clientY,
        x = touch.pageX;
        y = touch.pageY;

        rx = 600 * x / width,
        ry = 600 * y / height;

        var xc = ~~(256 * x / width);
        var yc = ~~(256 * y / height);

        grad = ctx.createRadialGradient(rx, ry, 0, rx, ry, 600); 
        grad.addColorStop(0, '#000');
        grad.addColorStop(1, ['rgb(', xc, ', ', (255 - xc), ', ', yc, ')'].join(''));
        ctx.fillStyle = grad;
        ctx.fillRect(0,0,600,600);
    };
    </script>

person Chewie The Chorkie    schedule 16.11.2011    source источник


Ответы (2)


В iOS все события мыши срабатывают сразу после завершения касания. Что, вероятно, не то, что вы хотите.

Вместо этого используйте события ontouchdown, ontouchmove и ontouchup.

Кроме того, в ontouchmove вам нужно предотвратить поведение по умолчанию, чтобы страница не начинала прокручиваться.

canvas.ontouchmove = function(e) {
  // your code here
  e.preventDefault();
}
person Alex Wayne    schedule 16.11.2011
comment
Спасибо. Я заменил свои функции событий только на canvas.ontouchmove = function (event) { event.preventDefault(); событие.timedCount(); } без интервалов, но timeCount, похоже, не вызывается. - person Chewie The Chorkie; 16.11.2011
comment
event.timedCount();? этого не должно быть... Попробуйте начать с чего-нибудь попроще. Сделайте тело вашего обработчика событий просто alert('omg it works') и посмотрите, вызывается ли функция вообще. Одна проблема за один раз здесь :) - person Alex Wayne; 16.11.2011
comment
На самом деле, я думаю, это потому, что я не указал касание в списке касаний. Я посмотрю на это. - person Chewie The Chorkie; 16.11.2011

Вы должны обрабатывать конкретные события касания

  1. touchstart: происходит каждый раз, когда палец помещается на экран
  2. touchend: происходит каждый раз, когда палец убирается с экрана
  3. touchmove: происходит, когда палец, уже помещенный на экран, перемещается по экрану.

См. ссылку http://www.sitepen.com/blog/2008/07/10/touching-and-gesturing-on-the-iphone/

node.ontouchstart = function(evt){
  console.log(evt.pageX + "/" + evt.pageY);
}
person Juan Mendes    schedule 16.11.2011