|
|
@@ -70,6 +70,23 @@
|
|
|
</svg>
|
|
|
</div>
|
|
|
</Popover>
|
|
|
+ <!-- 工具iframe字号缩放:比例1~24,每±1对应字号±1px,初始16px -->
|
|
|
+ <div class="handler-item font-scale-ctrl" v-if="hasInteractiveTool">
|
|
|
+ <span class="scale-btn" :class="{ disable: fontScale <= MIN_FONT_SCALE }" @click="changeFontScale(-1)">
|
|
|
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
|
|
+ stroke-linecap="round">
|
|
|
+ <line x1="5" y1="12" x2="19" y2="12" />
|
|
|
+ </svg>
|
|
|
+ </span>
|
|
|
+ <span class="scale-value">{{ fontScale }}</span>
|
|
|
+ <span class="scale-btn" :class="{ disable: fontScale >= MAX_FONT_SCALE }" @click="changeFontScale(1)">
|
|
|
+ <svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
|
|
+ stroke-linecap="round">
|
|
|
+ <line x1="12" y1="5" x2="12" y2="19" />
|
|
|
+ <line x1="5" y1="12" x2="19" y2="12" />
|
|
|
+ </svg>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
<Popover trigger="click" v-model:value="textTypeSelectVisible"
|
|
|
style="height: 100%;display: flex;align-items: center;" :offset="10" v-if="!isFrame">
|
|
|
<template #content>
|
|
|
@@ -341,6 +358,32 @@ const hasInteractiveTool = computed(() => {
|
|
|
return elements.some((el: any) => el.type === 'frame' && toolTypeArray.value.includes(el.toolType))
|
|
|
})
|
|
|
|
|
|
+// 工具iframe字号缩放:比例最小1最大24,每±1对应字号±1px,初始16px
|
|
|
+const MIN_FONT_SCALE = 1
|
|
|
+const MAX_FONT_SCALE = 24
|
|
|
+const BASE_FONT_SIZE = 16
|
|
|
+const fontScale = ref(1)
|
|
|
+
|
|
|
+const setToolIframeFontSize = () => {
|
|
|
+ try {
|
|
|
+ const iframe = document.getElementsByTagName('iframe')[0] as HTMLIFrameElement | undefined
|
|
|
+ const iframeDoc = iframe?.contentWindow?.document
|
|
|
+ if (iframeDoc?.documentElement) {
|
|
|
+ iframeDoc.documentElement.style.fontSize = `${BASE_FONT_SIZE + fontScale.value - 1}px`
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (error) {
|
|
|
+ console.warn('设置iframe字号失败:', error)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const changeFontScale = (delta: number) => {
|
|
|
+ const next = fontScale.value + delta
|
|
|
+ if (next < MIN_FONT_SCALE || next > MAX_FONT_SCALE) return
|
|
|
+ fontScale.value = next
|
|
|
+ setToolIframeFontSize()
|
|
|
+}
|
|
|
+
|
|
|
const iframeLabel = computed(() => {
|
|
|
return getTypeLabel(frametype.value)
|
|
|
})
|
|
|
@@ -730,6 +773,36 @@ const updateGradientColors = (color: string) => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+.font-scale-ctrl {
|
|
|
+ gap: 8px;
|
|
|
+ padding: 0 10px;
|
|
|
+
|
|
|
+ .scale-btn {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ svg {
|
|
|
+ width: 14px;
|
|
|
+ height: 14px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ color: #f89c46;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.disable {
|
|
|
+ opacity: .4;
|
|
|
+ cursor: not-allowed;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .scale-value {
|
|
|
+ min-width: 20px;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 13px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
.reset-preview-btn {
|
|
|
gap: 5px;
|
|
|
color: #6b7280;
|