使用Batik转换SVG为PNG时含transform-origin的路径丢失求助
问题:Batik转换SVG到PNG时,含transform-origin的路径消失
我在程序里用Batik库把SVG字符串转成PNG,碰到个问题:带transform-origin样式的路径没出现在生成的PNG里。换了其他库试,结果一样。有人遇到过类似情况吗?我猜是Batik不支持这个CSS样式,直接把整个元素忽略了,但我需要转换任意SVG,求建议。
- 原始SVG:包含完整的左右靠背元素
- 转换后PNG:右侧靠背缺失
相关SVG代码(缺失路径已标注)
<svg xmlns="http://www.w3.org/2000/svg" viewBox="155.26 80.62 734.44 678.46"> <path stroke="#000" stroke-width="18.66" d="M214.59 139.95h615.78l-18.66 559.8z" style="fill:#E4E6EF"/> <a> <svg xmlns="http://www.w3.org/2000/svg" width="167.94" height="93.3" x="391.86" y="186.6" class="w-100 h-100" preserveAspectRatio="none" viewBox="0 16.183 952.567 595.818"> <path d="M0 15.067h952.567v383.906H0z" style="stroke:rgb(0, 0, 0);fill:rgb(138, 157, 185)"/> <rect width="376.883" height="96.74" x="293.021" y="55.082" rx="30" ry="30" style="stroke:rgb(0, 0, 0)"/> <rect width="146.118" height="137.048" x="415.961" y="431.964" rx="40" ry="40" style="stroke:rgb(0, 0, 0);stroke-linecap:round;stroke-width:11px;stroke-miterlimit:4.83;stroke-dashoffset:1px;paint-order:fill"/> <path d="M378.675 432.972h16.123v77.594h-16.123v-77.594Zm1.008 51.393h30.231v26.2h-30.231v-26.2Z" style="stroke:rgb(0, 0, 0)"/> <path d="M565.605 511.069v-77.594h16.123v77.594h-16.123Zm1.008-51.393v-26.2h30.231v26.2h-30.231Z" style="stroke:rgb(0, 0, 0);transform-origin:581.225px 472.272px" transform="rotate(180 0 0)"/> <path d="M395.806 544.828h185.418v31.239H395.806z" style="stroke:rgb(0, 0, 0);fill:rgb(59, 59, 59)"/> <path fill="none" d="M0 0h167.94v93.3H0z" class="h-100 w-100"/> </svg> <path fill="orange" fill-opacity=".25" stroke="orange" stroke-dasharray="11, 4" stroke-width="3" d="M391.86 186.6H559.8v93.3H391.86z"/> </a> <a> <svg xmlns="http://www.w3.org/2000/svg" width="155.98" height="111.96" x="615.78" y="298.56" class="w-100 h-100" preserveAspectRatio="none" viewBox="0 16.183 952.567 595.818"> <path d="M0 15.067h952.567v383.906H0z" style="stroke:rgb(0, 0, 0);fill:rgb(138, 157, 185)"/> <rect width="376.883" height="96.74" x="293.021" y="55.082" rx="30" ry="30" style="stroke:rgb(0, 0, 0)"/> <rect width="146.118" height="137.048" x="415.961" y="431.964" rx="40" ry="40" style="stroke:rgb(0, 0, 0);stroke-linecap:round;stroke-width:11px;stroke-miterlimit:4.83;stroke-dashoffset:1px;paint-order:fill"/> <path d="M378.675 432.972h16.123v77.594h-16.123v-77.594Zm1.008 51.393h30.231v26.2h-30.231v-26.2Z" style="stroke:rgb(0, 0, 0)"/> <!-- 缺失部分 --> <path d="M565.605 511.069v-77.594h16.123v77.594h-16.123Zm1.008-51.393v-26.2h30.231v26.2h-30.231Z" style="stroke:rgb(0, 0, 0);transform-origin:581.225px 472.272px" transform="rotate(180 0 0)"/> <path d="M395.806 544.828h185.418v31.239H395.806z" style="stroke:rgb(0, 0, 0);fill:rgb(59, 59, 59)"/> <path fill="none" d="M0 0h155.98v111.96H0z" class="h-100 w-100"/> </svg> </a> </svg>
解决方案
问题根源:Batik的CSS解析器对
transform-origin属性支持不完善,当该样式和transform属性结合时,会导致元素无法被正确渲染,甚至被忽略。快速修复:把
transform-origin的原点参数直接合并到transform的rotate指令中,移除CSS里的transform-origin样式。修改前的缺失路径代码:
<path d="M565.605 511.069v-77.594h16.123v77.594h-16.123Zm1.008-51.393v-26.2h30.231v26.2h-30.231Z" style="stroke:rgb(0, 0, 0);transform-origin:581.225px 472.272px" transform="rotate(180 0 0)"/>修改后:
<path d="M565.605 511.069v-77.594h16.123v77.594h-16.123Zm1.008-51.393v-26.2h30.231v26.2h-30.231Z" style="stroke:rgb(0, 0, 0)" transform="rotate(180 581.225 472.272)"/>批量处理方案:如果需要转换任意SVG,可以在交给Batik前做预处理:
- 用SVG DOM解析工具遍历所有元素
- 检查元素的
style属性中是否包含transform-origin - 将
transform-origin的坐标提取出来,合并到transform属性的旋转、缩放等变换指令中 - 移除
style中的transform-origin条目
内容的提问来源于stack exchange,提问作者Roman Pejs
相关产品推荐
相关产品推荐

