Skip to content

Commit

Permalink
Add Zoom layer esc exit, svg page size fit
Browse files Browse the repository at this point in the history
  • Loading branch information
charli117 committed Sep 13, 2024
1 parent 0a8074f commit 0c8eefa
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 11 deletions.
22 changes: 21 additions & 1 deletion web/app/components/base/image-uploader/image-preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const ImagePreview: FC<ImagePreviewProps> = ({
const imgRef = useRef<HTMLImageElement>(null)
const dragStartRef = useRef({ x: 0, y: 0 })
const [isCopied, setIsCopied] = useState(false)
const containerRef = useRef<HTMLDivElement>(null)

const openInNewTab = () => {
// Open in a new window, considering the case when the page is inside an iframe
Expand Down Expand Up @@ -187,14 +188,33 @@ const ImagePreview: FC<ImagePreviewProps> = ({
}
}, [handleMouseUp])

useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Escape')
onCancel()
}

window.addEventListener('keydown', handleKeyDown)

// Set focus to the container element
if (containerRef.current)
containerRef.current.focus()

// Cleanup function
return () => {
window.removeEventListener('keydown', handleKeyDown)
}
}, [onCancel])

return createPortal(
<div className='fixed inset-0 p-8 flex items-center justify-center bg-black/80 z-[1000] image-preview-container'
onClick={e => e.stopPropagation()}
onWheel={handleWheel}
onMouseDown={handleMouseDown}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
style={{ cursor: scale > 1 ? 'move' : 'default' }}>
style={{ cursor: scale > 1 ? 'move' : 'default' }}
tabIndex={-1}>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
ref={imgRef}
Expand Down
44 changes: 34 additions & 10 deletions web/app/components/base/markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,25 @@ const useLazyLoad = (ref: RefObject<Element>): boolean => {
const SVGRenderer = ({ content }: { content: string }) => {
const svgRef = useRef<HTMLDivElement>(null)
const [imagePreview, setImagePreview] = useState('')
const [windowSize, setWindowSize] = useState({
width: typeof window !== 'undefined' ? window.innerWidth : 0,
height: typeof window !== 'undefined' ? window.innerHeight : 0,
})

const svgToDataURL = (svgElement: Element): string => {
const svgString = new XMLSerializer().serializeToString(svgElement)
return `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(svgString)))}`
}

useEffect(() => {
const handleResize = () => {
setWindowSize({ width: window.innerWidth, height: window.innerHeight })
}

window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [])

useEffect(() => {
if (svgRef.current) {
try {
Expand All @@ -117,16 +130,18 @@ const SVGRenderer = ({ content }: { content: string }) => {
const svgDoc = parser.parseFromString(content, 'image/svg+xml')
const svgElement = svgDoc.documentElement

const width = svgElement.getAttribute('width') || '100%'
const height = svgElement.getAttribute('height') || '100%'
if (!(svgElement instanceof SVGElement))
throw new Error('Invalid SVG content')

draw.size(width, height)
const rootElement = draw.svg(content)
const originalWidth = parseInt(svgElement.getAttribute('width') || '400', 10)
const originalHeight = parseInt(svgElement.getAttribute('height') || '600', 10)
const scale = Math.min(windowSize.width / originalWidth, windowSize.height / originalHeight, 1)
const scaledWidth = originalWidth * scale
const scaledHeight = originalHeight * scale
draw.size(scaledWidth, scaledHeight)

// Optional: If you want to support custom fonts, add the following code
// document.fonts.ready.then(() => {
// draw.font('family', 'STKaiti, SimKai, SimSun, serif', '/path/to/font.ttf')
// })
const rootElement = draw.svg(content)
rootElement.scale(scale)

rootElement.click(() => {
setImagePreview(svgToDataURL(svgElement as Element))
Expand All @@ -138,11 +153,20 @@ const SVGRenderer = ({ content }: { content: string }) => {
svgRef.current.innerHTML = 'Error rendering SVG. Please check the console for details.'
}
}
}, [content])
}, [content, windowSize])

return (
<>
<div ref={svgRef} style={{ width: '100%', height: '100%', minHeight: '300px', cursor: 'pointer' }} />
<div ref={svgRef} style={{
width: '100%',
height: '100%',
minHeight: '300px',
maxHeight: '80vh',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
cursor: 'pointer',
}} />
{imagePreview && (<ImagePreview url={imagePreview} title='Preview' onCancel={() => setImagePreview('')} />)}
</>
)
Expand Down

0 comments on commit 0c8eefa

Please sign in to comment.