Add JSDoc comments and clarify SvgViewer usage

This commit is contained in:
ema
2025-07-01 02:23:38 +08:00
parent 2a94fa155d
commit f1237aa86f

View File

@@ -1,12 +1,23 @@
// SvgViewer: Provides SVG preview with the following features: /**
// - Fit SVG to window with no upscaling * SvgViewer: Provides SVG preview with the following features.
// - Mouse wheel zoom in/out (with smooth animation) *
// - Double-click to fit SVG to window * Requirements:
// - Mouse drag to pan (only when SVG is larger than the container) * - Requires the following HTML structure:
// - Pan is limited to visible overflow area * <div id="svgContainer">
// - Handles SVGs with or without width/height/viewBox attributes * <div id="svgWrapper"></div>
// - Resets pan on zoom or fit * </div>
// - No animation during pan, smooth animation during zoom/fit * - SVG content is obtained via chrome.webview.hostObjects.external.GetSvgContent()
*
* Features:
* - Fit SVG to window with no upscaling
* - Mouse wheel zoom in/out (with smooth animation)
* - Double-click to fit SVG to window
* - Mouse drag to pan (only when SVG is larger than the container)
* - Pan is limited to visible overflow area
* - Handles SVGs with or without width/height/viewBox attributes
* - Resets pan on zoom or fit
* - No animation during pan, smooth animation during zoom/fit
*/
class SvgViewer { class SvgViewer {
constructor() { constructor() {
// Initial scale and scale limits // Initial scale and scale limits
@@ -33,7 +44,10 @@ class SvgViewer {
this.lastMouseY = 0; this.lastMouseY = 0;
} }
// Ensure SVG has proper size attributes and extract viewBox dimensions /**
* Ensure SVG has proper size attributes and extract viewBox dimensions.
* @param {SVGElement} svgElement The SVG element to fix.
*/
fixSvgSize(svgElement) { fixSvgSize(svgElement) {
let widthAttr = svgElement.getAttribute('width'); let widthAttr = svgElement.getAttribute('width');
let heightAttr = svgElement.getAttribute('height'); let heightAttr = svgElement.getAttribute('height');
@@ -71,7 +85,10 @@ class SvgViewer {
this.viewBoxHeight = viewBoxHeight; this.viewBoxHeight = viewBoxHeight;
} }
// Calculate the base scale to fit SVG into the container /**
* Calculate the base scale to fit SVG into the container.
* @returns {number} The base scale factor.
*/
computeBaseScale() { computeBaseScale() {
if (!this.viewBoxWidth || !this.viewBoxHeight) return 1; if (!this.viewBoxWidth || !this.viewBoxHeight) return 1;
@@ -82,7 +99,9 @@ class SvgViewer {
return Math.min(scaleX, scaleY, 1); // Never upscale by default return Math.min(scaleX, scaleY, 1); // Never upscale by default
} }
// Update SVG transform for scale and pan /**
* Update SVG transform for scale and pan.
*/
updateTransform() { updateTransform() {
// Calculate actual SVG display size // Calculate actual SVG display size
const container = document.getElementById('svgContainer'); const container = document.getElementById('svgContainer');
@@ -103,19 +122,25 @@ class SvgViewer {
this.svgElement.style.transformOrigin = 'center center'; this.svgElement.style.transformOrigin = 'center center';
} }
// Enable transform transition (for zoom) /**
* Enable transform transition (for zoom).
*/
enableTransition() { enableTransition() {
this.svgElement.style.transition = 'transform 0.1s ease-out'; this.svgElement.style.transition = 'transform 0.1s ease-out';
this.transitionEnabled = true; this.transitionEnabled = true;
} }
// Disable transform transition (for pan) /**
* Disable transform transition (for pan).
*/
disableTransition() { disableTransition() {
this.svgElement.style.transition = ''; this.svgElement.style.transition = '';
this.transitionEnabled = false; this.transitionEnabled = false;
} }
// Fit SVG to window and reset pan /**
* Fit SVG to window and reset pan.
*/
fitToWindow() { fitToWindow() {
this.baseScale = this.computeBaseScale(); this.baseScale = this.computeBaseScale();
this.scale = this.baseScale; this.scale = this.baseScale;
@@ -124,7 +149,9 @@ class SvgViewer {
this.updateTransform(); this.updateTransform();
} }
// Bind mouse and wheel events for zoom and pan /**
* Bind mouse and wheel events for zoom and pan.
*/
bindEvents() { bindEvents() {
// Zoom with mouse wheel // Zoom with mouse wheel
this.wrapper.addEventListener("wheel", (e) => { this.wrapper.addEventListener("wheel", (e) => {
@@ -167,6 +194,7 @@ class SvgViewer {
this.disableTransition(); // Disable animation while panning this.disableTransition(); // Disable animation while panning
} }
}); });
// Pan on mouse move // Pan on mouse move
window.addEventListener('mousemove', (e) => { window.addEventListener('mousemove', (e) => {
if (!this.isDragging) return; if (!this.isDragging) return;
@@ -192,6 +220,7 @@ class SvgViewer {
this.updateTransform(); this.updateTransform();
} }
}); });
// End pan on mouse up // End pan on mouse up
window.addEventListener('mouseup', () => { window.addEventListener('mouseup', () => {
if (this.isDragging) { if (this.isDragging) {
@@ -201,7 +230,10 @@ class SvgViewer {
}); });
} }
// Initialize SVG viewer /**
* Initialize SVG viewer.
* @async
*/
async init() { async init() {
const rawSvg = await chrome.webview.hostObjects.external.GetSvgContent(); const rawSvg = await chrome.webview.hostObjects.external.GetSvgContent();
const parser = new DOMParser(); const parser = new DOMParser();