@wayz/react-gl
Version:
React Component for DeckGL, Base on AMap, Mapbox GL
164 lines (163 loc) • 6.24 kB
JavaScript
// @ts-nocheck
/**
* 将普通 SVG 字符串或 SVG DOM 节点转换为具有自定义尺寸的图像
*
* @param {Object} settings 默认设置
* @returns {Promise}
*/
function SVGToImage(settings) {
var _settings = {
svg: null,
// 通常所有 SVG 都具有透明度,因此默认情况下使用 PNG
mimetype: 'image/png',
quality: 0.92,
width: 'auto',
height: 'auto',
outputFormat: 'base64',
};
// 重写默认设置
for (var key in settings) {
_settings[key] = settings[key];
}
return new Promise(function (resolve, reject) {
var svgNode;
if (typeof _settings.svg == 'string') {
var SVGContainer = document.createElement('div');
SVGContainer.style.display = 'none';
SVGContainer.innerHTML = _settings.svg;
svgNode = SVGContainer.firstElementChild;
}
else {
svgNode = _settings.svg;
}
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var svgXml = new XMLSerializer().serializeToString(svgNode);
var svgBase64 = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svgXml)));
var image = new Image();
image.onload = function () {
var _this = this;
var finalWidth, finalHeight;
// 如果设置为 auto 并且指定了高度,则计算宽度(以保持纵横比)
if (_settings.width === 'auto' && _settings.height !== 'auto') {
finalWidth = (_this.width / _this.height) * _settings.height;
// 使用图像原始宽度
}
else if (_settings.width === 'auto') {
finalWidth = _this.naturalWidth;
// 使用自定义宽度
}
else {
finalWidth = _settings.width;
}
// 如果设置为 auto 并且指定了宽度,则计算高度(以保持纵横比)
if (_settings.height === 'auto' && _settings.width !== 'auto') {
finalHeight = (_this.height / _this.width) * _settings.width;
// 使用图像原始高度
}
else if (_settings.height === 'auto') {
finalHeight = _this.naturalHeight;
// 使用自定义高度
}
else {
finalHeight = _settings.height;
}
// 定义canvas内在大小
canvas.width = finalWidth;
canvas.height = finalHeight;
// 渲染图像
context.drawImage(_this, 0, 0, finalWidth, finalHeight);
if (_settings.outputFormat === 'blob') {
// 返回Blob
canvas.toBlob(function (blob) {
resolve(blob);
}, _settings.mimetype, _settings.quality);
}
else {
// 返回Base64
resolve(canvas.toDataURL(_settings.mimetype, _settings.quality));
}
};
// 加载base64 SVG
image.src = svgBase64;
});
}
/**
* 获取dom对应图片的base64地址
* @param {HTMLElement} target
* @returns 图片的base64地址
*/
function getSVGString(target) {
//克隆一份dom节点
var cloneDom = target.cloneNode(true);
cloneDom.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
var _a = target.getBoundingClientRect(), width = _a.width, height = _a.height;
//转成svg字符串
var xmlContent = "\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"".concat(width, "\" height=\"").concat(height, "\">\n <foreignObject x=\"0\" y=\"0\" width=\"100%\" height=\"100%\">\n ").concat(target.outerHTML, "\n </foreignObject>\n </svg>\n ");
return xmlContent;
//处理部分特殊字符
// eslint-disable-next-line
return xmlContent.replace(/\n/g, '').replace(/\t/g, '').replace(/#/g, '%23');
}
/**
* 根据数据获取dom
* @param {any[]} data
* @param {Function} getHtml
* @return {HTMLDivElement} dom元素
*/
function getDom(data, getHtml) {
var iconMappingDom = document.createElement('div');
iconMappingDom.setAttribute('style', 'z-index: -1;position: absolute;top: 0;left: 0;display: flex;algin-item: center;flex-wrap: wrap;');
var html = '';
for (var _i = 0, _a = Object.entries(data); _i < _a.length; _i++) {
var _b = _a[_i], item = _b[1];
var dom = getHtml(item);
html += dom;
}
iconMappingDom.innerHTML = html;
return iconMappingDom;
}
/**
* 根据数据和自定义html生成函数, 生成iconAtlas和 iconMapping
*
* @export
* @param {any[]} data
* @param {(item: any) => string} getHtml
* @param {HTMLElement} [container]
* @return {{ iconAtlas: string; iconMapping: any }}
*/
export function domToIconMapping(data, getHtml, container) {
return new Promise(function (resolve, reject) {
container = container !== null && container !== void 0 ? container : document.body;
// 获取 iconMappingDom
var iconMappingDom = getDom(data, getHtml);
// 插入页面
container.appendChild(iconMappingDom);
var iconMapping = {};
var rect = iconMappingDom.getBoundingClientRect();
// 遍历iconMappingDom children生成mapping
iconMappingDom.childNodes.forEach(function (node, i) {
var nodeRect = node.getBoundingClientRect();
var iconName = 'icon_' + i;
iconMapping[iconName] = {
x: nodeRect.left - rect.left,
y: nodeRect.top - rect.top,
width: nodeRect.width,
height: nodeRect.height,
// mask: false,
};
if (data[i])
data[i]['_icon_'] = iconName;
});
// 获取图片
var svgStr = getSVGString(iconMappingDom);
SVGToImage({
svg: svgStr,
quality: 1,
}).then(function (dataUrl) {
// 移除dom
iconMappingDom.remove();
resolve({ iconAtlas: dataUrl, iconMapping: iconMapping });
});
});
}