Проблема с медленным обновлением холста html 5 после события mousemove / mouseclick

#html #canvas #mouseevent #setinterval

#HTML #холст #mouseevent #setinterval

Вопрос:

Недавно я впервые экспериментировал с html 5 и, в частности, с объектом canvas.

Кажется, у меня возникли некоторые проблемы с событиями мыши.

Программа представляет собой сетку граней с случайным изменением фона разного цвета. Сверху есть форма облака, которую я использую в качестве области отсечения, чтобы иметь возможность видеть только части сетки под облаком. (Подумайте, луч фонарика странной формы)

Проблема в том, что я пытаюсь переместить облачную область с помощью мыши, и она не обновляется плавно ни с помощью событий mousemove, ни с помощью mouseclick. Кажется, требуется один или два кадра, чтобы наверстать упущенное, в то время как циклические цвета, похоже, продолжаются.

Я пробовал:

  • Удаление случайных цветов для ускорения.
  • Использование только простой формы для обрезки.
  • Настройка функции setInterval для обновления каждые 1 мс

Можно увидеть здесь — http://jsfiddle.net/mXrNk/14 /

Любая помощь будет оценена. Вероятно, отсутствует что-то очевидное.

 <script>

const FPS = 60;
var myimg = new Image();

window.addEventListener('click', clicked, true);

var mouseX = 170;
var mouseY = 80;

window.onload = init;

function init() {

    canvas = document.getElementById('myCanvas');
    context = canvas.getContext('2d');

    myimg.src = "smile.png";

    setInterval(draw, 1000/FPS);

}

function draw() {

    context.clearRect(0,0,canvas.width,canvas.height);
    // draw cloud
    context.beginPath(); // begin custom shape
    context.moveTo(mouseX, mouseY);
    context.bezierCurveTo(mouseX-40, mouseY 20, mouseX-40, mouseY 70, mouseX 60, mouseY 70);
    context.bezierCurveTo(mouseX 80, mouseY 100, mouseX 150, mouseY 100, mouseX 170, mouseY 70);
    context.bezierCurveTo(mouseX 250, mouseY 70, mouseX 250, mouseY 40, mouseX 220, mouseY 20);
    context.bezierCurveTo(mouseX 260, mouseY-40, mouseX 200, mouseY-50, mouseX 170, mouseY-30);
    context.bezierCurveTo(mouseX 150, mouseY-75, mouseX 80, mouseY-60, mouseX 80, mouseY-30);
    context.bezierCurveTo(mouseX 30, mouseY-75, mouseX-20, mouseY-60, mouseX, mouseY);
    context.closePath(); // complete custom shape
    context.lineWidth = 5;
    context.strokeStyle = "#0000ff";
    context.stroke();

    context.save();
    context.clip();

    for (i = 0; i<7; i  ) {
        for (j = 0; j < 13; j  ) {
            context.strokeRect(j*myimg.width,  i*myimg.height, myimg.width, myimg.height);
            context.fillStyle = rndColor();
            context.fillRect(j*myimg.width,  i*myimg.height, myimg.width, myimg.height);
            context.drawImage(myimg, j*myimg.width, i*myimg.height);
            context.fillStyle = "black";
            context.font = "italic 10pt Arial ";
            context.fillText((i*13) j, j*myimg.width 5,i*myimg.width 15);
        }
    }   

    context.restore();

}

function rndColor() {
    return '#'   ('00000'   (Math.random() * 16777216 << 0).toString(16)).substr(-6);
}

function clicked(e) {
    mouseX = e.pageX;
    mouseY = e.pageY;
}

</script>
  

Комментарии:

1. скрипка убивает Chrome, о нет!

Ответ №1:

Живая демонстрация

Я использовал setTimeout вместо setInterval . При использовании интервала, если он пытается запустить функцию до ее завершения, события будут накапливаться и все еще продолжать пытаться выполнить, пока вызовы все еще накапливаются.

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

Также взгляните на эту статью,

https://simonsarris.com/increasing-performance-by-caching-paths-on-canvas/

Речь идет о кэшировании ваших путей. На самом деле это Саймон Саррис, который, я уверен, тоже появится и увидит этот вопрос.

Комментарии:

1. Нет проблем, рад, что помогло.

2. Эта ссылка 404:'(

3. @AlexPodworny удивлен, что на самом деле нашел новую ссылку и обновил