A Pen by Sean Seltzer on CodePen.
Created
February 16, 2017 03:39
-
-
Save sseltzer/25c5dc1c923511bd39555ba684bd956d to your computer and use it in GitHub Desktop.
Vue CSS Anim Test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <script src="https://unpkg.com/vue/dist/vue.js"></script> | |
| <div id="slider" class="slider"> | |
| <div v-for="(item, index) in items" class="item" v-bind:style="item" v-bind:index="index"/> | |
| </div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| let slider = new Vue({ | |
| el: '#slider', | |
| data: { | |
| items: [ | |
| {background: '#1A237E'}, | |
| {background: '#283593'}, | |
| {background: '#303F9F'}, | |
| {background: '#3949AB'}, | |
| {background: '#3F51B5'}, | |
| {background: '#5C6BC0'}, | |
| {background: '#7986CB'} | |
| ] | |
| }, | |
| methods: { | |
| setElementIndex: function() { | |
| this.itemElements = document.querySelectorAll('.item'); | |
| }, | |
| update: function() { | |
| console.log('update') | |
| if (this.animate) requestAnimationFrame(this.update); | |
| if (!this.target) return; | |
| if (this.dragging) this.updateItem(this.currentX - this.startX); | |
| else if (this.remove) this.slideAway(); | |
| else this.resetItem(); | |
| }, | |
| updateItem: function(translationX) { | |
| this.target.style.transform = `translateX(${translationX}px)`; | |
| this.target.style.opacity = 1 - Math.abs(this.originX - this.target.getBoundingClientRect().left) / this.target.getBoundingClientRect().width; | |
| }, | |
| onDown: function(event) { | |
| this.$el.style.willChange = 'transform'; | |
| this.originX = this.$el.getBoundingClientRect().left; | |
| this.startX = event.pageX || event.touches[0].pageX; | |
| this.dragging = true; | |
| this.itemElements.forEach((item, i) => { if (item === event.target) this.index = i; }); | |
| this.target = this.itemElements[this.index]; | |
| if (this.target) { | |
| this.animate = true; | |
| requestAnimationFrame(this.update); | |
| } | |
| }, | |
| onMove: function(event) { | |
| this.currentX = event.pageX || event.touches[0].pageX || 0; | |
| }, | |
| onUp: function(event) { | |
| if (this.itemElements.length < 1 || !this.target) return; | |
| this.dragging = false; | |
| this.releaseX = this.target.getBoundingClientRect().left; | |
| this.slideOffset = this.target.getBoundingClientRect().left - this.originX; | |
| this.remove = (Math.abs(this.currentX - this.startX) > (this.$el.getBoundingClientRect().width * .55)); | |
| }, | |
| resetItem: function() { | |
| let easing = (this.originX - this.target.getBoundingClientRect().left) * .8; | |
| let translationX = this.target.getBoundingClientRect().left + (this.currentX - this.startX < 0) ? -easing : easing; | |
| // Snap the easing algorithm & check for corner case 0 to ensure no mem leaks. | |
| if (Math.abs(this.originX - this.target.getBoundingClientRect().left) < 2 || translationX == 0 || easing == 0) { | |
| translationX = 0; | |
| this.updateItem(translationX); | |
| this.target.style.willChange = 'initial'; | |
| this.target.style.transform = 'none'; | |
| this.animate = false; | |
| this.index = -1; | |
| this.target = null; | |
| return; | |
| } | |
| this.updateItem(translationX); | |
| }, | |
| slideAway: function() { | |
| let direction = (this.releaseX < this.originX) ? -1 : 1; | |
| let easing = (this.originX + direction * this.target.getBoundingClientRect().width - this.releaseX) / 10; | |
| this.slideOffset += easing; | |
| this.updateItem(this.slideOffset); | |
| if (this.target.getBoundingClientRect().left < this.originX - this.target.getBoundingClientRect().width || | |
| this.target.getBoundingClientRect().left > this.originX + this.target.getBoundingClientRect().width) | |
| this.deleteItem(); | |
| }, | |
| deleteItem: function() { | |
| let onAnimationComplete = (event) => { | |
| event.target.removeEventListener( 'transitionend', onAnimationComplete ); | |
| event.target.style.transition = ''; | |
| event.target.style.transform = ''; | |
| this.animate = false; | |
| }; | |
| for (let i = this.index + 1; i < this.itemElements.length; ++i) { | |
| this.itemElements[i].style.transform = `translateY( ${ this.itemElements[i - 1].getBoundingClientRect().height }px )`; | |
| this.itemElements[i].addEventListener( 'transitionend', onAnimationComplete ); | |
| } | |
| this.target.parentNode.removeChild(this.target); | |
| requestAnimationFrame( () => { | |
| for (let i = this.index + 1; i < this.itemElements.length; ++i) { | |
| this.itemElements[i].style.transition = `transform 150ms cubic-bezier( 0,0,0.31,1 ) ${ i * 50 }ms`; | |
| this.itemElements[i].style.transform = ''; | |
| } | |
| }); | |
| this.setElementIndex(); | |
| this.index = -1; | |
| this.target = null; | |
| } | |
| }, | |
| mounted: function() { | |
| this.setElementIndex(); | |
| document.addEventListener( 'mousedown', this.onDown ); | |
| document.addEventListener( 'mousemove', this.onMove ); | |
| document.addEventListener( 'mouseup', this.onUp ); | |
| document.addEventListener( 'touchstart', this.onDown ); | |
| document.addEventListener( 'touchmove', this.onMove ); | |
| document.addEventListener( 'touchend', this.onUp ); | |
| } | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| * { | |
| box-sizing: border-box; | |
| } | |
| html, body { | |
| margin: 0; | |
| padding: 0; | |
| background: #fafafa; | |
| font-family: arial; | |
| font-size: 30px; | |
| } | |
| .slider { | |
| width: 100%; | |
| max-width: 450px; | |
| margin: 0 auto; | |
| } | |
| .item { | |
| height: 100px; | |
| cursor: pointer; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment