feat: 支持 mermaid 点击按钮放大缩小以及鼠标滑轮放大缩小

This commit is contained in:
huang 2025-01-03 14:55:49 +08:00 committed by 亢奋猫
parent a0413158c8
commit ce973ce3a0
8 changed files with 71 additions and 0 deletions

View File

@ -185,6 +185,7 @@ export class WindowService {
private loadMainWindowContent(mainWindow: BrowserWindow) { private loadMainWindowContent(mainWindow: BrowserWindow) {
if (is.dev && process.env['ELECTRON_RENDERER_URL']) { if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']) mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
mainWindow.webContents.openDevTools()
} else { } else {
mainWindow.loadFile(join(__dirname, '../renderer/index.html')) mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
} }

View File

@ -37,4 +37,32 @@ export const useMermaid = () => {
setTimeout(renderMermaid, 100) setTimeout(renderMermaid, 100)
}, [generating]) }, [generating])
useEffect(() => {
const handleWheel = (e: WheelEvent) => {
if (e.ctrlKey || e.metaKey) {
e.preventDefault()
const mermaidElement = (e.target as HTMLElement).closest('.mermaid')
if (!mermaidElement) return
const svg = mermaidElement.querySelector('svg')
if (!svg) return
const currentScale = parseFloat(svg.style.transform?.match(/scale\((.*?)\)/)?.[1] || '1')
const delta = e.deltaY < 0 ? 0.1 : -0.1
const newScale = Math.max(0.1, Math.min(3, currentScale + delta))
const container = svg.parentElement
if (container) {
container.style.overflow = 'auto'
container.style.position = 'relative'
svg.style.transformOrigin = 'top left'
svg.style.transform = `scale(${newScale})`
}
}
}
document.addEventListener('wheel', handleWheel, { passive: false })
return () => document.removeEventListener('wheel', handleWheel)
}, [])
} }

View File

@ -217,6 +217,10 @@
"png": "Download PNG", "png": "Download PNG",
"svg": "Download SVG" "svg": "Download SVG"
}, },
"resize": {
"zoom-in": "Zoom In",
"zoom-out": "Zoom Out"
},
"tabs": { "tabs": {
"preview": "Preview", "preview": "Preview",
"source": "Source" "source": "Source"

View File

@ -217,6 +217,10 @@
"png": "PNGをダウンロード", "png": "PNGをダウンロード",
"svg": "SVGをダウンロード" "svg": "SVGをダウンロード"
}, },
"resize": {
"zoom-in": "拡大する",
"zoom-out": "ズームアウト"
},
"tabs": { "tabs": {
"preview": "プレビュー", "preview": "プレビュー",
"source": "ソース" "source": "ソース"

View File

@ -217,6 +217,10 @@
"png": "Скачать PNG", "png": "Скачать PNG",
"svg": "Скачать SVG" "svg": "Скачать SVG"
}, },
"resize": {
"zoom-in": "Yвеличить",
"zoom-out": "Yменьшить масштаб"
},
"tabs": { "tabs": {
"preview": "Предпросмотр", "preview": "Предпросмотр",
"source": "Исходный код" "source": "Исходный код"

View File

@ -218,6 +218,10 @@
"png": "下载 PNG", "png": "下载 PNG",
"svg": "下载 SVG" "svg": "下载 SVG"
}, },
"resize": {
"zoom-in": "放大",
"zoom-out": "缩小"
},
"tabs": { "tabs": {
"preview": "预览", "preview": "预览",
"source": "源码" "source": "源码"

View File

@ -217,6 +217,10 @@
"png": "下載 PNG", "png": "下載 PNG",
"svg": "下載 SVG" "svg": "下載 SVG"
}, },
"resize": {
"zoom-in": "放大",
"zoom-out": "縮小"
},
"tabs": { "tabs": {
"preview": "預覽", "preview": "預覽",
"source": "原始碼" "source": "原始碼"

View File

@ -18,6 +18,7 @@ const PopupContainer: React.FC<Props> = ({ resolve, chart }) => {
const { t } = useTranslation() const { t } = useTranslation()
const mermaidId = `mermaid-popup-${Date.now()}` const mermaidId = `mermaid-popup-${Date.now()}`
const [activeTab, setActiveTab] = useState('preview') const [activeTab, setActiveTab] = useState('preview')
const [scale, setScale] = useState(1)
const onOk = () => { const onOk = () => {
setOpen(false) setOpen(false)
@ -31,6 +32,25 @@ const PopupContainer: React.FC<Props> = ({ resolve, chart }) => {
resolve({}) resolve({})
} }
const handleZoom = (delta: number) => {
const newScale = Math.max(0.1, Math.min(3, scale + delta))
setScale(newScale)
const element = document.getElementById(mermaidId)
if (!element) return
const svg = element.querySelector('svg')
if (!svg) return
const container = svg.parentElement
if (container) {
container.style.overflow = 'auto'
container.style.position = 'relative'
svg.style.transformOrigin = 'top left'
svg.style.transform = `scale(${newScale})`
}
}
const handleDownload = async (format: 'svg' | 'png') => { const handleDownload = async (format: 'svg' | 'png') => {
try { try {
const element = document.getElementById(mermaidId) const element = document.getElementById(mermaidId)
@ -110,6 +130,8 @@ const PopupContainer: React.FC<Props> = ({ resolve, chart }) => {
{activeTab === 'source' && <Button onClick={() => handleCopy()}>{t('common.copy')}</Button>} {activeTab === 'source' && <Button onClick={() => handleCopy()}>{t('common.copy')}</Button>}
{activeTab === 'preview' && ( {activeTab === 'preview' && (
<> <>
<Button onClick={() => handleZoom(0.1)}>{t('mermaid.resize.zoom-in')}</Button>
<Button onClick={() => handleZoom(-0.1)}>{t('mermaid.resize.zoom-out')}</Button>
<Button onClick={() => handleDownload('svg')}>{t('mermaid.download.svg')}</Button> <Button onClick={() => handleDownload('svg')}>{t('mermaid.download.svg')}</Button>
<Button onClick={() => handleDownload('png')}>{t('mermaid.download.png')}</Button> <Button onClick={() => handleDownload('png')}>{t('mermaid.download.png')}</Button>
</> </>