/** * 将 SVG 字符串转为小程序可用的 data URL(base64 在真机上更稳定) */ function utf8ToBytes(str) { const encoded = encodeURIComponent(str) const bytes = [] for (let i = 0; i < encoded.length; i++) { if (encoded.charCodeAt(i) === 37) { bytes.push(parseInt(encoded.substring(i + 1, i + 3), 16)) i += 2 } else { bytes.push(encoded.charCodeAt(i)) } } return new Uint8Array(bytes) } function bytesToBase64(bytes) { if (typeof uni !== 'undefined' && typeof uni.arrayBufferToBase64 === 'function') { return uni.arrayBufferToBase64(bytes.buffer) } if (typeof btoa !== 'undefined') { let binary = '' for (let i = 0; i < bytes.length; i++) { binary += String.fromCharCode(bytes[i]) } return btoa(binary) } const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' let result = '' for (let i = 0; i < bytes.length; i += 3) { const a = bytes[i] const b = i + 1 < bytes.length ? bytes[i + 1] : 0 const c = i + 2 < bytes.length ? bytes[i + 2] : 0 result += chars[a >> 2] result += chars[((a & 3) << 4) | (b >> 4)] result += i + 1 < bytes.length ? chars[((b & 15) << 2) | (c >> 6)] : '=' result += i + 2 < bytes.length ? chars[c & 63] : '=' } return result } export function svgToDataUrl(svg) { const normalized = String(svg || '').trim() if (!normalized) return '' const base64 = bytesToBase64(utf8ToBytes(normalized)) return `data:image/svg+xml;base64,${base64}` }