first commit
This commit is contained in:
80
apps/miniprogram/utils/svgDataUri.js
Normal file
80
apps/miniprogram/utils/svgDataUri.js
Normal file
@@ -0,0 +1,80 @@
|
||||
const BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
/**
|
||||
* 把 SVG 文本编码成 UTF-8 字节。
|
||||
* 说明:
|
||||
* 1. 小程序运行时没有稳定可用的 Buffer,因此这里使用纯 JS 编码;
|
||||
* 2. 需要显式处理代理对,避免非 ASCII 字符在 data URI 中损坏;
|
||||
* 3. 非法代理项统一替换成 U+FFFD,保证输出始终可编码。
|
||||
*/
|
||||
function encodeUtf8Bytes(input) {
|
||||
const source = String(input || "");
|
||||
const bytes = [];
|
||||
for (let index = 0; index < source.length; index += 1) {
|
||||
const first = source.charCodeAt(index);
|
||||
if (first < 0x80) {
|
||||
bytes.push(first);
|
||||
continue;
|
||||
}
|
||||
if (first < 0x800) {
|
||||
bytes.push(0xc0 | (first >> 6), 0x80 | (first & 0x3f));
|
||||
continue;
|
||||
}
|
||||
|
||||
let codePoint = first;
|
||||
if (first >= 0xd800 && first <= 0xdbff) {
|
||||
const second = source.charCodeAt(index + 1);
|
||||
if (second >= 0xdc00 && second <= 0xdfff) {
|
||||
codePoint = ((first - 0xd800) << 10) + (second - 0xdc00) + 0x10000;
|
||||
index += 1;
|
||||
} else {
|
||||
codePoint = 0xfffd;
|
||||
}
|
||||
} else if (first >= 0xdc00 && first <= 0xdfff) {
|
||||
codePoint = 0xfffd;
|
||||
}
|
||||
|
||||
if (codePoint < 0x10000) {
|
||||
bytes.push(0xe0 | (codePoint >> 12), 0x80 | ((codePoint >> 6) & 0x3f), 0x80 | (codePoint & 0x3f));
|
||||
continue;
|
||||
}
|
||||
|
||||
bytes.push(
|
||||
0xf0 | (codePoint >> 18),
|
||||
0x80 | ((codePoint >> 12) & 0x3f),
|
||||
0x80 | ((codePoint >> 6) & 0x3f),
|
||||
0x80 | (codePoint & 0x3f)
|
||||
);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把 UTF-8 字节数组转成 base64。
|
||||
* 这样生成的 data URI 可以避开开发者工具对 `utf8,...` 形式 SVG URI 的兼容问题。
|
||||
*/
|
||||
function encodeBase64FromBytes(bytes) {
|
||||
const output = [];
|
||||
for (let index = 0; index < bytes.length; index += 3) {
|
||||
const first = bytes[index];
|
||||
const second = index + 1 < bytes.length ? bytes[index + 1] : null;
|
||||
const third = index + 2 < bytes.length ? bytes[index + 2] : null;
|
||||
const triplet = (first << 16) | ((second || 0) << 8) | (third || 0);
|
||||
output.push(
|
||||
BASE64_ALPHABET[(triplet >> 18) & 0x3f],
|
||||
BASE64_ALPHABET[(triplet >> 12) & 0x3f],
|
||||
second === null ? "=" : BASE64_ALPHABET[(triplet >> 6) & 0x3f],
|
||||
third === null ? "=" : BASE64_ALPHABET[triplet & 0x3f]
|
||||
);
|
||||
}
|
||||
return output.join("");
|
||||
}
|
||||
|
||||
function toSvgDataUri(svg) {
|
||||
const base64 = encodeBase64FromBytes(encodeUtf8Bytes(svg));
|
||||
return `data:image/svg+xml;base64,${base64}`;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
toSvgDataUri
|
||||
};
|
||||
Reference in New Issue
Block a user