diff --git a/css/style.css b/css/style.css index 534f3ce..dc6a774 100644 --- a/css/style.css +++ b/css/style.css @@ -2,6 +2,15 @@ body { font-family: 'Inter', sans-serif; } +/* 统一处理 Iconify 图标的对齐方式,避免在按钮与文字中出现垂直偏移 */ +iconify-icon { + display: inline-flex; + align-items: center; + justify-content: center; + vertical-align: middle; + line-height: 1; +} + /* 狂野线条效果 */ .wild-border { border: 3px solid; @@ -223,9 +232,22 @@ body { transition: color 0.2s ease; } +.svg-placeholder-block { + position: relative; +} + +@keyframes svg-active-pulse { + 0% { box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.35), 0 6px 12px rgba(15, 23, 42, 0.15); } + 50% { box-shadow: 0 0 0 6px rgba(37, 99, 235, 0.15), 0 10px 18px rgba(15, 23, 42, 0.2); } + 100% { box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.35), 0 6px 12px rgba(15, 23, 42, 0.15); } +} + .svg-placeholder-active { - border-color: #2563eb; - box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.2); + border-color: #1d4ed8; + background: linear-gradient(135deg, #e0f2fe 0%, #dbeafe 100%); + color: #1e3a8a; + transform: translateY(-2px); + /* animation: svg-active-pulse 1.6s ease-in-out infinite; */ } .svg-content-wrapper { diff --git a/index.html b/index.html index ea09c65..6ed2897 100644 --- a/index.html +++ b/index.html @@ -25,6 +25,7 @@
@@ -43,10 +44,10 @@ -
+
-
+
@@ -85,7 +86,7 @@
-
+
diff --git a/js/app.js b/js/app.js index c32a068..95aeff0 100644 --- a/js/app.js +++ b/js/app.js @@ -26,6 +26,8 @@ class ProductCanvasApp { this.pendingSvgId = null; this.pendingCancel = false; this.copyClipboardSupported = typeof ClipboardItem !== 'undefined' && !!navigator.clipboard; + const deviceScale = typeof window !== 'undefined' ? (window.devicePixelRatio || 1) : 1; + this.imageExportScale = Math.min(4, Math.max(2, deviceScale)); this.initElements(); this.initEventListeners(); @@ -1214,7 +1216,7 @@ class ProductCanvasApp { }); } - async convertSvgToPngBlob(svgContent) { + async convertSvgToPngBlob(svgContent, options = {}) { const { width, height } = this.parseSvgDimensions(svgContent); const svgBlob = new Blob([svgContent], { type: 'image/svg+xml' }); const url = URL.createObjectURL(svgBlob); @@ -1222,14 +1224,16 @@ class ProductCanvasApp { try { const img = await this.loadImageFromUrl(url); const canvas = document.createElement('canvas'); - const canvasWidth = Math.max(1, img.naturalWidth || width || 1024); - const canvasHeight = Math.max(1, img.naturalHeight || height || 768); - canvas.width = canvasWidth; - canvas.height = canvasHeight; + const baseWidth = Math.max(1, img.naturalWidth || width || 1024); + const baseHeight = Math.max(1, img.naturalHeight || height || 768); + const preferredScale = options.scale || this.imageExportScale || 1; + const exportScale = Math.min(4, Math.max(1, preferredScale)); + canvas.width = Math.round(baseWidth * exportScale); + canvas.height = Math.round(baseHeight * exportScale); const ctx = canvas.getContext('2d'); - ctx.clearRect(0, 0, canvasWidth, canvasHeight); - ctx.drawImage(img, 0, 0, canvasWidth, canvasHeight); + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); return await new Promise((resolve, reject) => { canvas.toBlob((blob) => {