Skip to content

Instantly share code, notes, and snippets.

@Ginhing
Created August 17, 2018 06:36
Show Gist options
  • Save Ginhing/485c2f974583618729c321e25e7dbc46 to your computer and use it in GitHub Desktop.
Save Ginhing/485c2f974583618729c321e25e7dbc46 to your computer and use it in GitHub Desktop.
learn the APIs of Web Component
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>title</h1>
<div id="root"></div>
<template id="slot-machine-template">
<div id="wrapper">
<div id="main">
<slot></slot>
</div>
</div>
<div id="selected">
</div>
<button class="slot">Go</button>
<button class="switch">Fast</button>
<style>
#wrapper {
overflow: hidden;
width: 0;
}
#main {
display: flex;
justify-content: flex-start;
align-items: flex-start;
transition: transform 0.5s cubic-bezier(0.19, 1.22, 0.6, 1.58)
}
#selected {
display: flex;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
align-items: center;
justify-content: center;
transition: transform 1s ease-in;
transform: translateY(-100%);
}
</style>
</template>
</body>
<script>
customElements.define('slot-machine',
class extends HTMLElement {
get isRolling() {
return this.anim.playState === 'running'
}
get itemWidth() {
return this.getAttribute('item-width') || 250
}
constructor() {
super()
let template = document.getElementById('slot-machine-template').content
let shadow = this.attachShadow({ mode: 'open' })
shadow.appendChild(template.cloneNode(true))
this.images = shadow.querySelector('slot').assignedNodes().filter(it => it.tagName === 'IMG')
this.container = shadow.getElementById('main')
this.slotButton = shadow.querySelector('.slot')
this.switchButton = shadow.querySelector('.switch')
this.wrapper = shadow.getElementById('wrapper')
this.selectedView = shadow.getElementById('selected')
this.anim = null
this.initAnimation()
}
connectedCallback() {
this.handlePlay = e => {
if (this.isRolling) {
this.anim.pause()
this.slotButton.innerText = 'Go'
requestAnimationFrame(() => {
let offsetX = this.container.getBoundingClientRect().left - this.container.offsetLeft
let selectedItem = Math.ceil(Math.abs(offsetX) / this.itemWidth)
this.anim.cancel()
this.container.style.transform = `translateX(${offsetX}px)`
requestAnimationFrame(() => {
this.container.style.transform = `translateX(-${this.itemWidth * selectedItem}px)`
this.selectedView.style.transform = 'none'
this.selectedView.innerHTML = `<img src=${this.images[selectedItem].src}>`
})
})
} else {
this.anim.play()
this.slotButton.innerText = 'Stop'
}
}
this.handleSpeed = e => {
if (this.anim.playbackRate < 1) {
this.anim.playbackRate = 1
this.switchButton.innerText = 'Fast'
} else {
this.anim.playbackRate = 0.1
this.switchButton.innerText = 'Slow'
}
}
this.handleClose = e => {
this.selectedView.style.transform = ''
}
this.slotButton.addEventListener('click', this.handlePlay)
this.switchButton.addEventListener('click', this.handleSpeed)
this.selectedView.addEventListener('click', this.handleClose)
}
disconnectedCallback() {
this.slotButton.removeEventListener('click', this.handlePlay)
this.switchButton.removeEventListener('click', this.handleSpeed)
this.selectedView.removeEventListener('click', this.handleClose)
}
initAnimation() {
let [firstImg] = this.images
firstImg.addEventListener('load', () => {
this.wrapper.style.width = this.itemWidth * 1.1 + 'px'
this.anim = this.container.animate(
[
{ transform: 'translateX(0)' },
{ transform: `translateX(-${(this.images.length - 1) *this.itemWidth}px)` },
],
{
duration: 300,
iterations: Infinity,
direction: 'alternate'
}
)
this.anim.pause()
})
}
}
)
function main() {
let images = new Array(10).fill().map((_, i) => `http://placekitten.com/55${i}/400`)
document.getElementById('root').innerHTML = `
<slot-machine item-width="550">
${images.map(src => `<img src=${src}>`).join('')}
</slot-machine>
`.trim()
}
document.addEventListener('DOMContentLoaded', main)
</script>
</html>
@Ginhing
Copy link
Author

Ginhing commented Aug 17, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment