File size: 3,423 Bytes
89ce340
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3065c1d
f27eeb4
 
 
 
 
 
 
3065c1d
 
f27eeb4
3065c1d
 
 
 
 
f27eeb4
3065c1d
 
f27eeb4
 
 
 
 
 
 
 
 
3065c1d
 
 
f27eeb4
 
 
 
 
 
 
3065c1d
 
 
 
 
 
 
 
 
f27eeb4
3065c1d
 
 
f27eeb4
 
3065c1d
 
89ce340
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// svg转base64图片,参考:https://github.com/scriptex/svg64

const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
const PREFIX = 'data:image/svg+xml;base64,'

const utf8Encode = (string: string) => {
  string = string.replace(/\r\n/g, '\n')
  let utftext = ''

  for (let n = 0; n < string.length; n++) {
    const c = string.charCodeAt(n)

    if (c < 128) {
      utftext += String.fromCharCode(c)
    }
    else if (c > 127 && c < 2048) {
      utftext += String.fromCharCode((c >> 6) | 192)
      utftext += String.fromCharCode((c & 63) | 128)
    }
    else {
      utftext += String.fromCharCode((c >> 12) | 224)
      utftext += String.fromCharCode(((c >> 6) & 63) | 128)
      utftext += String.fromCharCode((c & 63) | 128)
    }
  }

  return utftext
}

const encode = (input: string) => {
  let output = ''
  let chr1, chr2, chr3, enc1, enc2, enc3, enc4
  let i = 0
  input = utf8Encode(input)
  while (i < input.length) {
    chr1 = input.charCodeAt(i++)
    chr2 = input.charCodeAt(i++)
    chr3 = input.charCodeAt(i++)
    enc1 = chr1 >> 2
    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4)
    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6)
    enc4 = chr3 & 63
    if (isNaN(chr2)) enc3 = enc4 = 64
    else if (isNaN(chr3)) enc4 = 64
    output = output + characters.charAt(enc1) + characters.charAt(enc2) + characters.charAt(enc3) + characters.charAt(enc4)
  }
  return output
}

export const svg2Base64 = (element: Element) => {
  try {
    console.log('svg2Base64: Starting conversion for element:', {
      tagName: element.tagName,
      className: element.className,
      id: element.id,
      hasChildren: element.children.length > 0
    });
    
    // 克隆元素以避免修改原始DOM
    const clonedElement = element.cloneNode(true) as Element;
    console.log('svg2Base64: Element cloned successfully');
    
    // 确保SVG有正确的命名空间
    if (clonedElement.tagName.toLowerCase() === 'svg') {
      clonedElement.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
      clonedElement.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
      console.log('svg2Base64: Added SVG namespaces');
    }
    
    // 检查是否有内联样式需要处理
    const computedStyles = window.getComputedStyle(element);
    console.log('svg2Base64: Element computed styles:', {
      width: computedStyles.width,
      height: computedStyles.height,
      display: computedStyles.display,
      visibility: computedStyles.visibility
    });
    
    const XMLS = new XMLSerializer();
    const svg = XMLS.serializeToString(clonedElement);
    
    console.log('svg2Base64: Serialization result:', {
      length: svg.length,
      preview: svg.substring(0, 200) + '...',
      containsSvgTag: svg.includes('<svg'),
      containsContent: svg.length > 50
    });
    
    if (!svg || svg.length === 0) {
      throw new Error('SVG serialization returned empty string');
    }
    
    const encoded = encode(svg);
    if (!encoded) {
      throw new Error('Base64 encoding failed');
    }
    
    console.log('svg2Base64: Encoding successful, result length:', (PREFIX + encoded).length);
    return PREFIX + encoded;
  } catch (error) {
    console.error('svg2Base64 failed:', error);
    console.error('svg2Base64: Element that caused error:', element);
    console.error('svg2Base64: Element outerHTML:', element.outerHTML);
    throw error;
  }
}