Как стать автором
Обновить

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

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

Мы в компании разрабатывали продукт, клиентская часть которого должна была быть написана на чистом Javascipt.
Видимо, требование к проекту было воспринято максимально буквально )

Никто не мешает CSS-анимацию использовать из JS, они же все равно обращаются к style в коде...

НЛО прилетело и опубликовало эту надпись здесь
Знаете, я ждал подобных комментариев.

Первый говорит об альтернативном способе воспроизведения анимации (без JS), второй предлагает готовое решение.

Между тем, кмк, в описании задачи (я подчеркнул это слово, потому что решение было в рамках бизнес-задачи, а не свободного творчества) недвусмысленно сказано, что:
а) Это всё должно успешно работать на IE8
б) Сторонний код принципиально недопустим

Предлагаю данную тему рассматривать в разрезе решения конкретно поставленной задачи, а не как попытку осмыслить, как бы не решать её, а заняться какой-то другой.

А зачем обсуждать странную полутрогодовалую задачу? Особенно в сфере веба, где технологии меняются очень быстро. Поддерживать ie8 в 2016 не надо. Доля восьмёрки чуть меньше нуля. Даже MS теперь довольно агрессивно обновляет свои продукты и внедряет стандарты в браузеры.


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

Не, я понимаю
— нет же, вы не понимаете :)

Я прямо словами написал, что продукт используется в разных странах. В том числе, таких, где доля IE8 до сих пор значительна.

Здесь, возможно, может последовать вполне предсказуемый холивар на тему, а зачем сотрудничать с такими компаниями, зачем продавать в такие страны, а зачем программисту горбатится в компаниях, которые разрабатывают такое «старое г-но». Но я, право, не имею никакого желания заниматься праведной борьбой в пучине этого платоновского моря чистой мысли :)

Нет, я не буду спорить с кем и чем вам стоит работать, это сугубо ваше дело.


У меня такой вопрос: если вы так жаждете обсуждения иных подходов при такой поставленной задаче, вы смотрели готовые решения? Не с целью их использовать, а с целью изучить подход. Если да, то какие и почему они не подошли?


Когда мне понадобилилась библиотека для анимации я быстро нашёл GSAP, ссылку на который я уже кидал. Полтора года назад он уже точно был. Библиотека имеет довольно маленькое ядро, и при этом очень быстрая и поддерживает всё вплоть до ie6.

Это "а" и "б" вы сейчас добавили, а в статье было так:


1) Анимируется любой элемент на странице, количество элементов не ограничено
2) Список анимируемых свойств задан (линейные размеры, положение, отступы, прозрачность)
3) Анимация должна управляться через параметры (время исполнения, функция скорости исполнения)
4) По завершению анимации вызывается любой произвольный коллбэк
5) Анимация в любой момент может быть прервана

Т. е. вполне резонные вопросы в комментариях. IE8 — уже экзотика, не всем понятно зачем его поддерживать по умолчанию, у такого решения должно быть очень веское обоснование, о котором Вы умолчали.

Почему setInterval, а не requestAnimationFrame?
Я думаю, поэтому: http://caniuse.com/#search=requestAnimationFrame

Кто мешает проверить поддерживает ли браузер requestAnimationFrame и использовать его, если это возможно? С фолбеком на setInterval, разумеется.

Почему в коде одни свитчи. И зачем огородить огород? На твоем маке тормозов не наблюдается?
Предложите, как сделать лучше, я с удовольствием ознакомлюсь.
Тормозит в разумных пределах не только на Маке, но даже на стареньких андроидах. Тестирование продукта у нас поставлено достаточно хорошо, он продаётся в разные страны

Лучше — реализовать анимацию через CSS и "изящно деградировать". Это избавит от тормозов на современных системах и на старых с IE8 тем более.

Я всё-таки проявлю упорство и переспрошу: как лучше организовать JS-код?
Извини, может это дело вкуса, но считаю что каждый свитч есть отдельная функция. Просто так кажется лучше
function getProgress(p) {
    switch (options.easing) {
        case 'linear' : return p; break;
        case 'swing' : return 0.5 - Math.cos(p * Math.PI ) / 2; break
        case 'quad' : return Math.pow(p, 2); break;
        case 'cubic' : return Math.pow(p, 3); break;
        default : return p;
    }
}

можно изменить на


const getProgress = (progress) => {
    const easeFn = {
        swing: progress => (0.5 - Math.cos(progress * Math.PI ) / 2),
        cubic: progress => (Math.pow(progress, 3)),
        quad: progress => (Math.pow(progress, 2))
    }[options.easing];

    return easeFn ? easeFn(progress) : progress;
}
Сразу создаём var $ = {d: window.document, w: window}, чтобы не лезть прямо в window.

И тут же


$.w.ltAnimate = function (el, props, opts, cb) {});

Судя по всему, чтобы лезть в window через определенное отверстие? И да, Люк, не гадь в глобальный скоуп.


setInterval

