mirror of
https://github.com/jackyzha0/quartz.git
synced 2025-12-20 11:24:05 -06:00
Merge 36e16cd195 into c99c8070f2
This commit is contained in:
commit
c6c5273d53
@ -12,6 +12,7 @@ class DiagramPanZoom {
|
||||
private scale = 1
|
||||
private readonly MIN_SCALE = 0.5
|
||||
private readonly MAX_SCALE = 3
|
||||
private resizeTimeout?: number
|
||||
|
||||
cleanups: (() => void)[] = []
|
||||
|
||||
@ -29,7 +30,7 @@ class DiagramPanZoom {
|
||||
const mouseDownHandler = this.onMouseDown.bind(this)
|
||||
const mouseMoveHandler = this.onMouseMove.bind(this)
|
||||
const mouseUpHandler = this.onMouseUp.bind(this)
|
||||
const resizeHandler = this.resetTransform.bind(this)
|
||||
const resizeHandler = this.onResize.bind(this)
|
||||
|
||||
this.container.addEventListener("mousedown", mouseDownHandler)
|
||||
document.addEventListener("mousemove", mouseMoveHandler)
|
||||
@ -44,10 +45,20 @@ class DiagramPanZoom {
|
||||
)
|
||||
}
|
||||
|
||||
private onResize() {
|
||||
if (this.resizeTimeout) {
|
||||
clearTimeout(this.resizeTimeout)
|
||||
}
|
||||
this.resizeTimeout = window.setTimeout(() => this.resetTransform(), 50)
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
for (const cleanup of this.cleanups) {
|
||||
cleanup()
|
||||
}
|
||||
if (this.resizeTimeout) {
|
||||
clearTimeout(this.resizeTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
private setupNavigationControls() {
|
||||
@ -102,16 +113,22 @@ class DiagramPanZoom {
|
||||
private zoom(delta: number) {
|
||||
const newScale = Math.min(Math.max(this.scale + delta, this.MIN_SCALE), this.MAX_SCALE)
|
||||
|
||||
// Zoom around center
|
||||
const rect = this.content.getBoundingClientRect()
|
||||
const centerX = rect.width / 2
|
||||
const centerY = rect.height / 2
|
||||
// Zoom around the center of the container viewport, not the content
|
||||
const containerRect = this.container.getBoundingClientRect()
|
||||
const centerX = containerRect.width / 2
|
||||
const centerY = containerRect.height / 2
|
||||
|
||||
const scaleDiff = newScale - this.scale
|
||||
this.currentPan.x -= centerX * scaleDiff
|
||||
this.currentPan.y -= centerY * scaleDiff
|
||||
// Calculate the point we're zooming around relative to current transform
|
||||
const zoomPointX = (centerX - this.currentPan.x) / this.scale
|
||||
const zoomPointY = (centerY - this.currentPan.y) / this.scale
|
||||
|
||||
// Update scale
|
||||
this.scale = newScale
|
||||
|
||||
// Adjust pan to keep the zoom point in the same screen position
|
||||
this.currentPan.x = centerX - zoomPointX * this.scale
|
||||
this.currentPan.y = centerY - zoomPointY * this.scale
|
||||
|
||||
this.updateTransform()
|
||||
}
|
||||
|
||||
@ -120,12 +137,23 @@ class DiagramPanZoom {
|
||||
}
|
||||
|
||||
private resetTransform() {
|
||||
this.scale = 1
|
||||
// Get container dimensions
|
||||
const containerRect = this.container.getBoundingClientRect()
|
||||
const svg = this.content.querySelector("svg")!
|
||||
|
||||
const svgRect = svg.getBoundingClientRect()
|
||||
|
||||
// svgRect is scaled by this.scale. We want the unscaled size.
|
||||
const svgWidth = svgRect.width / this.scale
|
||||
const svgHeight = svgRect.height / this.scale
|
||||
|
||||
this.scale = 1
|
||||
// Calculate center position relative to container
|
||||
this.currentPan = {
|
||||
x: svg.getBoundingClientRect().width / 2,
|
||||
y: svg.getBoundingClientRect().height / 2,
|
||||
x: (containerRect.width - svgWidth) / 2,
|
||||
y: (containerRect.height - svgHeight) / 2,
|
||||
}
|
||||
|
||||
this.updateTransform()
|
||||
}
|
||||
}
|
||||
@ -237,8 +265,10 @@ document.addEventListener("nav", async () => {
|
||||
popupContainer.classList.add("active")
|
||||
container.style.cursor = "grab"
|
||||
|
||||
// Initialize pan-zoom after showing the popup
|
||||
panZoom = new DiagramPanZoom(container, content)
|
||||
// Initialize pan-zoom after showing the popup and let the layout settle
|
||||
requestAnimationFrame(() => {
|
||||
panZoom = new DiagramPanZoom(container, content)
|
||||
})
|
||||
}
|
||||
|
||||
function hideMermaid() {
|
||||
|
||||
@ -53,7 +53,7 @@ pre {
|
||||
}
|
||||
|
||||
& > #mermaid-space {
|
||||
border: 1px solid var(--lightgray);
|
||||
border: 0.2vh solid var(--lightgray);
|
||||
background-color: var(--light);
|
||||
border-radius: 5px;
|
||||
position: fixed;
|
||||
@ -86,14 +86,14 @@ pre {
|
||||
|
||||
& > .mermaid-controls {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
bottom: 2.5vh;
|
||||
right: 2.5vw;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 8px;
|
||||
gap: 0.5vw;
|
||||
padding: 1vh 0.5vw;
|
||||
background: var(--light);
|
||||
border: 1px solid var(--lightgray);
|
||||
border-radius: 6px;
|
||||
border: 0.2vh solid var(--lightgray);
|
||||
border-radius: 0.8vh;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
z-index: 2;
|
||||
|
||||
@ -101,15 +101,15 @@ pre {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
width: 4.5vh;
|
||||
height: 4.5vh;
|
||||
padding: 0;
|
||||
border: 1px solid var(--lightgray);
|
||||
border: 0.2vh solid var(--lightgray);
|
||||
background: var(--light);
|
||||
color: var(--dark);
|
||||
border-radius: 4px;
|
||||
border-radius: 0.5vh;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
font-size: 2vh;
|
||||
font-family: var(--bodyFont);
|
||||
transition: all 0.2s ease;
|
||||
|
||||
@ -121,11 +121,10 @@ pre {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
// Style the reset button differently
|
||||
&:nth-child(2) {
|
||||
width: auto;
|
||||
padding: 0 12px;
|
||||
font-size: 14px;
|
||||
padding: 0 1vw;
|
||||
font-size: 2vh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user