SVG分组路径元素的transform-origin属性未生效问题
解决SVG中
<use>调用<defs>内分组图形时transform-origin不生效的问题 问题描述
我希望在<defs>区段中定义分组图形,通过<use>标签调用并将transform-origin设置为组的中心,但实际效果是组的左上角处于背景中心位置,而非预期的组中心与背景中心重合。
原测试代码如下:
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200"> <defs> <g id="triangle"> <path fill="green" d="m 24 0 l 24 41.569 l -48 0 z" /> <circle cx="24" cy="24" r="1" fill="red" /> <rect width="48" height="41.569" fill="purple" fill-opacity="20%" /> </g> </defs> <rect width="100" height="100" /> <rect fill="gray" x="100" width="100" height="100" /> <rect width="100" height="100" /> <rect fill="gray" y="100" width="100" height="100" /> <rect width="100" height="100" x="100" y="100" /> <use href="#triangle" transform-origin="50% 50%" transform="translate(100 100)" /> </svg>
问题根源
<use>元素的transform-origin是基于自身**边界框(bounding box)**计算的:
- 默认情况下,
<use>的边界框从坐标(0,0)开始,对应你定义的<g>的左上角。 - 你的
<g id="triangle">内部图形的坐标范围是(0,0)到(48,41.569),组的实际中心在(24, ~20.78),但transform="translate(100 100)"只是把<use>的(0,0)点移到了背景中心(100,100),所以组的左上角会落在该位置,而非中心。
解决方案
方案1:调整分组图形坐标,让组中心对齐原点
将<g>内所有图形的坐标改为以原点(0,0)为中心,这样<use>的transform-origin="50% 50%"就对应组的中心,直接平移即可实现居中:
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200"> <defs> <g id="triangle"> <!-- 图形坐标以(0,0)为中心重新绘制 --> <path fill="green" d="m 0 -20.7845 l 24 41.569 l -48 0 z" /> <circle cx="0" cy="0" r="1" fill="red" /> <rect x="-24" y="-20.7845" width="48" height="41.569" fill="purple" fill-opacity="20%" /> </g> </defs> <rect width="100" height="100" /> <rect fill="gray" x="100" width="100" height="100" /> <rect width="100" height="100" /> <rect fill="gray" y="100" width="100" height="100" /> <rect width="100" height="100" x="100" y="100" /> <!-- 此时translate(100,100)会直接把组中心移到背景中心 --> <use href="#triangle" transform-origin="50% 50%" transform="translate(100 100)" /> </svg>
方案2:通过嵌套平移修正位置
如果不想修改原图形坐标,可以在transform中先将组的中心偏移到<use>的原点,再平移到目标位置:
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200"> <defs> <g id="triangle"> <path fill="green" d="m 24 0 l 24 41.569 l -48 0 z" /> <circle cx="24" cy="24" r="1" fill="red" /> <rect width="48" height="41.569" fill="purple" fill-opacity="20%" /> </g> </defs> <rect width="100" height="100" /> <rect fill="gray" x="100" width="100" height="100" /> <rect width="100" height="100" /> <rect fill="gray" y="100" width="100" height="100" /> <rect width="100" height="100" x="100" y="100" /> <!-- 先平移-24,-20.7845把组中心移到<use>原点,再平移到背景中心 --> <use href="#triangle" transform="translate(100 100) translate(-24 -20.7845)" /> </svg>
方案3:给分组添加viewBox并配合相对平移
给<g>添加viewBox定义其边界范围,然后用translate(-50% -50%)将组中心对齐到<use>的原点:
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200"> <defs> <!-- 用viewBox明确分组的边界范围 --> <g id="triangle" viewBox="0 0 48 41.569"> <path fill="green" d="m 24 0 l 24 41.569 l -48 0 z" /> <circle cx="24" cy="24" r="1" fill="red" /> <rect width="48" height="41.569" fill="purple" fill-opacity="20%" /> </g> </defs> <rect width="100" height="100" /> <rect fill="gray" x="100" width="100" height="100" /> <rect width="100" height="100" /> <rect fill="gray" y="100" width="100" height="100" /> <rect width="100" height="100" x="100" y="100" /> <!-- translate(-50% -50%)将viewBox中心对齐到<use>原点,再平移到背景中心 --> <use href="#triangle" transform="translate(100 100) translate(-50% -50%)" /> </svg>
内容的提问来源于stack exchange,提问作者Valanthor
相关产品推荐
相关产品推荐

