Skip to content

Instantly share code, notes, and snippets.

@ekibun
Last active September 18, 2019 08:25
Show Gist options
  • Save ekibun/986ee31691b290dd95f4428a46cbeec2 to your computer and use it in GitHub Desktop.
Save ekibun/986ee31691b290dd95f4428a46cbeec2 to your computer and use it in GitHub Desktop.
<!--
* @Description: banner
* @Author: ekibun
* @Date: 2019-09-17 14:47:44
* @LastEditors: ekibun
* @LastEditTime: 2019-09-18 16:27:24
-->
<!DOCTYPE html>
<html>
<head>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
body,
#pager {
width: 100%;
height: 100%;
position: absolute;
top: 0px;
bottom: 0px;
padding: 0px;
margin: 0px;
background-color: antiquewhite;
overflow: hidden;
user-select: none;
touch-action: none;
}
#pager * {
position: absolute;
width: 80%;
top: 10%;
left: 50%;
margin-left: -40%;
height: 80%;
}
</style>
</head>
<body>
<div id="app">
<div id="pager" @pointermove="onPointerMove" @pointerup="onPointerUp">
<div v-for="(item, index) in items" :style="itemStyles(item, index)"></div>
</div>
</div>
<script>
let DISTANCE = 100;
new Vue({
el: '#app',
data: () => ({
offset: 0,
curIndex: 1,
dragging: false,
items: [
{
color: "red"
},
{
color: "green"
},
{
color: "blue"
},
{
color: "yellow"
}]
}),
computed: {
newIndex() {
return this.offset < -DISTANCE ? (this.curIndex + 1) % this.items.length :
this.offset > DISTANCE ? (this.curIndex - 1 + this.items.length) % this.items.length : this.curIndex
}
},
methods: {
onPointerMove(e) {
if (e.buttons != 1) return;
this.dragging = true;
this.offset += e.movementX;
this.offset = Math.min(2 * DISTANCE, Math.max(-2 * DISTANCE, this.offset));
},
onPointerUp(e) {
this.dragging = false;
this.curIndex = this.newIndex;
this.offset = 0;
},
indexDistance(a, b) {
return (a - b + this.items.length * 3 / 2) % this.items.length - this.items.length / 2;
},
itemStyles(item, index) {
let distance = this.indexDistance(index, this.curIndex);
if (this.offset < 0 && -2 * distance >= this.items.length) distance = -distance;
let indexOffset = this.offset + 2 * distance * DISTANCE;
distance = this.indexDistance(index, this.newIndex);
return {
transition: this.dragging ? undefined : 'transform .2s ease-out',
'background-color': item.color,
'z-index': 2 - Math.abs(distance),
'visibility': Math.abs(distance) > 1 ? "hidden" : "visible",
transform: `scale(${
1 - Math.min(2 * DISTANCE, Math.abs(indexOffset)) / (10 * DISTANCE)
}) translateX(${
Math.max(-2 * DISTANCE, Math.min(2 * DISTANCE, indexOffset)) / 5
}%)`
}
}
}
})
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment