@things-factory/board-ui 4.0.0 → 4.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,279 +0,0 @@
1
- import { LitElement, html, css } from 'lit-element'
2
-
3
- import '@material/mwc-fab/mwc-fab'
4
- import '@material/mwc-icon/mwc-icon'
5
- import SwipeListener from 'swipe-listener'
6
-
7
- import './board-wrapper'
8
-
9
- import './player/board-player-carousel'
10
-
11
- import { togglefullscreen, exitfullscreen } from '@things-factory/utils'
12
-
13
- import { style } from './board-player-style'
14
-
15
- export class BoardPlayer extends LitElement {
16
- constructor() {
17
- super()
18
-
19
- this.boards = []
20
-
21
- this.playtime = 30
22
- this.columns = 1
23
- this.rows = 1
24
- this.started = false
25
- this.fullscreened = false
26
- }
27
-
28
- static get properties() {
29
- return {
30
- boards: Array,
31
-
32
- playtime: Number,
33
- columns: Number,
34
- rows: Number,
35
- started: Boolean,
36
- playing: Boolean,
37
- fullscreened: Boolean
38
- }
39
- }
40
-
41
- static get styles() {
42
- return [style]
43
- }
44
-
45
- render() {
46
- return html`
47
- <slot @mousemove=${e => this.onMousemove(e)} @transform=${e => this.onTransform(e)} tabindex="-1">
48
- ${
49
- this.started
50
- ? html`
51
- <board-player-carousel axis="y" .rows=${this.rows} .columns=${this.columns} player>
52
- ${this.boards.map(
53
- item => html`
54
- <board-wrapper page .sceneId=${item.id}> </board-wrapper>
55
- `
56
- )}
57
- </board-player-carousel>
58
- `
59
- : html``
60
- }
61
- </slot>
62
-
63
- <div id="control" @mouseover=${e => this.onMouseoverControl(e)} hidden>
64
- <div id="joystick">
65
- <mwc-icon id="up" @click=${e => this.onTapUp(e)}>keyboard_arrow_up</mwc-icon>
66
- <mwc-icon id="left" @click=${e => this.onTapLeft(e)}>keyboard_arrow_left</mwc-icon>
67
- <mwc-icon id="play" @click=${e => this.onTapPlay(e)} ?hidden=${this.playing}>play_arrow</mwc-icon>
68
- <mwc-icon id="pause" @click=${e => this.onTapPause(e)} ?hidden=${!this.playing}>pause</mwc-icon>
69
- <mwc-icon id="right" @click=${e => this.onTapRight(e)}>keyboard_arrow_right</mwc-icon>
70
- <mwc-icon id="down" @click=${e => this.onTapDown(e)}>keyboard_arrow_down</mwc-icon>
71
- </div>
72
-
73
- <div id="setting-container">
74
- <div id="setting">
75
- <div id="schedule-container">
76
- <mwc-icon id="schedule">schedule</mwc-icon>
77
- <input .value=${this.playtime} @change=${e => (this.playtime = e.target.value)}></input>
78
- sec.
79
- </div>
80
- <div id="grid-setting-container">
81
- <mwc-icon id="view_module">view_module</mwc-icon>
82
- <select .value=${this.rows} @change=${e => (this.rows = e.target.value)}>
83
- ${[1, 2, 3, 4, 5].map(
84
- row => html`
85
- <option>${row}</option>
86
- `
87
- )}
88
- </select>
89
- x
90
- <select .value=${this.columns} @change=${e => (this.columns = e.target.value)}>
91
- ${[1, 2, 3, 4, 5].map(
92
- column => html`
93
- <option>${column}</option>
94
- `
95
- )}
96
- </select>
97
- </div>
98
- </div>
99
-
100
- <div id="etc">
101
- <mwc-icon id="fullscreen" @click=${e => this.onTapFullscreen(e)} ?hidden=${this.fullscreened}
102
- >fullscreen</mwc-icon>
103
- <mwc-icon id="fullscreen-exit" @click=${e => this.onTapFullscreen(e)} ?hidden=${!this.fullscreened}
104
- >fullscreen_exit</mwc-icon>
105
- <mwc-icon id="close" @click=${e => this.onTapClose(e)}>close</mwc-icon>
106
- </div>
107
- </div>
108
- </div>
109
- `
110
- }
111
-
112
- firstUpdated() {
113
- SwipeListener(this)
114
-
115
- this.addEventListener('swipe', e => {
116
- var directions = e.detail.directions
117
-
118
- if (directions.left) {
119
- this.onTapRight()
120
- } else if (directions.right) {
121
- this.onTapLeft()
122
- } else if (directions.top) {
123
- this.onTapDown()
124
- } else if (directions.bottom) {
125
- this.onTapUp()
126
- }
127
- })
128
- }
129
-
130
- updated(changes) {
131
- if (changes.has('boards') || changes.has('columns') || changes.has('rows')) {
132
- this.boards && this.boards.length > 0 ? this.restart() : this.stop()
133
- } else if (changes.has('playtime') && this.playing) {
134
- this._resetTransformTimer()
135
- }
136
- }
137
-
138
- get control() {
139
- return this.shadowRoot.getElementById('control')
140
- }
141
-
142
- get fullscreen() {
143
- return this.shadowRoot.getElementById('fullscreen')
144
- }
145
-
146
- async _resetFadeTimer(stop) {
147
- if (!this._control_animation) {
148
- this._control_animation = this.control.animate(
149
- [
150
- {
151
- opacity: 1,
152
- easing: 'ease-in'
153
- },
154
- { opacity: 0 }
155
- ],
156
- { delay: 1000, duration: 2000 }
157
- )
158
- }
159
-
160
- this.control.hidden = false
161
-
162
- this._control_animation.cancel()
163
- if (stop) return
164
-
165
- try {
166
- this._control_animation.play()
167
- await this._control_animation.finished
168
- this.control.hidden = true
169
- } catch (e) {
170
- /* cancelled */
171
- }
172
- }
173
-
174
- _resetTransformTimer() {
175
- clearTimeout(this._transfer_timer)
176
-
177
- this.playing = true
178
-
179
- if (this.currentPlayer) {
180
- this._transfer_timer = setTimeout(() => {
181
- if (this._transfer_timer) this.currentPlayer.next()
182
- }, this.playtime * 1000)
183
- }
184
- }
185
-
186
- onMousemove() {
187
- this._resetFadeTimer()
188
- }
189
-
190
- onMouseoverControl() {
191
- this._resetFadeTimer(true)
192
- }
193
-
194
- onTapFullscreen() {
195
- togglefullscreen(
196
- this,
197
- () => {
198
- this.fullscreened = true
199
- this.focus()
200
- },
201
- () => {
202
- this.fullscreened = false
203
- this.focus()
204
- }
205
- )
206
- }
207
-
208
- onTransform() {
209
- requestAnimationFrame(() => this.started && this.playing && this._resetTransformTimer())
210
- }
211
-
212
- onTapPlay(e) {
213
- this._resetTransformTimer()
214
- }
215
-
216
- onTapPause(e) {
217
- clearTimeout(this._transfer_timer)
218
- this.playing = false
219
- }
220
-
221
- onTapLeft(e) {
222
- this.currentPlayer.axis = 'y'
223
- this.currentPlayer.previous()
224
- }
225
-
226
- onTapRight(e) {
227
- this.currentPlayer.axis = 'y'
228
- this.currentPlayer.next()
229
- }
230
-
231
- onTapUp(e) {
232
- this.currentPlayer.axis = 'x'
233
- this.currentPlayer.next()
234
- }
235
-
236
- onTapDown(e) {
237
- this.currentPlayer.axis = 'x'
238
- this.currentPlayer.previous()
239
- }
240
-
241
- onTapClose(e) {
242
- if (this.fullscreened) {
243
- exitfullscreen()
244
- }
245
-
246
- window.history.back()
247
- }
248
-
249
- async restart() {
250
- await this.stop()
251
- await this.start()
252
- }
253
-
254
- async start() {
255
- if (!this.boards || this.boards.length == 0) return
256
-
257
- this.started = true
258
- this.playing = true
259
-
260
- await this.renderComplete
261
- this.currentPlayer = this.shadowRoot.querySelector(':not([style*="display: none"])[player]')
262
-
263
- this._resetTransformTimer()
264
- this._resetFadeTimer()
265
-
266
- this.focus()
267
- }
268
-
269
- async stop() {
270
- clearTimeout(this._transfer_timer)
271
-
272
- this.currentPlayer && this.currentPlayer.stop()
273
-
274
- await this.renderComplete
275
- this.started = false
276
- }
277
- }
278
-
279
- customElements.define('board-player', BoardPlayer)
@@ -1,126 +0,0 @@
1
- import { LitElement, html, css } from 'lit-element'
2
- import { createBoardProvider } from '../board-provider'
3
-
4
- class BoardWrapper extends LitElement {
5
- constructor() {
6
- super()
7
-
8
- this.sceneId = ''
9
- }
10
-
11
- static get properties() {
12
- return {
13
- sceneId: String
14
- /*
15
- * 캔바스에 모델을 어떻게 적절하게 보여줄 것인지를 설정한다.
16
- *
17
- * @none 가로, 세로 스케일을 1로 고정하고, {0, 0}좌표로 translate시킨다.
18
- * @both 캔바스에 모델을 꼭 채우도록 가로, 세로 스케일을 조정하고, {0, 0}좌표로 translate시킨다.
19
- * @width 캔바스의 폭에 모델의 폭을 일치하도록 가로, 세로 스케일을 동일하게 조정하고, {0, 0}좌표로 translate시킨다.
20
- * @height 캔바스의 높이에 모델의 높이를 일치하도록 가로, 세로 스케일을 동일하게 조정하고, {0, 0}좌표로 translate시킨다.
21
- * @center 가로, 세로 스케일을 1로 고정하고 모델이 화면의 중앙에 위치하도록 translate시킨다.
22
- * @ratio 모델의 모든 부분이 캔바스에 최대 크기로 표현될 수 있도록 가로, 세로 동일한 스케일로 조정하고, {0, 0}좌표로 translate시킨다.
23
- *
24
- * @todo things-real 에서는 enumeration type 이며, FitMode.RATIO | FitMode.BOTH 중 하나로 정의한다.
25
- */
26
- }
27
- }
28
-
29
- static get styles() {
30
- return [
31
- css`
32
- :host {
33
- display: block;
34
- position: relative;
35
- width: 100%;
36
- height: 100%;
37
- }
38
-
39
- #target {
40
- display: block;
41
- width: 100%;
42
- height: 100%;
43
- outline: 0;
44
- }
45
- `
46
- ]
47
- }
48
-
49
- render() {
50
- return html`
51
- <div id="target"></div>
52
- <slot></slot>
53
- `
54
- }
55
-
56
- connectedCallback() {
57
- super.connectedCallback()
58
-
59
- window.addEventListener('resize', () => {
60
- requestAnimationFrame(() => {
61
- if (this.scene) {
62
- this.scene.resize()
63
-
64
- if (this.offsetWidth) {
65
- this.scene.fit()
66
- }
67
- }
68
- })
69
- })
70
-
71
- if (!this.provicer) {
72
- this.provider = createBoardProvider()
73
- }
74
- }
75
-
76
- get targetEl() {
77
- return this.shadowRoot.getElementById('target')
78
- }
79
-
80
- disconnectedCallback() {
81
- super.disconnectedCallback()
82
-
83
- this._releaseRef()
84
- }
85
-
86
- updated(change) {
87
- change.has('sceneId') && this._onSceneIdChanged()
88
- }
89
-
90
- _releaseRef() {
91
- if (this.scene) {
92
- this.scene.target = null
93
- this.scene.release()
94
- delete this.scene
95
-
96
- this.provider.dispose()
97
- delete this.provider
98
- }
99
- }
100
-
101
- _onSceneIdChanged() {
102
- if (!this.provider) return
103
-
104
- this._releaseRef()
105
-
106
- if (!this.sceneId) return
107
-
108
- this.provider.get(this.sceneId, true).then(
109
- scene => {
110
- this.scene = scene
111
- this.scene.target = this.targetEl
112
-
113
- /* 이 컴포넌트의 폭이 값을 가지고 있으면 - 화면상에 자리를 잡고 보여지고 있음을 의미한다.
114
- * 이 때는 정상적으로 그려주고,
115
- * 그렇지 않으면, 다음 Resize Handling시에 처리하도록 한다.
116
- */
117
- if (this.scene.target.offsetWidth) {
118
- this.scene.fit()
119
- }
120
- },
121
- e => {}
122
- )
123
- }
124
- }
125
-
126
- customElements.define('board-wrapper', BoardWrapper)
@@ -1,187 +0,0 @@
1
- import { LitElement, html, css } from 'lit-element'
2
- import { FlattenedNodesObserver } from '@polymer/polymer/lib/utils/flattened-nodes-observer'
3
-
4
- import './board-player-grid'
5
-
6
- class BoardPlayerCarousel extends LitElement {
7
- static get is() {
8
- return 'board-player-carousel'
9
- }
10
-
11
- static get properties() {
12
- return {
13
- axis: String,
14
- rows: Number,
15
- columns: Number
16
- }
17
- }
18
-
19
- static get styles() {
20
- return [
21
- css`
22
- :host {
23
- display: block;
24
- width: 100%;
25
- height: 100%;
26
- position: relative;
27
- margin: 0 auto 0px;
28
- -webkit-perspective: 1200px;
29
- -moz-perspective: 1200px;
30
- -o-perspective: 1200px;
31
- perspective: 1200px;
32
- }
33
-
34
- #carousel {
35
- width: 100%;
36
- height: 100%;
37
- margin: 0px auto 0px;
38
-
39
- position: absolute;
40
- -webkit-transform-style: preserve-3d;
41
- -moz-transform-style: preserve-3d;
42
- -o-transform-style: preserve-3d;
43
- transform-style: preserve-3d;
44
- -webkit-transition: -webkit-transform 1.5s;
45
- -moz-transition: -moz-transform 1.5s;
46
- -o-transition: -o-transform 1.5s;
47
- transition: transform 1.5s;
48
- }
49
-
50
- #carousel > * {
51
- position: absolute;
52
- width: 100%;
53
- height: 100%;
54
- font-weight: bold;
55
- -webkit-transition: opacity 1.5s, -webkit-transform 1.5s;
56
- -moz-transition: opacity 1.5s, -moz-transform 1.5s;
57
- -o-transition: opacity 1.5s, -o-transform 1.5s;
58
- transition: opacity 1.5s, transform 1.5s;
59
-
60
- -webkit-backface-visibility: hidden;
61
- -moz-backface-visibility: hidden;
62
- -o-backface-visibility: hidden;
63
- backface-visibility: hidden;
64
- }
65
- `
66
- ]
67
- }
68
-
69
- render() {
70
- return html`
71
- <slot id="slot" select="[page]"></slot>
72
-
73
- <div id="carousel"></div>
74
- `
75
- }
76
-
77
- disconnectedCallback() {
78
- super.disconnectedCallback()
79
-
80
- this._slotObserver.disconnect()
81
-
82
- if (this.boundResize) {
83
- window.removeEventListener('resize', this.boundResize)
84
- delete this.boundResize
85
- }
86
- }
87
-
88
- firstUpdated() {
89
- this.rotation = 0
90
- this._slotObserver = new FlattenedNodesObserver(this.shadowRoot.querySelector('#slot'), info => {
91
- this.build()
92
- })
93
-
94
- this.boundResize = this.build.bind(this)
95
-
96
- window.addEventListener('resize', this.boundResize)
97
- }
98
-
99
- get carousel() {
100
- return this.shadowRoot.querySelector('#carousel')
101
- }
102
-
103
- updated(change) {
104
- change.has('axis') && this._onAxisChanged(this.axis)
105
- }
106
-
107
- build() {
108
- var pages = Array.from(this.querySelectorAll('[page]'))
109
- var panel = Array.from(this.carousel.querySelectorAll('board-player-grid')).pop()
110
-
111
- var rows = this.rows || 1
112
- var columns = this.columns || 1
113
-
114
- var i = panel ? panel.querySelectorAll('[page]').length : 0
115
- var page = pages.shift()
116
-
117
- while (page) {
118
- if (!(i++ % (rows * columns))) {
119
- panel = document.createElement('board-player-grid')
120
- panel.rows = rows
121
- panel.columns = columns
122
-
123
- this.carousel.appendChild(panel)
124
- }
125
- panel.appendChild(page)
126
-
127
- page = pages.shift()
128
- }
129
-
130
- this.start()
131
- }
132
-
133
- start() {
134
- var panels = this.carousel.querySelectorAll('board-player-grid')
135
-
136
- this.isHorizontal = this.axis === 'y'
137
-
138
- this.panelCount = panels.length
139
-
140
- this.panelSize = this.carousel[this.isHorizontal ? 'offsetWidth' : 'offsetHeight'] || '640'
141
- this.rotateFn = this.isHorizontal ? 'rotateY' : 'rotateX'
142
- this.theta = 360 / (this.panelCount || 1)
143
-
144
- // do some trig to figure out how big the carousel is in 3D space
145
- this.radius = Math.round(this.panelSize / 2 / Math.tan(Math.PI / (this.panelCount < 2 ? 2 : this.panelCount)))
146
-
147
- for (let i = 0; i < this.panelCount; i++) {
148
- let panel = panels[i]
149
- let angle = this.theta * i
150
- panel.style.opacity = 1
151
-
152
- panel.style.backgroundColor = 'white'
153
-
154
- panel.style.transform = this.rotateFn + '(' + angle + 'deg) translateZ(' + this.radius + 'px)'
155
- }
156
-
157
- // adjust rotation so panels are always flat
158
- this.rotation = Math.round(this.rotation / this.theta) * this.theta
159
- this._transform()
160
- }
161
-
162
- stop() {
163
- this.carousel.innerHTML = ''
164
- }
165
-
166
- _onAxisChanged(after) {
167
- this.start()
168
- }
169
-
170
- _transform() {
171
- // push the carousel back in 3D space, and rotate it
172
- this.carousel.style.transform = 'translateZ(-' + this.radius + 'px) ' + this.rotateFn + '(' + this.rotation + 'deg)'
173
- this.dispatchEvent(new CustomEvent('transform', { bubbles: true, composed: true }))
174
- }
175
-
176
- previous() {
177
- this.rotation += this.theta
178
- this._transform()
179
- }
180
-
181
- next() {
182
- this.rotation -= this.theta
183
- this._transform()
184
- }
185
- }
186
-
187
- customElements.define(BoardPlayerCarousel.is, BoardPlayerCarousel)