polarvo-layout 1.0.2 → 1.0.3
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.
- package/package.json +1 -1
- package/src/components/FastMenu/DisplayFastMenu.vue +4 -3
- package/src/components/FastMenu/HistoryFastMenu.vue +18 -3
- package/src/components/Layout/BaseLayout.vue +6 -4
- package/src/components/Layout/CanvasContainer.vue +6 -7
- package/src/components/Layout/GridLayout.vue +42 -42
- package/src/components/SideBar/LayoutSettingSideBar.vue +4 -4
- package/src/components/SideBar/LayoutSideBar.vue +4 -4
- package/src/configs/index.js +0 -5
- package/src/core/engines/DisplayEngine.js +76 -29
- package/src/core/engines/FreeDropEngine.js +111 -113
- package/src/core/engines/GridDropEngine.js +101 -89
- package/src/core/engines/HistoryEngine.js +259 -13
- package/src/core/engines/LayoutEngine.js +111 -79
- package/src/core/managers/EngineManager.js +251 -174
- package/src/library/DisplayLibrary.js +21 -8
- package/src/library/FreeDropLibrary.js +42 -34
- package/src/library/GridDropLibrary.js +36 -28
- package/src/library/HistoryLibrary.js +44 -5
- package/src/library/LayoutLibrary.js +65 -50
- package/src/library/index.js +1 -0
package/package.json
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
min="600"
|
|
25
25
|
max="2400"
|
|
26
26
|
step="50"
|
|
27
|
-
:value="displaySize
|
|
27
|
+
:value="displaySize?.px"
|
|
28
28
|
class="border-b-2 pr-1 border-white focus:outline-none focus:border-b-2 focus:border-blue-500"
|
|
29
29
|
@change="setDisplaySize('px', $event.target.value)"
|
|
30
30
|
/>
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
min="0"
|
|
37
37
|
max="100"
|
|
38
38
|
step="10"
|
|
39
|
-
:value="displaySize
|
|
39
|
+
:value="displaySize?.percent"
|
|
40
40
|
class="border-b-2 pr-1 border-white focus:outline-none focus:border-b-2 focus:border-blue-500"
|
|
41
41
|
@change="setDisplaySize('percent', $event.target.value)"
|
|
42
42
|
/>
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
</template>
|
|
47
47
|
|
|
48
48
|
<script setup>
|
|
49
|
-
import { toRefs } from 'vue';
|
|
49
|
+
import { toRefs, onMounted } from 'vue';
|
|
50
50
|
|
|
51
51
|
const props = defineProps({
|
|
52
52
|
polarvo: {
|
|
@@ -56,6 +56,7 @@ const props = defineProps({
|
|
|
56
56
|
});
|
|
57
57
|
const { displayMode, displaySize } = toRefs(props.polarvo.display.state);
|
|
58
58
|
const { setDisplayMode, setDisplaySize } = props.polarvo.display;
|
|
59
|
+
|
|
59
60
|
</script>
|
|
60
61
|
|
|
61
62
|
<style scoped>
|
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<!-- editor - title right -->
|
|
3
3
|
<div id="fast-menu" class="flex gap-2 text-gray-400">
|
|
4
|
-
<
|
|
5
|
-
|
|
4
|
+
<button @click="undo" :class="undoable ? 'cursor-pointer hover:opacity-70 ' : 'cursor-not-allowed opacity-50'" :disabled="!undoable">
|
|
5
|
+
<UndoIcon class="size-5 active:text-blue-600" />
|
|
6
|
+
</button>
|
|
7
|
+
<button @click="redo" :class="redoable ? 'cursor-pointer hover:opacity-70' : 'cursor-not-allowed opacity-50'" :disabled="!redoable">
|
|
8
|
+
<RedoIcon class="size-5 active:text-blue-600" />
|
|
9
|
+
</button>
|
|
6
10
|
</div>
|
|
7
11
|
</template>
|
|
8
12
|
|
|
9
13
|
<script setup>
|
|
10
|
-
import
|
|
14
|
+
import { toRefs } from 'vue';
|
|
15
|
+
import UndoIcon from '../../icons/history/UndoIcon.vue';
|
|
11
16
|
import RedoIcon from '../../icons/history/RedoIcon.vue';
|
|
17
|
+
|
|
18
|
+
const props = defineProps({
|
|
19
|
+
polarvo: {
|
|
20
|
+
type: Object,
|
|
21
|
+
required: true,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const { undoable, redoable } = toRefs(props.polarvo.history.state);
|
|
26
|
+
const { undo, redo } = props.polarvo.history;
|
|
12
27
|
</script>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div
|
|
3
3
|
:id="preview ? 'previewLayout' : 'baseLayout'"
|
|
4
4
|
class="grid h-full p-2 bg-transparent rounded-lg"
|
|
5
|
-
:class="[layoutType + '-layout', `grid-cols-${gridNumber
|
|
5
|
+
:class="[layoutType + '-layout', `grid-cols-${gridNumber?.column}`, 'mb-4' ? layoutType === 'three-column-split' : '']"
|
|
6
6
|
:style="getBaseStyle"
|
|
7
7
|
>
|
|
8
8
|
<template v-for="(section, key) in layoutData" :key="key">
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
</template>
|
|
35
35
|
|
|
36
36
|
<script setup>
|
|
37
|
-
import { toRefs, computed } from 'vue';
|
|
37
|
+
import { toRefs, computed, onUnmounted } from 'vue';
|
|
38
38
|
|
|
39
39
|
import PolarLayout from './PolarLayout.vue';
|
|
40
40
|
import FreeLayout from './FreeLayout.vue';
|
|
@@ -67,8 +67,8 @@ const layoutType = computed(() => {
|
|
|
67
67
|
|
|
68
68
|
const getBaseStyle = computed(() => {
|
|
69
69
|
return {
|
|
70
|
-
gridTemplateColumns: gridRatio.value
|
|
71
|
-
gridTemplateRows: gridRatio.value
|
|
70
|
+
gridTemplateColumns: gridRatio.value?.column.map((ratio) => `${ratio}%`).join(' '),
|
|
71
|
+
gridTemplateRows: gridRatio.value?.row.map((ratio) => `${ratio}%`).join(' '),
|
|
72
72
|
marginRight: layoutType.value === 'no-split' ? '0' : layoutType.value === 'three-column-split' ? '14px' : '8px',
|
|
73
73
|
gap: `${gapSize.value}px`,
|
|
74
74
|
};
|
|
@@ -88,6 +88,8 @@ const getSectionClass = (key, section) => ({
|
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
const { layoutName, layoutData, activeSection, gapSize, gridNumber, gridRatio } = toRefs(props.polarvo.layout.state);
|
|
91
|
+
|
|
92
|
+
|
|
91
93
|
</script>
|
|
92
94
|
|
|
93
95
|
<style scoped>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</template>
|
|
8
8
|
|
|
9
9
|
<script setup>
|
|
10
|
-
import { toRefs,
|
|
10
|
+
import { toRefs, computed, provide } from 'vue';
|
|
11
11
|
import BaseLayout from './BaseLayout.vue';
|
|
12
12
|
|
|
13
13
|
const props = defineProps({
|
|
@@ -18,14 +18,14 @@ const props = defineProps({
|
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
const { displaySize } = toRefs(props.polarvo.display.state);
|
|
21
|
-
const gridSize = computed(() => displaySize.value
|
|
21
|
+
const gridSize = computed(() => displaySize.value?.gridSize || 16);
|
|
22
22
|
|
|
23
23
|
const containerStyle = computed(() => {
|
|
24
24
|
return {
|
|
25
|
-
aspectRatio: displaySize.value
|
|
26
|
-
width: `${displaySize.value
|
|
25
|
+
aspectRatio: displaySize.value?.aspectRatio,
|
|
26
|
+
width: `${displaySize.value?.px}px`,
|
|
27
27
|
margin: `0 auto`,
|
|
28
|
-
transform: `scale(${displaySize.value
|
|
28
|
+
transform: `scale(${displaySize.value?.percent / 100})`,
|
|
29
29
|
transformOrigin: 'top center',
|
|
30
30
|
backgroundImage: `
|
|
31
31
|
linear-gradient(rgba(0,0,0,0.05) 1px, transparent 1px),
|
|
@@ -38,8 +38,7 @@ const containerStyle = computed(() => {
|
|
|
38
38
|
const { elements } = toRefs(props.polarvo.layout.state);
|
|
39
39
|
|
|
40
40
|
// 전체 elements
|
|
41
|
-
provide('elements', elements)
|
|
42
|
-
|
|
41
|
+
provide('elements', elements);
|
|
43
42
|
</script>
|
|
44
43
|
|
|
45
44
|
<style scoped lang="scss"></style>
|
|
@@ -1,51 +1,51 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<div
|
|
17
|
-
|
|
18
|
-
<
|
|
19
|
-
|
|
2
|
+
<template v-if="!preview">
|
|
3
|
+
<div
|
|
4
|
+
v-for="(item, index) in filteredElements"
|
|
5
|
+
:key="index"
|
|
6
|
+
:id="item.id"
|
|
7
|
+
class="relative bg-gray-200"
|
|
8
|
+
:class="{
|
|
9
|
+
'z-50': activeElement?.id === item.id,
|
|
10
|
+
'bg-white border-2 border-blue-400': activeElement?.id === item.id,
|
|
11
|
+
}"
|
|
12
|
+
:style="getElementStyle('element', item)"
|
|
13
|
+
@mousedown.stop="startDrag($event, item.id)"
|
|
14
|
+
>
|
|
15
|
+
<!-- 리사이즈 핸들 -->
|
|
16
|
+
<div v-if="activeElement?.id === item.id">
|
|
17
|
+
<div class="absolute w-4 h-4 bottom-0 right-0 bg-blue-400 z-10 cursor-se-resize" @mousedown="startResize($event, item.id)"></div>
|
|
18
|
+
<div class="absolute z-10 pointer-events-auto cursor-pointer" @click="toggleLock()">
|
|
19
|
+
<LockIcon v-if="item.isLocked" />
|
|
20
|
+
<UnlockIcon v-else />
|
|
21
|
+
</div>
|
|
20
22
|
</div>
|
|
21
|
-
</div>
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
</div>
|
|
24
|
+
<component
|
|
25
|
+
:is="dynamicComponent(item.type)"
|
|
26
|
+
:id="`${sectionKey}-${index}`"
|
|
27
|
+
:ref="(el) => setComponentRef(el, item.id)"
|
|
28
|
+
v-bind="item"
|
|
29
|
+
class="hover:opacity-80 pointer-events-none"
|
|
30
|
+
/>
|
|
31
|
+
</div>
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
<div
|
|
35
|
-
v-for="(cell, index) in emptyData[sectionKey]"
|
|
36
|
-
:key="index"
|
|
37
|
-
class="flex items-center justify-center bg-gray-100 border border-gray-300"
|
|
38
|
-
:style="getElementStyle('empty', cell)"
|
|
39
|
-
@mouseenter="detectHoverCell(cell)"
|
|
40
|
-
>
|
|
33
|
+
<!-- 빈 그리드 설정 -->
|
|
41
34
|
<div
|
|
42
|
-
v-
|
|
43
|
-
|
|
44
|
-
|
|
35
|
+
v-for="(cell, index) in emptyData[sectionKey]"
|
|
36
|
+
:key="index"
|
|
37
|
+
class="flex items-center justify-center bg-gray-100 border border-gray-300"
|
|
38
|
+
:style="getElementStyle('empty', cell)"
|
|
39
|
+
@mouseenter="detectHoverCell(cell)"
|
|
45
40
|
>
|
|
46
|
-
|
|
41
|
+
<div
|
|
42
|
+
class="text-sm w-8 h-8 rounded-full bg-gray-300 flex items-center justify-center text-gray-500 hover:bg-blue-200 hover:text-white transition-colors cursor-pointer"
|
|
43
|
+
@click="setActiveCell('new', cell)"
|
|
44
|
+
>
|
|
45
|
+
+
|
|
46
|
+
</div>
|
|
47
47
|
</div>
|
|
48
|
-
</
|
|
48
|
+
</template>
|
|
49
49
|
</template>
|
|
50
50
|
|
|
51
51
|
<script setup>
|
|
@@ -70,7 +70,7 @@ const props = defineProps({
|
|
|
70
70
|
elementIds: {
|
|
71
71
|
type: Array,
|
|
72
72
|
required: true,
|
|
73
|
-
}
|
|
73
|
+
},
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
const { setActiveDesign } = props.polarvo.display;
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
id="gap-size"
|
|
50
50
|
min="0"
|
|
51
51
|
max="12"
|
|
52
|
-
:value="
|
|
53
|
-
@change="
|
|
52
|
+
:value="activeData?.config?.gridGap"
|
|
53
|
+
@change="setSectionConfig('gap', $event.target.value)"
|
|
54
54
|
/>
|
|
55
55
|
</div>
|
|
56
56
|
</div>
|
|
@@ -81,8 +81,8 @@ const props = defineProps({
|
|
|
81
81
|
required: true,
|
|
82
82
|
},
|
|
83
83
|
});
|
|
84
|
-
const { activeData
|
|
85
|
-
const {
|
|
84
|
+
const { activeData } = toRefs(props.polarvo.layout.state);
|
|
85
|
+
const { setSectionMode, setSectionConfig } = props.polarvo.layout;
|
|
86
86
|
|
|
87
87
|
const sectionMode = computed(() => activeData.value?.mode);
|
|
88
88
|
</script>
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
</div>
|
|
28
28
|
|
|
29
29
|
<div class="px-4 py-0">
|
|
30
|
-
<div class="flex flex-row items-center gap-2 mb-2" v-if="gridNumber
|
|
31
|
-
<template v-for="column in gridNumber
|
|
30
|
+
<div class="flex flex-row items-center gap-2 mb-2" v-if="gridNumber?.column > 1">
|
|
31
|
+
<template v-for="column in gridNumber?.column" :key="column">
|
|
32
32
|
<label class="text-sm w-12 text-gray-500" :for="`col-ratio-${column}`" v-if="column === 1">열비율</label>
|
|
33
33
|
<input
|
|
34
34
|
class="text-sm w-12 border-b-2 border-white focus:outline-none focus:border-b-2 focus:border-blue-500"
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
</template>
|
|
41
41
|
</div>
|
|
42
42
|
|
|
43
|
-
<div class="flex flex-row items-center gap-2 mb-2" v-if="gridNumber
|
|
44
|
-
<template v-for="row in gridNumber
|
|
43
|
+
<div class="flex flex-row items-center gap-2 mb-2" v-if="gridNumber?.row > 1">
|
|
44
|
+
<template v-for="row in gridNumber?.row" :key="row">
|
|
45
45
|
<label class="text-sm w-12 text-gray-500" :for="`row-ratio-${row}`" v-if="row === 1">행비율</label>
|
|
46
46
|
<input
|
|
47
47
|
class="text-sm w-12 border-b-2 border-white focus:outline-none focus:border-b-2 focus:border-blue-500"
|
package/src/configs/index.js
CHANGED
|
@@ -3,13 +3,8 @@ import { resources } from './resources/index.js';
|
|
|
3
3
|
const createDefaultConfig = (overrides = {}) => {
|
|
4
4
|
return {
|
|
5
5
|
initialState: {
|
|
6
|
-
gridSize: 16,
|
|
7
|
-
gridNumber: { column: 1, row: 1 },
|
|
8
6
|
elements: [], // 요소들
|
|
9
|
-
// layoutData: null, // 레이아웃 데이터 - 캐시용
|
|
10
7
|
activeSection: null,
|
|
11
|
-
// activeData: null,
|
|
12
|
-
activeId: null,
|
|
13
8
|
},
|
|
14
9
|
resource: {
|
|
15
10
|
display: resources.display,
|
|
@@ -5,8 +5,9 @@ class DisplayEngine {
|
|
|
5
5
|
|
|
6
6
|
this.activeMenu = null; // 현재 활성화된 메뉴
|
|
7
7
|
this.activeDesign = null; // 현재 활성화된 디자인 메뉴
|
|
8
|
-
this.displayMode = 'desktop'; // 현재 디스플레이 모드
|
|
9
|
-
this.displaySize = { px: 1200, percent: 100, gridSize: 16, aspectRatio: '16/9' }; // 현재 디스플레이 사이즈
|
|
8
|
+
this.displayMode = 'desktop'; // 현재 디스플레이 모드 (초기값 = 'desktop')
|
|
9
|
+
// this.displaySize = { px: 1200, percent: 100, gridSize: 16, aspectRatio: '16/9' }; // 현재 디스플레이 사이즈
|
|
10
|
+
this.displaySize = null
|
|
10
11
|
|
|
11
12
|
this._subscriptions = []; // 구독 해제 함수 저장용
|
|
12
13
|
this._setupSubscriptions();
|
|
@@ -27,29 +28,46 @@ class DisplayEngine {
|
|
|
27
28
|
/** 구독 설정 */
|
|
28
29
|
_setupSubscriptions() {
|
|
29
30
|
// 초기화 완료 이벤트 구독 - from EngineManager
|
|
30
|
-
this._subscribe('system:engineInitialized', (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
this._subscribe('freeDrop:closeActiveMenu', () => {
|
|
35
|
-
this.setActiveMenu(null);
|
|
36
|
-
});
|
|
31
|
+
this._subscribe('system:engineInitialized', () => {
|
|
32
|
+
console.log('1. displayEngine')
|
|
33
|
+
this._resetDisplaySizeByMode(this.displayMode);
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
this.eventBus.emit('display:engineInitialized', {
|
|
36
|
+
displaySize: this.displaySize,
|
|
37
|
+
timestamp: Date.now(),
|
|
38
|
+
})
|
|
40
39
|
});
|
|
41
40
|
|
|
42
|
-
this._subscribe('
|
|
43
|
-
|
|
44
|
-
});
|
|
41
|
+
// this._subscribe('freeDrop:closeActiveMenu', () => {
|
|
42
|
+
// this.setActiveMenu(null);
|
|
43
|
+
// });
|
|
44
|
+
|
|
45
|
+
// this._subscribe('freeDrop:closeDesignMenu', () => {
|
|
46
|
+
// this.setActiveDesign(null);
|
|
47
|
+
// });
|
|
48
|
+
|
|
49
|
+
// this._subscribe('system:closeActiveMenu', () => {
|
|
50
|
+
// this.setActiveMenu(null);
|
|
51
|
+
// });
|
|
52
|
+
|
|
53
|
+
// this._subscribe('gridDrop:updateActiveCell', ({ type, activeCell }) => {
|
|
54
|
+
// if (type === 'new' && activeCell != null) {
|
|
55
|
+
// this.setActiveMenu('element');
|
|
56
|
+
// } else {
|
|
57
|
+
// this.setActiveMenu(activeCell);
|
|
58
|
+
// }
|
|
59
|
+
// });
|
|
60
|
+
|
|
61
|
+
// this._subscribe('system:enginesReset', () => {
|
|
62
|
+
// this.reset();
|
|
63
|
+
// })
|
|
64
|
+
}
|
|
45
65
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
});
|
|
66
|
+
reset() {
|
|
67
|
+
this.activeMenu = null;
|
|
68
|
+
this.activeDesign = null;
|
|
69
|
+
this.displayMode = 'desktop';
|
|
70
|
+
this.displaySize = { px: 1200, percent: 100, gridSize: 16, aspectRatio: '16/9' }; // 현재 디스플레이 사이즈
|
|
53
71
|
}
|
|
54
72
|
|
|
55
73
|
/** 삭제 및 정리 */
|
|
@@ -67,6 +85,27 @@ class DisplayEngine {
|
|
|
67
85
|
console.log('[DisplayEngine] 삭제 완료');
|
|
68
86
|
}
|
|
69
87
|
|
|
88
|
+
getState() {
|
|
89
|
+
return {
|
|
90
|
+
displayMode: this.displayMode,
|
|
91
|
+
displaySize: { ...this.displaySize },
|
|
92
|
+
activeMenu: this.activeMenu,
|
|
93
|
+
activeDesign: this.activeDesign,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
setState(state) {
|
|
98
|
+
this.displayMode = state.displayMode;
|
|
99
|
+
this.displaySize = { ...state.displaySize };
|
|
100
|
+
this.activeMenu = state.activeMenu;
|
|
101
|
+
this.activeDesign = state.activeDesign;
|
|
102
|
+
|
|
103
|
+
// this.eventBus.emit('display:restoredState', {
|
|
104
|
+
// prev: state,
|
|
105
|
+
// timestamp: Date.now(),
|
|
106
|
+
// });
|
|
107
|
+
}
|
|
108
|
+
|
|
70
109
|
/** ---------------------------------- 공통 메소드 ---------------------------------- **/
|
|
71
110
|
|
|
72
111
|
/** 아이콘바 메뉴 변경
|
|
@@ -105,19 +144,30 @@ class DisplayEngine {
|
|
|
105
144
|
}
|
|
106
145
|
|
|
107
146
|
if (this.displayMode === mode) return;
|
|
147
|
+
|
|
148
|
+
const prevDisplayMode = this.displayMode;
|
|
149
|
+
const prevDisplaySize = { ...this.displaySize };
|
|
150
|
+
|
|
108
151
|
this.displayMode = mode;
|
|
152
|
+
this._resetDisplaySizeByMode(mode);
|
|
109
153
|
|
|
154
|
+
// displayMode 변경 시, displaySize도 초기화 됨
|
|
110
155
|
this.eventBus.emit('display:updateDisplayMode', {
|
|
111
|
-
displayMode:
|
|
156
|
+
displayMode: this.displayMode,
|
|
157
|
+
displaySize: this.displaySize,
|
|
158
|
+
prev: {
|
|
159
|
+
displayMode: prevDisplayMode,
|
|
160
|
+
displaySize: prevDisplaySize,
|
|
161
|
+
},
|
|
112
162
|
timestamp: Date.now(),
|
|
113
163
|
});
|
|
114
|
-
|
|
164
|
+
|
|
115
165
|
}
|
|
116
166
|
|
|
117
167
|
/** 사이즈 설정
|
|
118
168
|
* @param {string} mode - 디스플레이 모드
|
|
119
169
|
*/
|
|
120
|
-
|
|
170
|
+
_resetDisplaySizeByMode(mode) {
|
|
121
171
|
if (this.resource[mode]) {
|
|
122
172
|
this.displaySize = {
|
|
123
173
|
px: this.resource[mode]?.defaultWidth || 1200,
|
|
@@ -125,11 +175,6 @@ class DisplayEngine {
|
|
|
125
175
|
gridSize: this.resource[mode]?.gridSize || 16,
|
|
126
176
|
aspectRatio: this.resource[mode]?.aspectRatio || '16/9',
|
|
127
177
|
};
|
|
128
|
-
|
|
129
|
-
this.eventBus.emit('display:updateDisplaySizeByMode', {
|
|
130
|
-
displaySize: this.displaySize,
|
|
131
|
-
timestamp: Date.now(),
|
|
132
|
-
});
|
|
133
178
|
}
|
|
134
179
|
}
|
|
135
180
|
|
|
@@ -159,10 +204,12 @@ class DisplayEngine {
|
|
|
159
204
|
alert(`설정 가능한 최대 ${typeLimit.name}는 ${typeLimit.max}${typeLimit.unit}입니다.`);
|
|
160
205
|
}
|
|
161
206
|
|
|
207
|
+
const prevDisplaySize = { ...this.displaySize };
|
|
162
208
|
this.displaySize[type] = Math.min(Math.max(0, numSize), typeLimit.max);
|
|
163
209
|
|
|
164
210
|
this.eventBus.emit('display:updateDisplaySize', {
|
|
165
211
|
displaySize: this.displaySize,
|
|
212
|
+
prev: prevDisplaySize,
|
|
166
213
|
timestamp: Date.now(),
|
|
167
214
|
});
|
|
168
215
|
}
|