UNPKG

@wayz/react-gl

Version:

React Component for DeckGL, Base on AMap, Mapbox GL

164 lines (163 loc) 6.24 kB
// @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 }); }); }); }