如何用JavaScript为SVG中的rect标签填充图片?
解决SVG矩形填充图片的问题
原代码的核心问题
- HTML按钮标签闭合错误:
<button>应该用</button>而非</a> - SVG矩形的
fill值格式错误:#00000是5位无效值,需改为#000或#000000 - Snap.svg使用方式错误:创建的pattern对象不能直接赋值给
style.fill,需先添加到SVG文档再通过url()引用 - 未等待SVG加载完成就操作:可能导致
contentDocument获取失败 - 矩形默认
visibility="hidden":不修改的话看不到填充效果
方案一:原生SVG实现(无需第三方库)
这种方法更轻量,无需依赖Snap.svg:
修正后的HTML
<button onclick="changeRect('rect252')">Input</button> <object type="image/svg+xml" id="main" class="edit-area" data="image.svg"></object>
JavaScript代码
// 监听SVG加载完成事件,避免提前操作 document.getElementById('main').addEventListener('load', () => { console.log('SVG加载完成'); }); function changeRect(id){ const obj = document.getElementById("main"); const svgDoc = obj.contentDocument; // 校验SVG是否加载完成 if(!svgDoc) { alert('SVG未加载完成,请稍后重试'); return; } const svgRect = svgDoc.getElementById(id); if(!svgRect) { alert('未找到指定ID的矩形'); return; } // 显示矩形 svgRect.setAttribute('visibility', 'visible'); // 创建pattern元素(SVG命名空间必须正确) const pattern = svgDoc.createElementNS('http://www.w3.org/2000/svg', 'pattern'); pattern.setAttribute('id', 'imgPattern'); pattern.setAttribute('patternUnits', 'userSpaceOnUse'); pattern.setAttribute('width', '50'); // 图案重复单元宽度,可按需调整 pattern.setAttribute('height', '50'); // 图案重复单元高度,可按需调整 // 创建image元素 const img = svgDoc.createElementNS('http://www.w3.org/2000/svg', 'image'); img.setAttribute('href', 'teste.svg'); // SVG内图片需用href而非src img.setAttribute('width', '50'); img.setAttribute('height', '50'); // 将pattern添加到SVG的defs(没有defs则创建) pattern.appendChild(img); let defs = svgDoc.querySelector('defs'); if(!defs) { defs = svgDoc.createElementNS('http://www.w3.org/2000/svg', 'defs'); svgDoc.querySelector('svg').insertBefore(defs, svgDoc.querySelector('svg').firstChild); } defs.appendChild(pattern); // 给矩形设置图片填充 svgRect.setAttribute('fill', 'url(#imgPattern)'); }
修正后的SVG(image.svg)
<svg xmlns="http://www.w3.org/2000/svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"> <rect style="fill:#000;" id="rect252" width="51.396542" height="31.275505" x="120.8588" y="92.630028" inkscape:label="Right" visibility="hidden"/> </svg>
方案二:Snap.svg修正版
如果一定要用Snap.svg,需调整pattern的添加方式:
JavaScript代码
document.getElementById('main').addEventListener('load', () => { console.log('SVG加载完成'); }); function changeRect(id){ const obj = document.getElementById("main"); const svgDoc = obj.contentDocument; if(!svgDoc) { alert('SVG未加载完成'); return; } const svgRect = svgDoc.getElementById(id); if(!svgRect) { alert('未找到指定矩形'); return; } svgRect.setAttribute('visibility', 'visible'); // 用Snap包装SVG根元素 const snapSvg = Snap(svgDoc.querySelector('svg')); // 创建并配置pattern const pattern = snapSvg.image('teste.svg', 0, 0, 50, 50).pattern(0, 0, 50, 50); // 确保defs存在并添加pattern snapSvg.select('defs') || snapSvg.append('<defs></defs>'); snapSvg.select('defs').append(pattern); // 给矩形设置填充 snapSvg.select('#' + id).attr('fill', pattern); }
关键注意事项
- 确保
teste.svg与当前页面、image.svg在同一域名下,避免跨域导致图片加载失败 - 必须等待
<object>内的SVG完全加载后再执行操作,否则contentDocument会返回null - SVG元素创建时必须使用官方命名空间(
http://www.w3.org/2000/svg),否则浏览器无法识别
内容的提问来源于stack exchange,提问作者arleite
相关产品推荐
相关产品推荐

