Я недоволен существующими библиотеками параллакса, поэтому я пытаюсь написать свои собственные. Мой текущий состоит из трех основных классов:
-
ScrollDetector
отслеживает позицию прокрутки элемента относительно экрана; он имеет функции для возврата float, представляющего его текущую позицию:-
0
представляет верхний край элемента, находящийся в нижнем краю окна просмотра. -
1
представляет нижний край элемента, находящегося на верхнем краю окна просмотра. - Все остальные позиции интерполируются/экстраполируются линейно.
-
-
ScrollAnimation
использует экземплярScrollDetector
для интерполяции произвольных значений CSS для другого элемента на основе элементаScrollDetector
. -
ParallaxativeAnimation
extendsScrollAnimation
для специального случая фонового изображения, которое должно прокручиваться с точным коэффициентом скорости прокрутки окна.
Моя текущая ситуация такова:
-
ScrollAnimation
с помощьюtransform: translateY(x)
работает плавно. -
ParallaxativeAnimation
с помощьюtranslateY(x)
работает, но оживляется. -
ParallaxativeAnimation
с использованиемtranslate3d(0, x, 0)
являются отрывистыми, но не так сильно. - Анимированные библиотеки Rellax, которые используют
translate3d(0, x, 0)
, работают совершенно гладко.
Вы можете увидеть сравнение в этом пером. (В Firefox Firefox выглядит лучше всего). Моя библиотека в Bitbucket.
Я не знаю, где лежит проблема в моей библиотеке, и я не знаю, как это понять. Вот сокращенная паста, где тяжелый подъем выполняется при прокрутке в классе ScrollAnimation
, который работает плавно:
getCSSValue(set, scrollPosition) {
return set.valueFormat.replace(set.substitutionString, ((set.endValue - set.startValue) * scrollPosition + set.startValue).toString() + set.unit)
}
updateCSS() {
var cssValues = [];
var scrollPosition = this.scrollDetector.clampedRelativeScrollPosition();
var length = this.valueSets.length;
for(var i = 0; i < length; i++) {
cssValues.push(getCSSValue(valueSets[i], scrollPosition) );
}
this.setCSS(cssValues);
this.ticking = false;
}
requestUpdate() {
if(!this.ticking) {
requestAnimationFrame(() => { this.updateCSS(); });
}
this.ticking = true;
}
И здесь эквивалент в классе ParallaxativeAnimation
, который является отрывистым:
updateCSS() {
var scrollPosition = this.scrollDetector.clampedRelativeScrollPosition();
var cssValues = [];
var length = this.valueSets.length;
for(var i = 0; i < length; i++) {
var scrollTranslate = -((this.scrollTargetSize - this.valueSets[i].parallaxSize) * scrollPosition);
cssValues.push(
this.valueSets[i].valueFormat.replace(this.valueSets[i].substitutionString, scrollTranslate.toString() + 'px')
);
}
this.setCSS(cssValues);
this.ticking = false;
}
requestUpdate() {
if(!this.ticking) {
requestAnimationFrame(() => { this.updateCSS(); });
}
this.ticking = true;
}
Математика не кажется более сложной, поэтому я не могу понять, как это влияет на производительность анимации. Я думал, что разница может быть моим стилем на изображении параллакса, но в ручке выше, версия Rellax имеет тот же самый CSS на нем, но анимируется совершенно гладко. Кажется, что Rellax может делать более сложную математику на каждом кадре:
var updatePosition = function(percentage, speed) {
var value = (speed * (100 * (1 - percentage)));
return self.options.round ? Math.round(value) : Math.round(value * 100) / 100;
};
//
var update = function() {
if (setPosition() && pause === false) {
animate();
}
// loop again
loop(update);
};
// Transform3d on parallax element
var animate = function() {
for (var i = 0; i < self.elems.length; i++){
var percentage = ((posY - blocks[i].top + screenY) / (blocks[i].height + screenY));
// Subtracting initialize value, so element stays in same spot as HTML
var position = updatePosition(percentage, blocks[i].speed) - blocks[i].base;
var zindex = blocks[i].zindex;
// Move that element
// (Set the new translation and append initial inline transforms.)
var translate = 'translate3d(0,' + position + 'px,' + zindex + 'px) ' + blocks[i].transform;
self.elems[i].style[transformProp] = translate;
}
self.options.callback(position);
};
Единственное, что я могу сказать от Chrome Developer Tools, это то, что частота кадров не опускается слишком далеко ниже 60 кадров в секунду, так что, возможно, это не то, что я делаю слишком много работы в каждом кадре, но что я делаю что-то математически неверно, когда я вычисляю позицию?
Так что я не знаю. Я явно в голове. Мне жаль бросать целую библиотеку в StackOverflow и говорить "FIX IT", но если кто-то может сказать, что я делаю неправильно, или расскажите, как использовать инструменты для разработчиков, чтобы понять, что я делаю неправильно, я Я очень ценю это.
ИЗМЕНИТЬ
Хорошо, я понял, что самым важным фактором в дрожании прокрутки является высота переводимого элемента. У меня был просчет в моей библиотеке, который заставлял фоновое изображение быть намного выше, чем нужно, когда мое свойство scrollPixelsPerParallaxPixel
было высоким. Я сейчас пытаюсь исправить это.