Упрощение анимации Javascript

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

Это моя функция, которая перемещает камеру в то место, где пользователь щелкнул на холсте:

function moveCamera(e,parent){
    clearInterval(parent.scroll);

var mouseData       = mousePos(evt,parent); //get x:y relative to element           
var initial         = {'x':el.width/2,'y':el.height/2},
    target          = {'x':mouseData.x,'y':mouseData.y},            
    deltaX          = target.x-initial.x,
    deltaY          = target.y-initial.y,
    timeStart       = Date.now(),
    timeLength      = 800,
    x,y,deltaTime;

function update(){
    function fraction(t){
        x               = (target.x - initial.x) - (t*deltaX),
        y               = (target.y - initial.y) - (t*deltaY);
        camera.x       -= x;
        camera.y       -= y;
    }
    function easing(x) {
        return 0.5 + 0.5 * Math.sin((x - 0.5) * Math.PI);
    }   

    deltaTime = (Date.now() - timeStart) / timeLength;
    if (deltaTime > 1) {
        fraction(1);
    } else {
        fraction(easing(deltaTime));
    }   
}
parent.scroll = setInterval(update, 10);        
}

Я приложил JSFiddle продемонстрированной проблемы: http://jsfiddle.net/p5xjmLay/< /strong> просто нажмите на холст, чтобы прокрутить до этой позиции, и вы увидите, что это немного сходит с ума.

Мне интересно, как решить эту проблему, чтобы смещение камеры каждый раз менялось правильно?


person Sir    schedule 06.10.2015    source источник
comment
Разве это не то же самое, что stackoverflow.com/questions/32600794/?   -  person Kaiido    schedule 06.10.2015
comment
@Kaiido, это более ранняя версия, когда у меня была другая настройка. Это действительно сработало, но раньше оно устанавливало положение камеры в соответствии с ее местоположением, где я хочу получить разницу и вместо этого обновить смещение камеры для каждого цикла. Кроме того, как вы можете видеть в jsFiddle, он на самом деле не работает после изменений, и я не знаю, почему.   -  person Sir    schedule 06.10.2015


Ответы (1)


Я немного изменил вашу версию, и кажется, что она работает, попробуйте следующее:

    var el      = document.getElementById('canvas'),
    initial         = {'x':el.width/2,'y':el.height/2},
    ctx     = el.getContext('2d'),
    camera  = {'x':el.width/2,'y':el.height/2},
    box     = {'x':0,'y':0};
    var x,y,deltaTime;

    el.addEventListener('mousedown',function(e){moveCamera(e,this);},false);

function moveCamera(e,parent){
        clearInterval(parent.scroll);

    var mouseData       = mousePos(e,parent);                       
        target          = {'x':mouseData.x,'y':mouseData.y},            
        deltaX          = target.x-initial.x,
        deltaY          = target.y-initial.y,
        timeStart       = Date.now(),
        timeLength      = 800;


    function update(){
        function fraction(t){
            x               = target.x - (initial.x + (t*deltaX)),
            y               = target.y - (initial.y + (t*deltaY));

            if (Math.abs(camera.x + x - target.x) > Math.abs(camera.x - target.x)) {
                camera.x = target.x;
                initial.x = target.x;
            } else {
                camera.x       += x;                
            }

            if (Math.abs(camera.y + y - target.y) > Math.abs(camera.y - target.y)) {
                camera.y = target.y;
                initial.y = target.y;
            } else {
                camera.y       += y;                
            }            

        }
        function easing(x) {
            return 0.5 + 0.5 * Math.sin((x - 0.5) * Math.PI);
        }   

        deltaTime = (Date.now() - timeStart) / timeLength;
        if (deltaTime > 1) {
            fraction(1);
        } else {
            fraction(easing(deltaTime));
        }
        draw(); 
    }
    parent.scroll = setInterval(update, 200);       
}

function mousePos(evt,el){
        var offsetX = 0,
            offsetY = 0;        
        do{
            offsetX += el.offsetLeft - el.scrollLeft;
            offsetY += el.offsetTop  - el.scrollTop;
        }while(el = el.offsetParent){
            return {'x':evt.pageX - offsetX, 'y':evt.pageY - offsetY}       
        }       
}

function draw(){

    ctx.clearRect(0,0,el.width,el.height);

    ctx.save();
    ctx.translate(camera.x,camera.y);     

    ctx.beginPath();
    ctx.rect(box.x-25, box.y-25,50,50);
    ctx.fillStyle = 'red';
    ctx.fill(); 

    ctx.restore();           
}
draw();
person Miguel Salto    schedule 06.10.2015
comment
Можете ли вы объяснить логику того, что вы изменили, чтобы я понял, где я ошибся - person Sir; 06.10.2015
comment
В основном я применил 3 вещи: 1) Исправил инкремент для camera.x и camera.y, в функции дроби у вас было camera.x -= x (и то же самое для camera.y) и я понял, что канвас собирается прочь, а не приближаться, поэтому я изменил выражение на camera.x += x. - person Miguel Salto; 06.10.2015
comment
2) Когда я исправил приращение для camera.x, я понял, что холст продолжает двигаться вперед, даже когда цель была достигнута, затем я добавил условие, чтобы увидеть, больше ли разница между camera.x + x и target.x, чем camera.x - target.x, если да, то это значит, что если я присвою camera.x += x, я передам цель, то я присвоил значение target camera.x = target.x (то же самое для camera.y ) - person Miguel Salto; 06.10.2015
comment
3) Когда я достиг цели, пришло время обновить начальные координаты холста, чтобы позволить продолжить следующий клик, начиная с текущей позиции: initial.x = target.x (и то же самое для initial.y). Надеюсь, я дал вам хорошее объяснение, привет. - person Miguel Salto; 06.10.2015
comment
Для меня это просто перемещает поле с молниеносной скоростью, я не вижу анимации плавности, которая занимает 800 миллисекунд ... поэтому я бы сказал, что это на самом деле не работает. См. здесь: jsfiddle.net/mmcfvr9t — ваш ответ не использует t, который передается функции fraction - person Sir; 06.10.2015
comment
Конечно, в версии, которую я написал, используется t, см.: x = (target.x - initial.x) - (t*deltaX). Я дал вам подсказку. Вам решать изменять свои приращения, чтобы получить желаемую анимацию, привет. - person Miguel Salto; 07.10.2015