Vue Touch HammerJs Example and Demo

Vue Touch HammerJs Example and Demo are developed using CSS, HTML and HammerJs.

Demo Download

AuthorLisi
CreatedAUGUST 10, 2018
LicenseOpen
Compatible browsersChrome, Firefox, Safari

HTML Snippet

<main class="" id="app" v-pan="onPan"> 	<div class="emoji" ref="emoji">{{ selectedContent }}</div> 	<section class="slider"> 		<ul class="slider__list" ref="list"> 			<li v-for="(animal, index) in animals" :key="animal" 					class="slider__item"  					v-tap="(e) => onTap(e, animal)" 					:style="{backgroundColor: colors[index]}"> 				{{ animal }} 			</li> 		</ul> 	</section> </main>

SCSS Code

.slider { 	width: 100%; 	height: 120px; 	overflow: visible;   position: relative;   white-space: nowrap;  	&__list { 		display: flex; 		width: 100%; 		height: 100%; 		 		font-size: 2rem; 		backface-visibility: hidden; 		transform: translateX(calc(var(--x, 0) * 1%)); 	} 	 	&__item { 		position: relative; 		flex: 0 0 140px; 		 		display: flex; 		justify-content: center; 		align-items: center; 		height: 100%; 		margin-right: 12px; 		padding: 6px; 		box-sizing: border-box; 		 		border-radius: 8px; 		text-align: center;   	transition: opacity 0.15s ease; 		color: #fff;  		&:focus { 			opacity: 0.8; 		} 	} }  .emoji  { 	padding: 40px; 	font-size: 6rem; 	min-height: 6rem; 	backface-visibility: hidden; }    html { 	height: 100%; 	display: flex; 	background: #155e63; }  body {	 	position: relative;  	width: 100%; 	height: 100%; 	max-width:  360px; 	max-height: 640px; 	margin: auto;  	background: #efefef; 	font-family:'Do Hyeon', sans-serif; 	font-size: 16px; }  #app { 	height: 100%; 	width: 100%; 	display: flex; 	flex-direction: column; 	justify-content: center; 	align-items: center; 	padding: 20px; 	box-sizing: border-box; 	 	overflow: hidden; }

JavaScript Snippet

Vue.directive("pan", { 	bind: function(el, binding) { 		if (typeof binding.value === "function") { 			const mc = new Hammer(el); 			mc.get("pan").set({ direction: Hammer.DIRECTION_ALL }); 			mc.on("pan", binding.value); 		} 	} });  Vue.directive("tap", { 	bind: function(el, binding) { 		if (typeof binding.value === "function") { 			const mc = new Hammer(el); 			mc.on("tap", binding.value); 		} 	} });  const app = new Vue({ 	el: "#app", 	data: { 		animals: [ 			"cat", 			"dog", 			"panda", 			"lion", 			"frog", 			"bear", 			"mouse", 			"tiger", 			"monkey" 		], 		emojis: ["ðߐ±", "ðߐ¶", "ðߐ¼", "ð�¦", "🐸", "🐻", "🐹", "🐯", "🐵"], 		colors: [ 			"#F7CC45", 			"#AC6909", 			"#272625", 			"#FFAD01", 			"#81DC58", 			"#C68E71", 			"#F2B2BD", 			"#FFCB00", 			"#BE9763" 		], 		currentOffset: 0, 		selected: "cat" 	}, 	computed: { 		overflowRatio() { 			return this.$refs.list.scrollWidth / this.$refs.list.offsetWidth; 		}, 		itemWidth() { 			return this.$refs.list.scrollWidth / this.animals.length; 		}, 		selectedContent() { 			if (this.selected) { 				return this.emojis[this.animals.indexOf(this.selected)]; 			} 			return ""; 		}, 		count() { 			return this.animals.length 		} 	}, 	watch: { 		selected(newValue) { 			TweenMax.fromTo( 				this.$refs.emoji, 				0.6, 				{ scale: 0 }, 				{ scale: 1, ease: Elastic.easeOut.config(1, 0.8) } 			); 		} 	}, 	methods: { 		onPan(e) { 			const dragOffset = 100 / this.itemWidth * e.deltaX / this.count * this.overflowRatio;  			const transform = this.currentOffset + dragOffset;  			this.$refs.list.style.setProperty("--x", transform);  			if (e.isFinal) { 				this.currentOffset = transform; 				const maxScroll = 100 - this.overflowRatio * 100; 				let finalOffset = this.currentOffset;  				// scrolled to last item 				if (this.currentOffset <= maxScroll) { 					finalOffset = maxScroll; 				} else if (this.currentOffset >= 0) { 					// scroll to first item 					finalOffset = 0; 				} else { 					// animate to next item according to pan direction 					const index = this.currentOffset / this.overflowRatio / 100 * this.count; 					const nextIndex = e.deltaX <= 0 ? Math.floor(index) : Math.ceil(index); 					finalOffset = 100 * this.overflowRatio / this.count * nextIndex; 				}  				// bounce back animation 				TweenMax.fromTo( 					this.$refs.list, 					0.4, 					{ '--x': this.currentOffset }, 					{ 						'--x': finalOffset, 						ease: Elastic.easeOut.config(1, 0.8), 						onComplete: () => { 							this.currentOffset = finalOffset; 						} 					} 				); 			} 		}, 		onTap(e, value) { 			if (value) { 				TweenMax.to(e.target, 0.12, { scale: 1.1, yoyo: true, repeat: 1, ease: Sine.easeOut}) 				this.selected = value; 			} 		} 	} });

Preview

Vue Touch HammerJs Example and Demo preview

W3TWEAKS
Latest posts by W3TWEAKS (see all)

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *