javascript плавная анимация от X, Y до X1, Y1

Я хотел бы плавно переместить изображение (или элемент) из его фактического местоположения X, Y в X1, Y1.

Когда расстояние между X и X1 равно расстоянию между Y и Y1, это легко. Но что, если разница по оси X составляет, скажем, 100 пикселей, а разница по оси Y — 273 пикселя?

Будучи новичком в Javascript, я не хочу изобретать велосипед! Кроме того, поскольку я учусь, я НЕ хочу использовать jQuery или тому подобное. Я хочу чистый javascript.

Пожалуйста, предоставьте простой скрипт :-)


person Didier Levy    schedule 17.09.2011    source источник
comment
Я предполагаю, что элемент абсолютно позиционирован...   -  person Šime Vidas    schedule 17.09.2011
comment
@scessor Определить нечистый JavaScript :)   -  person Šime Vidas    schedule 17.09.2011
comment
@Šime Вот что я имею в виду: нечистого javascript не существует.   -  person scessor    schedule 17.09.2011
comment
@epascarello Нет проблем в том, что Дидье не хочет использовать jQuery. Но если кто-то говорит, что не хочет изобретать велосипед, он хочет библиотеку. jQuery и прочие как раз об этом.   -  person scessor    schedule 17.09.2011
comment
@scessor Иногда, когда нужно выполнить простую задачу, нет необходимости загружать относительно большую библиотеку.   -  person duri    schedule 17.09.2011


Ответы (4)


Одно решение:

function translate( elem, x, y ) {
    var left = parseInt( css( elem, 'left' ), 10 ),
        top = parseInt( css( elem, 'top' ), 10 ),
        dx = left - x,
        dy = top - y,
        i = 1,
        count = 20,
        delay = 20;

    function loop() {
        if ( i >= count ) { return; }
        i += 1;
        elem.style.left = ( left - ( dx * i / count ) ).toFixed( 0 ) + 'px';
        elem.style.top = ( top - ( dy * i / count ) ).toFixed( 0 ) + 'px';
        setTimeout( loop, delay );
    }

    loop();
}

function css( element, property ) {
    return window.getComputedStyle( element, null ).getPropertyValue( property );
}

Текущая демонстрация: http://jsfiddle.net/qEVVT/1/

person Šime Vidas    schedule 17.09.2011
comment
Требование! :-) Спасибо, что поделились, это именно то, что я искал. - person Didier Levy; 17.09.2011
comment
У меня это тоже работает, за исключением старого доброго Internet Explorer. Да, мой div позиционируется абсолютно. Я протестировал скрипт/методы со всеми видами div-элементов, но в IE ничего не двигается. - person huzzm; 18.08.2016
comment
Вот почему: window.getComputedStyle( element, null ).getPropertyValue( property ) просто возвращает «auto» в Internet Explorer, тогда как во всех других браузерах это число с окончанием «px». Но я не знаю, как решить проблему. - person huzzm; 18.08.2016
comment
Хорошо, я решил свою проблему, добавив left: 0px; к моему div-элементу. - person huzzm; 18.08.2016

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

Лучший способ сделать это — встать на плечи других и использовать то, что было изобретено ранее. В наше время я бы никогда не попытался написать это сам с нуля. Его можно использовать в переходах/анимациях CSS3, но они еще не везде поддерживаются. Его можно использовать или анализировать в jQuery и YUI3. Мой первый выбор — использовать один из фреймворков с богатым набором возможностей. Вам не нужно использовать фреймворк ни для чего другого, вы можете просто использовать его для анимации, если хотите. YUI3 даже позволит вам создать библиотеку с наименьшим количеством кода именно для того, что вы хотите. jQuery не очень большой для начала.

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

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

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

Firefox и Chrome также внедрили несколько новых экспериментальных API, помогающих с плавной анимацией. Я обнаружил это сам, просматривая исходный код jQuery, потому что он использует его, когда он доступен. В Chrome он называется webkitRequestAnimationFrame, и вы можете прочитать о нем здесь, в записи блога Firefox. .

person jfriend00    schedule 17.09.2011

Если вы ориентируетесь на современные браузеры, переходы CSS упрощают жизнь (пример для firefox, для других браузеров измените префикс -moz):

<body>
    <input type="button" onclick="move()" value="press" />
    <div id="sq" style="position:absolute; top:50px; left:50px; height:50px; width:50px; background-color:Black; -moz-transition : all 0.8s ease 0s;" />
</body>

И сценарий

 function move() {
            var sq = document.getElementById("sq");
            sq.style.left = "300px";
            sq.style.top = "150px";
        }
person Alejandro Martin    schedule 17.09.2011

Если бы я собирался написать это с нуля, я бы начал с чего-то вроде этого:

function linearEase(start, end, percent) {
    return start + ((end - start) * percent);
}

function animateTo(settings) {
    var elem = settings.element;
    var ease = settings.ease;

    var start = { left: elem.offsetLeft, top: elem.offsetTop };

    var lastTime = new Date().getTime();
    var timeLeft = settings.totalTime;

    function update() {
        var currentTime = new Date().getTime();
        var elapsed = currentTime - lastTime;
        timeLeft -= elapsed;
        lastTime = currentTime;

        var percentDone = 1 - timeLeft/settings.totalTime;

        elem.style.top = ease(start.top, settings.top, percentDone) + "px" ;
        elem.style.left = ease(start.left, settings.left, percentDone) + "px" ;

        if(timeLeft > 0) {
            setTimeout(update, 33);
        }   
    }

    update();
}

Например, чтобы переместить div на (50,50) в течение следующих двух секунд.

var elem = document.getElementById("animatable");

setTimeout(function() {
    animateTo({
        element: elem, 
        left: 50, 
        top: 50, 
        totalTime: 2000,
        ease: linearEase
    })
}, 10);

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

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

Кроме того, если вы одновременно анимируете кучу элементов, я бы определенно реорганизовал это в один «цикл рендеринга». вызовы animateTo подталкивают воркеров в очередь воркеров, но есть только цикл setTimeout, который вычисляет прошедшее время, а затем вызывает каждого воркера, так что у вас нет плавающих вокруг базилиона timeout замыканий.

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

person J. Holmes    schedule 17.09.2011
comment
Просто предупреждение. ease не поддерживается сафари - person user2831723; 28.03.2019