svg 渲染 html 标签 及 添加到 canvas 中
主要用到 svg 的 foreignObject
https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/foreignObject
记录demo
import { fabric } from "fabric";
import { Pieces } from "../@share/pieces";
/**
* svg 将 html 内容转成 图片并添加到 canvas 中;支持改变并重新渲染
*/
export class SvgForeignObject {
width = '100px';
height = '50px';
styleObj = {
'font-weight': 'bold',
'background-color': 'blue',
'font-size': '16px',
'color': '#fff',
'border-radius': '5px',
'width': this.width,
'height': this.height,
};
style = ''; // 最终使用的样式列表
innerHTML = 'Button';
constructor() {
let body = $('body');
// fabric 获取 canvas 对象
let canvas = this.getCanvas(body);
// 添加改变样式的操作按钮
this.addButtons(canvas, body);
// 开始绘制
this.init(canvas, body);
}
/**
* 流程整理成调用方法
* @param canvas
* @param body
*/
init(canvas, body) {
// 获取模板字符串
let str = this.getSvg();
// 将 svg 添加到 canvas 中
this.addSvgToCanvas(canvas, str);
// 添加 svg 到 body,直观效果
this.addSvgToBody(body, str);
}
/**
* 拼接 svg template
* xmlns="http://www.w3.org/2000/svg" SVG专属命名空间
* <foreignObject>元素允许包含来自不同的 XML 命名空间的元素。在浏览器的上下文中,很可能是 XHTML / HTML。
* @return {string}
*/
getSvg() {
// 拼接样式
this.style = '.btn {';
let attrs = Object.keys(this.styleObj);
attrs.forEach(attr => {
this.style = this.style + attr + ':' + this.styleObj[attr] + ';';
});
this.style += '}';
// 返回最终 svg str
return `
<svg width="${ this.width }" height="${ this.height }" xmlns="http://www.w3.org/2000/svg">
<style>
${ this.style }
</style>
<foreignObject height="100%" width="100%">
<div class="btn" xmlns="http://www.w3.org/1999/xhtml" >${ this.innerHTML }</div>
</foreignObject>
</svg>`;
}
/**
* fabric 获取 canvas 对象
* @param body
* @return {*}
*/
getCanvas(body) {
let id = new Date().getTime() + '';
body.append(`<canvas id="${ id }" width="500" height="500" style="border:1px solid grey;"></canvas>`);
return new fabric.Canvas(id);
}
/**
* 添加 svg 到 canvas 中,使用 dataUrl 形式
* @param canvas
* @param str
*/
addSvgToCanvas(canvas, str) {
let dataUrl = 'data:image/svg+xml;base64,' + window.btoa(str);
new fabric.Image.fromURL(dataUrl, (img) => {
let objs = canvas.getObjects();
if (objs.length) {
// 存在则删除
canvas.remove(objs[0]);
}
canvas.add(img);
img.center();
img.sendBackwards();
});
}
/**
* 添加改变样式的 按钮
* @param canvas
* @param body
*/
addButtons(canvas, body) {
body.append(`<button class="button">Change Style</button>`);
$('.button').on('click', (e) => {
this.styleObj['background-color'] = Pieces.getColor();
this.styleObj['color'] = Pieces.getColor();
this.innerHTML = 'Button' + Math.round(Math.random() * 10);
// 重绘
this.init(canvas, body);
});
}
/**
* svg 添加到 body 中
* @param body
* @param str
*/
addSvgToBody(body, str) {
if (document.getElementsByTagName('svg').length) {
// 存在说明为更新,删除旧样式
document.getElementsByTagName('svg')[0].remove();
}
body.append(str);
}
}
效果:



浙公网安备 33010602011771号