当前位置: 首页 > Web前端 > vue.js

在VueJs中,动态更改svg的相关属性

时间:2023-03-31 22:09:55 vue.js

公司项目中有图标库管理的需求。一般需要动态改变页面上对应svg图标的大小和颜色(这里的颜色变化仅限于线性图标)。在网上搜索了相关资料,做了技术预研并准备了一个demo,记录在这里。如何将远程svg图标资源“下载”到本地主页我们可以使用XMLHttpRequest对象请求对应svg图标的远程资源链接地址,并监听XMLHttpRequest对象的load事件,将返回的资源转换为一个dom对象,字符串转换为xml。代码如下:constxhr=newXMLHttpRequest();xhr.open('GET','https://www.xx.com/img/xxx.svg',true);xhr.发送();/*监听xhr对象*/xhr.onreadystatechange=function(){if(xhr.readyState==4&&xhr.status==200){console.log(xhr.responseXML,'xhr.responseXML---------')}};xhr.addEventListener('load',()=>{constresXML=stringToXml(xhr.response);this.svgDom=resXML.documentElement.cloneNode(true);});到这里工具函数stringToXml就完成了代码如下://将字符串转换为dom对象;将字符串转换为xml函数stringToXml(xmlString){letxmlDoc;if(typeofxmlString=="string"){//FFif(document.implementation.createDocument){constparser=newDOMParser();xmlDoc=parser.parseFromString(xmlString,"文本/xml");}elseif(window.ActiveXObject){//eslint-disable-next-lineno-undefxmlDoc=newActiveXObject("Microsoft.XMLDOM");xml文档.as同步=假;xmlDoc.loadXML(xmlString);}}else{xmlDoc=xmlString;}returnxmlDoc;}这样就可以获取到远程svg资源对应的dom结构如何更改svgdom结构中的相关属性产品需求需要能够动态改变宽高,颜色值等.相应的svg图标。要实现这样的功能,有几个小点:将svgDom对象转化为vue的虚拟dom,代码如下:constoSerializer=newXMLSerializer();根据序列化对象提供的serializeToString方法将svgDom对象字符串化;利用svgDom对象提供的宽高属性值,结合正则表达式遍历svgDom字符串化后的字符串,替换宽高值。代码如下:letsXML=oSerializer.serializeToString(this.svgDom);sXML=sXML.replace(`width="${this.svgDom.width.baseVal.value}"`,'width="40"').replace(`height="${this.svgDom.height.baseVal.value}"`,'height="40"')根据sXML截取svg结构表示的字符串中对应的颜色值,结合is-color插件判断是否为真实颜色。如果是,则可以根据要替换的颜色值进行全局替换。代码如下:letcurColor=sXML.split('#')[1].substr(0,6)if(!isColor(`#${curColor}`)){curColor=sXML.split('#')[1].substr(0,3)}sXML=sXML.replace(newRegExp(`#${curColor}`,"gm"),'#90EE90')通过Vue实例并将其挂载到一个元素上,代码如下:constProfile=Vue.extend({template:""+sXML+'

'});//创建实例并将其挂载到元素上newProfile().$mount('#svgTemplate');处理前渲染:处理后渲染(将svg的宽高由20改为40,颜色值改为“#90EE90”):最终完整代码如下:testSvg(){constxhr=newXMLHttpRequest();xhr.open('GET','https://www.xx.com/img/xxx.svg',true);xhr.send();/*监听xhr对象*/xhr.onreadystatechange=function(){if(xhr.readyState==4&&xhr.status==200){console.log(xhr.responseXML,'xhr.responseXML---------')}};xhr.addEventListener('load',()=>{constresXML=stringToXml(xhr.responsese);this.svgDom=resXML.documentElement.cloneNode(true);/*将svgDom对象转换为vue的虚拟dom*/constoSerializer=newXMLSerializer();让sXML=oSerializer.serializeToString(this.svgDom);让curColor=sXML.split('#')[1].substr(0,6)if(!isColor(`#${curColor}`)){curColor=sXML.split('#')[1]。substr(0,3)}sXML=sXML.replace(`width="${this.svgDom.width.baseVal.value}"`,'width="40"').replace(`height="${this.svgDom.height.baseVal.value}"`,'height="40"').replace(newRegExp(`#${curColor}`,"gm"),'#90EE90')constProfile=Vue.extend({template:""+sXML+'
'});//创建一个实例并将其挂载到元素上newProfile().$mount('#svgTemplate');});},