write(ui): input-bar 高度也可拖拽(横向 splitter,row-resize 光标,60-window-200 px)
deploy write / build-and-deploy (push) Successful in 1m28s
deploy write / build-and-deploy (push) Successful in 1m28s
This commit is contained in:
@@ -16,33 +16,39 @@ const recording = ref(false)
|
||||
|
||||
onMounted(() => applyLayoutVars())
|
||||
|
||||
// ====== 拖拽布局:sidebar 宽(px) + editor/preview 比例(0-1)======
|
||||
// ====== 拖拽布局 ======
|
||||
// sidebarW: 侧栏宽(px) | editorRatio: 源码/预览比例(0-1) | inputH: 输入框高(px)
|
||||
const sidebarW = ref(parseInt(localStorage.getItem('write.sidebarW') || '260'))
|
||||
const editorRatio = ref(parseFloat(localStorage.getItem('write.editorRatio') || '0.5'))
|
||||
const inputH = ref(parseInt(localStorage.getItem('write.inputH') || '140'))
|
||||
|
||||
function applyLayoutVars(): void {
|
||||
const r = document.documentElement
|
||||
r.style.setProperty('--sidebar-w', sidebarW.value + 'px')
|
||||
r.style.setProperty('--editor-fr', editorRatio.value + 'fr')
|
||||
r.style.setProperty('--preview-fr', (1 - editorRatio.value) + 'fr')
|
||||
r.style.setProperty('--input-h', inputH.value + 'px')
|
||||
}
|
||||
|
||||
let dragKind: 'sidebar' | 'editor' | null = null
|
||||
let dragStartX = 0
|
||||
type DragKind = 'sidebar' | 'editor' | 'input'
|
||||
let dragKind: DragKind | null = null
|
||||
let dragStartPos = 0
|
||||
let dragStartVal = 0
|
||||
let dragPaneW = 0
|
||||
|
||||
function startDrag(e: MouseEvent, kind: 'sidebar' | 'editor'): void {
|
||||
function startDrag(e: MouseEvent, kind: DragKind): void {
|
||||
dragKind = kind
|
||||
dragStartX = e.clientX
|
||||
dragStartPos = kind === 'input' ? e.clientY : e.clientX
|
||||
if (kind === 'sidebar') {
|
||||
dragStartVal = sidebarW.value
|
||||
} else {
|
||||
} else if (kind === 'editor') {
|
||||
dragStartVal = editorRatio.value
|
||||
const pane = (e.currentTarget as HTMLElement).parentElement
|
||||
dragPaneW = pane ? pane.offsetWidth : window.innerWidth
|
||||
} else {
|
||||
dragStartVal = inputH.value
|
||||
}
|
||||
document.body.style.cursor = 'col-resize'
|
||||
document.body.style.cursor = kind === 'input' ? 'row-resize' : 'col-resize'
|
||||
document.body.style.userSelect = 'none'
|
||||
window.addEventListener('mousemove', onDrag)
|
||||
window.addEventListener('mouseup', endDrag)
|
||||
@@ -50,12 +56,17 @@ function startDrag(e: MouseEvent, kind: 'sidebar' | 'editor'): void {
|
||||
}
|
||||
function onDrag(e: MouseEvent): void {
|
||||
if (!dragKind) return
|
||||
const dx = e.clientX - dragStartX
|
||||
if (dragKind === 'sidebar') {
|
||||
sidebarW.value = Math.max(180, Math.min(500, dragStartVal + dx))
|
||||
if (dragKind === 'input') {
|
||||
const dy = dragStartPos - e.clientY // 向上拖 = 高度变大
|
||||
inputH.value = Math.max(60, Math.min(window.innerHeight - 200, dragStartVal + dy))
|
||||
} else {
|
||||
const newR = dragStartVal + dx / Math.max(1, dragPaneW)
|
||||
editorRatio.value = Math.max(0.15, Math.min(0.85, newR))
|
||||
const dx = e.clientX - dragStartPos
|
||||
if (dragKind === 'sidebar') {
|
||||
sidebarW.value = Math.max(180, Math.min(500, dragStartVal + dx))
|
||||
} else {
|
||||
const newR = dragStartVal + dx / Math.max(1, dragPaneW)
|
||||
editorRatio.value = Math.max(0.15, Math.min(0.85, newR))
|
||||
}
|
||||
}
|
||||
applyLayoutVars()
|
||||
}
|
||||
@@ -63,6 +74,7 @@ function endDrag(): void {
|
||||
if (!dragKind) return
|
||||
localStorage.setItem('write.sidebarW', String(sidebarW.value))
|
||||
localStorage.setItem('write.editorRatio', String(editorRatio.value))
|
||||
localStorage.setItem('write.inputH', String(inputH.value))
|
||||
dragKind = null
|
||||
document.body.style.cursor = ''
|
||||
document.body.style.userSelect = ''
|
||||
@@ -318,6 +330,8 @@ onMounted(() => {
|
||||
<div class="preview" v-html="renderedPreview"></div>
|
||||
</div>
|
||||
|
||||
<div class="splitter splitter-input" @mousedown="startDrag($event, 'input')" title="拖动调整输入框高度"></div>
|
||||
|
||||
<div class="input-bar">
|
||||
<div class="input-row">
|
||||
<textarea
|
||||
|
||||
@@ -79,7 +79,7 @@ textarea, input { font: inherit; }
|
||||
|
||||
.workspace {
|
||||
display: grid;
|
||||
grid-template-rows: 1fr auto;
|
||||
grid-template-rows: 1fr 6px var(--input-h, 140px);
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
background: #fafafa;
|
||||
@@ -108,6 +108,9 @@ textarea, input { font: inherit; }
|
||||
.splitter:hover { background: #b0c5ff; }
|
||||
.splitter-main { /* sidebar | workspace */ }
|
||||
.splitter-editor { /* editor | preview */ }
|
||||
.splitter-input { /* editor-pane | input-bar 横向分隔 */
|
||||
cursor: row-resize;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.splitter { display: none; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user