Есть аж, наверное, 3 причины, почему нельзя использовать setInterval, даже если оооочень хочется. Это даже типовой вопрос на middle frontend developer.


Вопрос на senior: почему следует избегать try-catch в js? (Вдобавок, зачем он используется тут вместо проверки существования функции?).


Ну и да, таймауты, поджидающие конец интервалов — у вас никогда более-менее сложная анимация не сойдется. (Подсказка, js не гарантирует, что setTimeout(..., 1000) выполнится через секунду. Более того, даже примерно это не обещает).

Судя по всему, чтобы лезть в window через определенное отверстие?

Совершенно верно. Но вообще, код выдернут из некой библиотеки, так что обвязка весьма условна. Впрочем, и не она суть темы.
Вдобавок, зачем он используется тут вместо проверки существования функции?
Всё просто: что делать, если во время исполнения коллбэка (мы не знаем, что туда напхают) вылезет exception?

А вот как избежать try-catch, я бы сам заслушал. Пока ещё не senior, есть, чему учиться
  1. Подобным образом пишут чтобы как раз не писать в глобальный scope в js. Почитайте umd, лучше сделать так. В window желательно вообще ничего лишнего, тем более в 2016 веке с поголовным es6 import, require.js и подобными технологиями.
    Если же беспокоитесь, что кто-то там странно и криво вызовет вашу библиотеку в неожиданных местах — это уже скорее его проблемы, покуда там либо будут глобально доступны setTimeout и иже с ним, либо подобным вариантом уже не спасти.


  2. setInterval никогда нельзя использовать в js, покуда движок будет ставить, допустим, каждые 50 мс событие в очередь независимо от того, успела ли очередь выполнения рассосаться или нет. Как не сложно догадаться — если время, через которое по интервалу будут добавляться события меньше, чем время рассасывания этих сообщений, у вас все застрянет наглухо и в какой-то момент попросту повиснет. Ну и что уж говорить про то, что в таком случае желаемые 50 мс будут даже близко не равны реальным, что будет выглядеть дерганно в конечной анимации. И это прям совсем не редкая ситуация.


  3. а: в данном случае в вашей библиотеке достаточно написать if (options.sucess) options.success();
    (ну или options.success && options.success(); если вы js-ninja, хотя этот вариант не читаемый, так что не стоит).
    Если оно упадет в этой функции — заботы того, кто использует библиотеку. Более того, своей оберткой над этим вы только навредите, покуда найти источник ошибки будет сложнее.
    б: есть 3 условия, которые должны быть выполнены для того, чтобы движок webkit мог скомпилировать функцию в нативный байт-код. Так получилось, что отсутствие блока try-catch одно из них. Обычно это не столь важно (в вашем примере так же не важно), однако в целом когда речь про какую-либо анимацию на js — позволять скомпилировать webkit-y код в нативный идея хорошая. (Кто не знает, два других условия: вроде как функция должна быть вызвана не менее 100 раз и у функции не должны меняться типы входных значений. И это справедливо только для webkit, про другие движки не скажу. Впрочем, это тоже вероятно поменялось, документации по этому особо нет).
1. Нет, здесь только чистый JS, никаких require и прочих библиотек. До ES6 тоже ещё очень далеко. Но это так, заметка, по сути это вопрос на отдельную тему.

2. Вот тут интереснее. Interval всё-таки существует в JS. Значит, это инструмент, который нужно использовать по назначению.
Для функции я сделал очередь входящих вызовов. Конечно, её можно забить, вызвав, допустим, 1000 раз с с разницей в 1мс (думаю, при таких условиях любой браузер просто повиснет). Однако, ровно так же повиснет и jQuery-анимация, и любая другая, сделанная именно на JS. Тут мы упираемся в возможности связки язык + браузер. Для практического же применения (несколько анимируемых элементов на странице, не тысяча) моё решение, безусловно, подходит, и неплохо работает. Поэтому утверждение "setInterval никогда нельзя использовать в js" мне не кажется разумным. Каждый раз надо разбираться.

3. «Если оно упадет в этой функции — заботы того, кто использует библиотеку» — такой подход тоже является спорным. Точнее, так: можно сделать обработку ошибок, можно не делать. В данном случае, как я вижу, «призом» за отказ от обработки является некоторые призрачные шансы, что webkit скомпилирует нативный байт-код. Не очень железно. Хотя за подсказку идеи Вам спасибо, раньше об этом не слышал.
Скрытый текст
Хотел написать комментарий о том что в интернете кто-то не прав, но я полностью согласен с предыдущими комментариями, а после этого ответа автора вообще отпала необходимость что-либо комментировать.

Автор, я решительно рекомендую Вам заняться самообучением, посмотреть best practice, пописать код для души. Javascript уже совсем не тот что был раньше, он сейчас намного прекраснее и становится лучше с каждой новой ревизией.
Весьма нерентабельно, но интересно и познавательно в плане «сделай сам». Автору спасибо :)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории