fancy-carousel-animations.html
<script>
FancyCarouselAnimations = (superClass) => class extends superClass {
connectedCallback() {
if(super.connectedCallback) {
super.connectedCallback();
}
this._preloadAnimationSprites();
}
ready() {
this.addEventListener('transitionend', this._resetChildrenStyles);
this.addEventListener('touchstart', this._touchstart);
this.addEventListener('touchmove', this._touchmove);
this.addEventListener('touchend', this._touchend);
super.ready();
}
_getNatureSpriteUrl() {
return "url('" + this.resolveUrl('images/nature-sprite.png') + "')";
}
_getUrbanSpriteUrl() {
return "url('" + this.resolveUrl('images/urban-sprite.png') + "')";
}
_getShiftSpriteUrl() {
return "url('" + this.resolveUrl('images/building-sprite.png') + "')";
}
_getCollaspeSpriteUrl() {
return "url('" + this.resolveUrl('images/building-sprite-2.png') + "')";
}
_preloadAnimationSprites() {
var spriteElem = document.createElement('div');
if (this.transitionType === 'spread') {
spriteElem.style.backgroundImage = this._getNatureSpriteUrl();
} else if (this.transitionType === 'paint') {
spriteElem.style.backgroundImage = this._getUrbanSpriteUrl();
} else if (this.transitionType === 'collapse') {
spriteElem.style.backgroundImage = this._getShiftSpriteUrl();
} else if (this.transitionType === 'shift') {
spriteElem.style.backgroundImage = this._getCollaspeSpriteUrl();
}
spriteElem.className = "preloaded-sprite";
spriteElem.style.visibility = "hidden";
Polymer.dom(this).appendChild(spriteElem);
}
_resetZIndex(elements, current) {
for (var i = 0; i < elements.length; i++) {
if (current && current.src === elements[i].src) {
elements[i].style.zIndex = "20";
} else {
elements[i].style.zIndex = "10";
}
}
}
_startTransition(direction, selected, nextElem) {
if (this.transitionType === 'spread' ||
this.transitionType === 'paint' ||
this.transitionType === 'shift' ||
this.transitionType === 'collapse') {
this._animateTransition(direction, selected, nextElem);
} else {
if (this._isWorking) return;
this._isWorking = true;
nextElem.style.zIndex = "50";
var oldSelected = selected;
this._translateX(oldSelected, 0);
this._translateX(nextElem, this.offsetWidth*direction);
// Start the transition
this.selected = nextElem;
this._translateX(oldSelected, -this.offsetWidth*direction, true /* transition */);
this._translateX(nextElem, 0, true /* transition */);
this._resetZIndex(Polymer.dom(this).children, selected);
nextElem.style.zIndex = "100";
this._isWorking = false;
}
}
_animateTransition(direction, selected, nextElem) {
var self = this;
if (self._isWorking) return;
self._isWorking = true;
selected.style.zIndex = "30";
nextElem.style.zIndex = "20";
var spriteUrl;
if (this.transitionType === 'spread') {
spriteUrl = this._getNatureSpriteUrl();
} else if (this.transitionType === 'paint') {
spriteUrl = this._getUrbanSpriteUrl();
} else if (this.transitionType === 'collapse') {
spriteUrl = this._getCollaspeSpriteUrl();
} else if (this.transitionType === 'shift') {
spriteUrl = this._getShiftSpriteUrl();
}
self._updateSelectedStyles(selected, this.transitionType, spriteUrl, '1400ms', '0ms', 'mask-play');
setTimeout(function() {
self._updateSelectedStyles(selected, '', '', '', '', '');
selected.style.zIndex = "10";
nextElem.style.zIndex = "30"
self.selected = nextElem;
self._isWorking = false;
}, 1400);
}
_updateSelectedStyles(element, className, spriteUrl, animationDuration, animationDelay, animationName) {
element.className = className;
element.style.mask = spriteUrl;
element.style.webkitMask = spriteUrl;
element.style.webkitMaskImage = spriteUrl;
element.style.animationName = animationName;
}
_resetChildrenStyles() {
var elem = this.firstElementChild;
while (elem) {
elem.style.display = '';
elem.style.transition = '';
elem.style.transform = '';
elem = elem.nextElementSibling;
}
}
_translateX(elem, x, transition) {
elem.style.display = 'block';
elem.style.transition = transition ? 'transform 0.2s' : '';
elem.style.transform = 'translate3d(' + x + 'px, 0, 0)';
}
_touchstart(event) {
// No transition if less than two images
if (this.childElementCount < 2) {
return;
}
// Save start coordinates
if (!this._touchDir) {
this._startX = event.changedTouches[0].clientX;
this._startY = event.changedTouches[0].clientY;
}
}
_touchmove(event) {
// No transition if less than two images
if (this.childElementCount < 2) {
return;
}
// Is touchmove mostly horizontal or vertical?
if (!this._touchDir) {
var absX = Math.abs(event.changedTouches[0].clientX - this._startX);
var absY = Math.abs(event.changedTouches[0].clientY - this._startY);
this._touchDir = absX > absY ? 'x' : 'y';
}
if (this._touchDir === 'x') {
// Prevent vertically scrolling when swiping
event.preventDefault();
var dx = Math.round(event.changedTouches[0].clientX - this._startX);
var prevChild = this.selected.previousElementSibling;
var nextChild = this.selected.nextElementSibling;
// Don't translate past the current image if there's no adjacent image in that direction
if ((!prevChild && dx > 0) || (!nextChild && dx < 0)) {
dx = 0;
}
this._translateX(this.selected, dx);
if (prevChild) {
this._translateX(prevChild, dx - this.offsetWidth);
}
if (nextChild) {
this._translateX(nextChild, dx + this.offsetWidth);
}
}
}
_touchend(event) {
// No transition if less than two images
if (this.childElementCount < 2) {
return;
}
// Don't finish swiping if there are still active touches.
if (event.touches.length) {
return;
}
if (this._touchDir === 'x') {
var dx = Math.round(event.changedTouches[0].clientX - this._startX);
var prevChild = this.selected.previousElementSibling;
var nextChild = this.selected.nextElementSibling;
// Don't translate past the current image if there's no adjacent image in that direction
if ((!prevChild && dx > 0) || (!nextChild && dx < 0)) {
dx = 0;
}
if (dx > 0) {
var prevChild = this.selected.previousElementSibling;
if (prevChild) {
if (dx > 100) {
if (dx === this.offsetWidth) {
// No transitionend will fire (since we're already in the final state),
// so reset children styles now
this._resetChildrenStyles();
} else {
this._translateX(prevChild, 0, true);
this._translateX(this.selected, this.offsetWidth, true);
}
this.selected = prevChild;
} else {
this._translateX(prevChild, -this.offsetWidth, true);
this._translateX(this.selected, 0, true);
}
}
} else if (dx < 0) {
var nextChild = this.selected.nextElementSibling;
if (nextChild) {
if (dx < -100) {
if (dx === -this.offsetWidth) {
// No transitionend will fire (since we're already in the final state),
// so reset children styles now
this._resetChildrenStyles();
} else {
this._translateX(this.selected, -this.offsetWidth, true);
this._translateX(nextChild, 0, true);
}
this.selected = nextChild;
} else {
this._translateX(this.selected, 0, true);
this._translateX(nextChild, this.offsetWidth, true);
}
}
} else {
// No transitionend will fire (since we're already in the final state),
// so reset children styles now
this._resetChildrenStyles();
}
}
// Reset touch direction
this._touchDir = null;
}
};
</script>