JavaScript — как рисовать на холсте и заставить изображение следовать за мышью

Я получил много помощи от этого сайта, но у меня, кажется, проблема собрать все это вместе. В частности, в JS я знаю, как

а) нарисовать изображение на холсте

б) заставьте прямоугольник следовать за курсором (Рисование на холсте) и (http://billmill.org/static/canvastutorial/ball.html)

c) нарисуйте прямоугольник, чтобы использовать его в качестве фона

Чего я не могу понять, так это того, как использовать прямоугольник в качестве фона, а затем нарисовать изображение (png) на холсте и заставить его следовать за курсором.

То, что у меня есть до сих пор, выглядит так:

var canvas = document.getElementByID('canvas');
var ctx = canvas.getContext('2d');
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
var bgColor = '#FFFFFF';
var cirColor = '#000000';

clear = function() {
    ctx.clearRect(0, 0, WIDTH, HEIGHT);
}

drawIMG = function(x,y,r) {
    ctx.fillStyle = cirColor;
    ctx.beginPath();
    ctx.arc(x, y, r, 0, Math.PI*2, true);
    ctx.closePath();
    ctx.fill();
}

draw = function() {
    ctx.fillStyle = bgColor;
    clear();
    ctx.fillRect(0, 0, WIDTH, HEIGHT);
    drawIMG(150, 150, 30);
    drawIMG(300, 500, 12);
};

draw();

Это отобразит элемент холста HTML5, высота и ширина которого указаны в HTML и поэтому являются переменными, с белым прямоугольником размером с холст под двумя черными кругами в точках (150 150) и (300 500). Он делает это отлично.

Однако я не знаю, как заставить JS рисовать .png поверх того, что следует за курсором. Как я уже сказал, я смог выполнить большинство шагов по отдельности, но понятия не имею, как их комбинировать. Я знаю, например, что я должен сделать

img = new Image();

а потом

img.src = 'myPic.png';

в какой-то момент. Их нужно сочетать с модификаторами позиции, такими как

var xPos = pos.clientX;
var yPos = pos.clientY;
ctx.drawImage(img, xPos, yPos);

Но я понятия не имею, как это сделать, сохраняя при этом какие-либо другие вещи, которые я написал выше (в частности, фон).

Спасибо за ваше терпение, если вы прочитали все это. Я не спал какое-то время и боюсь, что мой мозг настолько загорелся, что я не узнал бы ответ, если бы он разделся догола и исполнил Макарену. Я был бы признателен за любую помощь, которую вы могли бы прислать мне, но я думаю, что рабочий пример будет лучше. Я посвящен в религию программирования и до сих пор лучше всего учусь, бессовестно копируя, а затем изменяя.

В любом случае, заранее примите мою оптимистическую благодарность.


person brake    schedule 15.06.2014    source источник
comment
Сделай скрипку, и я постараюсь помочь.   -  person Mosho    schedule 15.06.2014


Ответы (1)


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

Прежде чем продолжить, я рекомендую вам посетить эти веб-сайты: http://www.williammalone.com/articles/create-html5-canvas-javascript-sprite-animation/

Уильям рассказывает об основных приемах анимации холста.

http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/ Пол Айриш рассказывает о функции рекурсивной анимации, которая вращается со скоростью 60 кадров в секунду.

Использование обоих их туториалов — неплохое начало для анимации.

Теперь, насколько я понимаю, вам нужен один «фон» и одна анимация, которая следует за курсором. Первое, что вы должны иметь в виду, это то, что когда вы рисуете на холсте, все, на чем вы рисуете, заменяется. Итак, первое, что я заметил, что вызовет проблемы с производительностью, это тот факт, что вы очищаете весь холст, а не то, что нужно очистить.

Что вам нужно сделать, так это запомнить положение и размер вашего движущегося элемента. Неважно, какую форму он принимает, потому что ваш clearRect() должен полностью удалить его.

Теперь вы, наверное, спросите, а что, если я нарисую прямоугольник на заднем плане. Ну, это вызовет проблему. У вас есть два решения. Либо (а) очистите фон и анимацию движения и снова нарисуйте их в том же порядке, либо (б) поскольку вы знаете, что ваш фон никогда не будет двигаться, создайте второй холст с position = absolute. , z-index = -1 , и его расположение такое же, как и у первого холста.

Таким образом, вам никогда не придется беспокоиться о фоне, и вы сможете сосредоточиться на текущей анимации.


Теперь, возвращаясь к части кодирования, первое, что вам нужно сделать, это скопировать рекурсивную функцию Пола Айриша:

(function() {
    var lastTime = 0;
    var vendors = ['webkit', 'moz'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame =
          window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

Тогда вопрос, как его использовать? Если вы перейдете здесь, вы сможете увидеть, как это было сделано:

function fireLoop()
{
    window.requestAnimationFrame(fireLoop);
    fire.update();
    fire.render();
    console.log('you spin me right round baby right round');
    follow();

}

Это петля, которую я использую. Каждую секунду функция Пола Айриша будет вызывать основной цикл. В этой петле. Я обновляю информацию, выбираю нужную анимацию, которую нужно нарисовать, а затем рисую на холсте (после удаления предыдущего элемента).

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

function follow()
{
        $(fireCanvas).offset({
            top: getTop(),
            left: getLeft()
        });

}

function getTop()
{
    var off = $(fireCanvas).offset();
    if(off.top != currentMousePos.y - $(fireCanvas).height() + 10)
    {
        if(off.top > currentMousePos.y - $(fireCanvas).height() + 10)
        {
            return off.top - 1;
        }
        else
        {
            return off.top + 1;
        }
    }
}
function getLeft()
{
    var off = $(fireCanvas).offset();
    if(off.left != currentMousePos.x - $(fireCanvas).width()/2)
    {
        if(off.left > currentMousePos.x - $(fireCanvas).width()/2)
        {
            return off.left - 1;
        }
        else
        {
            return off.left + 1;
        }     
    }
}
var currentMousePos = { x: -1, y: -1 };
$(document).mousemove(function(event) {
    currentMousePos.x = event.pageX;
    currentMousePos.y = event.pageY;
});

Если вы хотите, чтобы я подробно рассказал о чем-то конкретном, дайте мне знать.

person kemicofa ghost    schedule 15.06.2014