35 lines
1.3 KiB
JavaScript
35 lines
1.3 KiB
JavaScript
/**
|
|
* 画个标 · 海报渲染引擎:元素数组 → SVG 字符串
|
|
*/
|
|
const HGB_PosterRenderer = (function () {
|
|
'use strict';
|
|
|
|
function esc(s) {
|
|
return String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
}
|
|
|
|
function elToSvg(el) {
|
|
if (el.type === 'rect') {
|
|
return `<rect x="${el.x}" y="${el.y}" width="${el.w}" height="${el.h}" fill="${el.fill}"/>`;
|
|
}
|
|
if (el.type === 'circle') {
|
|
return `<circle cx="${el.cx}" cy="${el.cy}" r="${el.r}" fill="${el.fill}"/>`;
|
|
}
|
|
if (el.type === 'text') {
|
|
const anchor = el.align === 'middle' ? 'middle' : 'start';
|
|
return `<text x="${el.x}" y="${el.y}" font-family="SimHei, Microsoft YaHei, sans-serif" font-size="${el.fontSize}" font-weight="${el.fontWeight}" fill="${el.fill}" text-anchor="${anchor}" dominant-baseline="middle">${esc(el.text)}</text>`;
|
|
}
|
|
if (el.type === 'icon') {
|
|
return `<g transform="translate(${el.x} ${el.y}) scale(${el.w / 24})">${el.svg}</g>`;
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function render(spec, elements) {
|
|
const body = (elements || []).map(elToSvg).join('');
|
|
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${spec.w} ${spec.h}" width="${spec.w}" height="${spec.h}">${body}</svg>`;
|
|
}
|
|
|
|
return { render };
|
|
})();
|