-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcube.js
136 lines (117 loc) · 3.61 KB
/
cube.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
function makeStyle({ x, y, width, height, color }) {
return {
cube: {
width: `${width}px`,
height: `${height}px`,
position: 'absolute',
bottom: y,
left: x,
transformStyle: 'preserve-3d',
transition: 'transform 1s',
},
cube__face: {
position: 'absolute',
width: `${width}px`,
height: `${height}px`,
border: '1px solid black',
},
['cube__face--front']: { background: color, transform: `rotateY(0deg) translateZ(${width / 2}px)` },
['cube__face--right']: { background: color, transform: `rotateY(90deg) translateZ(${width / 2}px)` },
['cube__face--back']: { background: color, transform: `rotateY(180deg) translateZ(${width / 2}px)` },
['cube__face--left']: { background: color, transform: `rotateY(-90deg) translateZ(${width / 2}px)` },
}
}
const template = `
<div class="cube" id="cube">
<div class="cube__face cube__face--front">Front</div>
<div class="cube__face cube__face--back">Back</div>
<div class="cube__face cube__face--right">Right</div>
<div class="cube__face cube__face--left">Left</div>
</div>
`
function createElement(htmlString) {
var div = document.createElement('div')
div.innerHTML = htmlString.trim()
// Change this to div.childNodes to support multiple top-level nodes
return div.firstChild
}
function stylize(element, pStyle) {
for (const prop in pStyle) {
const isRootClass = element.classList.contains(prop)
if (isRootClass) {
for(const cssProperty in pStyle[prop]) {
element.style[cssProperty] = pStyle[prop][cssProperty]
}
}
const parts = element.querySelectorAll(`.${prop}`)
if (parts) {
parts.forEach(el => {
for(const cssProperty in pStyle[prop]) {
el.style[cssProperty] = pStyle[prop][cssProperty]
}
})
}
}
}
export class Cube {
constructor(options) {
this.options = options
this.rotation = 0
this.currentFace = 0
this.children = []
this.element = createElement(template)
stylize(this.element, makeStyle(options))
this.element.style.zIndex = this.options.zIndex
}
attachTo(child, face) {
child.face = face
this.children.push(child)
const { x, width, zIndex } = this.options
child.element.style.zIndex = zIndex - 1
child.element.style.transformOrigin = `${(parseInt(x) + parseInt(width)) / 2}px center`
}
rotateRight() {
this.previousHiddenFace = this.getHiddenFace()
if (this.currentFace === 0) {
this.currentFace = 4
}
this.currentFace -= 1
this.rotation += 90
this.rotate()
}
rotateLeft() {
this.previousHiddenFace = this.getHiddenFace()
if(this.currentFace === 3) {
this.currentFace = 0
} else {
this.currentFace += 1
}
this.rotation -= 90
this.rotate()
}
rotate() {
this.element.style.transform = `rotateY(${this.rotation}deg)`
this.children.forEach(child => {
child.element.style.transform = `rotateY(${this.rotation}deg)`
if(this.isChildHidden(child)) {
child.element.style.transition = 'transform 1s, zIndex 1s'
} else {
child.element.style.transition = 'transform 1s'
}
if(this.isChildHidden(child)) {
child.element.style.zIndex = this.options.zIndex - 1
} else {
child.element.style.zIndex = this.options.zIndex + 1
}
})
}
getHiddenFace() {
if (this.currentFace === 0) return 2
if (this.currentFace === 3) return 1
if (this.currentFace === 2) return 0
return 3
}
isChildHidden({ face }) {
return face === this.getHiddenFace() || face === this.previousHiddenFace
}
}