-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsrc.js
159 lines (123 loc) · 3.9 KB
/
src.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
const DEFAULT_UNIT_DIR = 400
const CONTENT_SHOW_DURATION_RATIO = 0.5
const DEFAULT_M = 4
const DEFAULT_N = 4
const DEFAULT_BGCOLOR = '#393F44'
const CHIP_CLASS = 'multiflip-chip'
const FLIPPED_CLASS = 'multiflip-flipped'
const FLIP_TRANSFORM = 'rotate3d(1, -1, 0, -180deg)' // Transformation for the flipping a chip
const wait = n => new Promise(resolve => setTimeout(resolve, n))
class MultiflipContent {
static __mount__ () {
this.capsid.on('transitionend')(this.prototype, 'onTransitionEnd')
}
__mount__ () {
const el = this.el
const transition = +el.getAttribute('transition')
this.delay = +el.getAttribute('delay')
el.style.transitionDuration = `${transition}ms`
el.style.transitionDelay = `${this.delay}ms`
}
onTransitionEnd () {
if (this.el.parentElement.classList.contains(FLIPPED_CLASS)) {
this.el.style.transitionDelay = '0ms'
} else {
this.el.style.transitionDelay = `${this.delay}ms`
}
}
}
/**
* Multiflip class handles the behaviours of multi-flipping.
*
* <div class="multiflip" m="6" n="4" unit-dur="400" bgcolor="#4588aa"></div>
*
* - attr {number} m The horizontal partition number
* - attr {number} n The vertical partition number
* - attr {number} unit-dur The unit duration of multiflipping
* - attr {string} bgcolor The background color of the flipping chips
*/
export default class Multiflip {
/**
* Initializes the multiflip.
*/
__mount__ () {
const el = this.el
const { mount } = Multiflip.capsid
const width = el.clientWidth
const height = el.clientHeight
const m = +el.getAttribute('m') || DEFAULT_M
const n = +el.getAttribute('n') || DEFAULT_N
const unitW = width / m
const unitH = height / n
const unitDur = +el.getAttribute('unit-dur') || DEFAULT_UNIT_DIR
const diffDur = unitDur / (m + n)
const bgcolor = el.getAttribute('bgcolor') || DEFAULT_BGCOLOR
this.flipDur = unitDur * 2
Multiflip.insertGlobalStyle()
Array.prototype.forEach.call(el.children, child => {
const transition = unitDur * CONTENT_SHOW_DURATION_RATIO
const delay = unitDur * (2 - CONTENT_SHOW_DURATION_RATIO)
child.setAttribute('transition', transition)
child.setAttribute('delay', delay)
mount(MultiflipContent, child)
})
const total = n * m
for (let c = 0; c < total; c++) {
const i = c % m
const j = Math.floor(c / m)
const div = document.createElement('div')
const style = div.style
div.classList.add(CHIP_CLASS)
style.left = i * unitW + 'px'
style.top = j * unitH + 'px'
style.width = unitW + 'px'
style.height = unitH + 'px'
style.backgroundColor = bgcolor
style.transitionDuration = unitDur + 'ms'
style.transitionDelay = diffDur * (i + j) + 'ms'
el.insertBefore(div, el.firstChild)
}
}
static insertGlobalStyle () {
if (document.getElementById('multiflip-global-style')) {
return
}
const style = document.createElement('style')
style.setAttribute('id', 'multiflip-global-style')
style.textContent = `
.multiflip .${CHIP_CLASS} {
position: absolute;
transform: ${FLIP_TRANSFORM};
backface-visibility: hidden;
transform-style: preserve-3d;
}
.multiflip.${FLIPPED_CLASS} .${CHIP_CLASS} {
transform: none;
}
.multiflip > :not(.${CHIP_CLASS}) {
opacity: 0;
transition-property: opacity;
}
.multiflip.${FLIPPED_CLASS} > :not(.${CHIP_CLASS}) {
opacity: 1;
}
`
document.body.appendChild(style)
}
/**
* Performs multiflipping and shows the content.
* @return {Promise}
*/
show () {
this.el.classList.add(FLIPPED_CLASS)
return wait(this.flipDur)
}
/**
* Perfoms multiflipping and hides the content.
* @return {Promise}
*/
hide () {
this.el.classList.remove(FLIPPED_CLASS)
return wait(this.flipDur)
}
}