需求:
用户上传svg素材,前端展示素材图片,并可编辑颜色(取svg中的颜色并改变色值);
解决方案:
- 通过blob获取svg图片的文件字符串,存储原始字符串
- 通过match获取svg字符串中的16进制色值,通过colorList对象存贮
- 通过replace函数将变化颜色后的colorList遍例替换svg字符串,生成新的svg字符串
- 将新的svg字符串通过shadowDom插入到网页中
代码实现
let colorList = {}
let svgData = ''
// 获取svg字符串,查询色值列表
axios.get(img.imgUrl, {
contentType: 'blob'
}).then((data) => {
svgData = data.data
let colors = data.data.match(/#(?:[0-9a-fA-F]{6})/g) || []
colors.length > 0 && colors.map(color => {
colorList[color]=color
})
})
/**
* 获取变色渲染后svg
* @param svgData svg初始数据
*/
function getColorSvg(svgData){
if (!svgData) return
// 插入svg的容器
let svgBody = document.getElementById(id)
// 获取shadowDom根节点
const shadowRoot = svgBody.shadowRoot || svgBody.attachShadow({mode: 'open'});
if (!svgBody) return
for(let key in props.colorList){
if(key !== props.colorList[key]){
let reg = new RegExp(`${key}`, 'g')
svgData = svgData.replace(reg, props.colorList[key])
}
}
let parser = new DOMParser();
let doc = parser.parseFromString(svgData, "image/svg+xml");
let svgDom = doc.getElementsByTagName('svg')[0]
shadowRoot.innerHTML = ''
shadowRoot.appendChild(svgDom)
}
为什么使用shadowDom
形成css沙箱,不会因为插入的svg字符串影响到已有样式和重复插入的图片