为何在控制台执行a.fill = 'black'无法改变SVG圆形颜色?
为什么修改SVG圆形实例的
fill属性无法生效? 我出于兴趣制作SVG圆形,通过构造函数makeCircle生成实例。希望在控制台修改已创建圆形的属性,但执行a.fill = "black";无法改变圆形对象的参数,请问为何此方法无法生效?
代码示例:
const container = document.body let svgContainer = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svgContainer.style.width = "100vw" svgContainer.style.height = "100vw" svgContainer.setAttribute("viewBox", "0 0 500 750"); container.appendChild(svgContainer); function makeCircle(cx, cy, r, fill, stroke, id) { this.cx = cx; this.cy = cy; this.r = r; this.fill = fill; this.stroke = stroke; this.id = id; let newCircle = document.createElementNS("http://www.w3.org/2000/svg", "circle"); newCircle.setAttribute("cx", cx); newCircle.setAttribute("cy", cy); newCircle.setAttribute("r", r); newCircle.setAttributeNS(null, 'fill', fill); newCircle.setAttributeNS(null, 'stroke', stroke); svgContainer.appendChild(newCircle); } let a = new makeCircle(50, 300, 20, '#493fea', 'green');
原因分析
你的makeCircle构造函数中,实例的this.fill等属性与页面上的SVG圆形DOM元素是完全独立的两个实体:
- 构造函数里给实例(
this)赋值的fill只是普通的JavaScript对象属性,和页面上的SVG元素没有任何绑定关联。 - 执行
a.fill = "black"时,仅修改了a对象的fill属性值,并没有同步更新SVG DOM元素的fill属性,因此页面上的圆形不会产生视觉变化。
解决方案
方案1:将DOM元素挂载到实例,直接操作DOM
修改构造函数,把创建的SVG圆形DOM元素绑定到实例上,后续可通过实例直接操作DOM来更新属性:
function makeCircle(cx, cy, r, fill, stroke, id) { this.cx = cx; this.cy = cy; this.r = r; this.fill = fill; this.stroke = stroke; this.id = id; // 将DOM元素挂载到实例属性上 this.element = document.createElementNS("http://www.w3.org/2000/svg", "circle"); this.element.setAttribute("cx", cx); this.element.setAttribute("cy", cy); this.element.setAttribute("r", r); this.element.setAttributeNS(null, 'fill', fill); this.element.setAttributeNS(null, 'stroke', stroke); svgContainer.appendChild(this.element); } // 修改时直接操作DOM并同步实例属性 a.element.setAttributeNS(null, 'fill', 'black'); a.fill = 'black';
方案2:使用getter/setter实现自动同步
通过ES6的Object.defineProperty给实例的fill属性添加getter和setter,让实例属性与DOM元素属性自动绑定,修改实例属性时自动更新DOM:
function makeCircle(cx, cy, r, fill, stroke, id) { this.cx = cx; this.cy = cy; this.r = r; this.stroke = stroke; this.id = id; this.element = document.createElementNS("http://www.w3.org/2000/svg", "circle"); this.element.setAttribute("cx", cx); this.element.setAttribute("cy", cy); this.element.setAttribute("r", r); this.element.setAttributeNS(null, 'stroke', stroke); // 初始化fill属性 this.element.setAttributeNS(null, 'fill', fill); svgContainer.appendChild(this.element); // 为fill添加getter和setter Object.defineProperty(this, 'fill', { get() { return this.element.getAttributeNS(null, 'fill'); }, set(newValue) { this.element.setAttributeNS(null, 'fill', newValue); } }); } // 现在直接修改a.fill即可同步更新页面上的圆形 a.fill = "black";
方案3:添加专用更新方法
给实例添加专门的更新方法,统一处理实例属性与DOM元素的同步:
function makeCircle(cx, cy, r, fill, stroke, id) { this.cx = cx; this.cy = cy; this.r = r; this.fill = fill; this.stroke = stroke; this.id = id; this.element = document.createElementNS("http://www.w3.org/2000/svg", "circle"); this.element.setAttribute("cx", cx); this.element.setAttribute("cy", cy); this.element.setAttribute("r", r); this.element.setAttributeNS(null, 'fill', fill); this.element.setAttributeNS(null, 'stroke', stroke); svgContainer.appendChild(this.element); // 添加更新fill的方法 this.updateFill = function(newFill) { this.fill = newFill; this.element.setAttributeNS(null, 'fill', newFill); } } // 调用方法更新属性 a.updateFill("black");
内容的提问来源于stack exchange,提问作者The Adventuring Flylinus
相关产品推荐
相关产品推荐

