如何在变换SVG <g>组时保持渐变相对于屏幕固定?
解决SVG组变换时渐变固定于视口的问题
要让渐变完全固定在视口、不受<g>组变换影响,按以下步骤调整:
- 把渐变定义移到SVG的
<defs>标签里,别放在<g>组内部,确保它属于全局视口坐标系。 - 给渐变明确设置
gradientUnits="userSpaceOnUse",同时指定固定的渐变起止坐标(比如x1="0%" x2="100%" y1="0%" y2="0%"表示水平渐变,完全基于视口左右)。 - 不要在
<g>标签上设置fill="url(#myGradient)",而是把这个填充属性直接加到<g>内的每个图形元素(比如<rect>、<path>、<circle>)上。 - 正常给
<g>组添加缩放、旋转、平移等变换即可。
原理是:当渐变用userSpaceOnUse且定义在全局defs中,它的坐标空间是SVG的视口,和<g>组的变换无关。把fill属性移到子元素后,图形元素会跟着<g>变换,但填充的渐变会始终以视口为基准,不会随图形旋转或移动。
举个示例代码:
<svg width="400" height="400"> <defs> <!-- 全局定义的渐变,基于视口坐标系 --> <linearGradient id="myGradient" gradientUnits="userSpaceOnUse" x1="0%" x2="100%" y1="0%" y2="0%"> <stop offset="0%" stop-color="#ff0000"/> <stop offset="100%" stop-color="#0000ff"/> </linearGradient> </defs> <!-- 带变换的组,内部元素单独用渐变填充 --> <g transform="rotate(90) translate(0, -400)"> <rect x="50" y="50" width="300" height="300" fill="url(#myGradient)"/> <circle cx="200" cy="200" r="100" fill="url(#myGradient)"/> </g> </svg>
这个示例里,<g>组被旋转90度并平移,但渐变始终是视口从左到右的红到蓝,不会跟着图形转到上下方向。
如果一定要在<g>上设置fill,那需要给渐变添加反向变换来抵消<g>的变换,但这种方式需要同步更新渐变的gradientTransform,不如上面的方法省心。比如<g>用transform="rotate(90)",就给渐变加gradientTransform="rotate(-90)",但如果<g>的变换动态变化,你也得跟着改渐变的transform,适合静态场景。
内容的提问来源于stack exchange,提问作者Franck Freiburger
相关产品推荐
相关产品推荐

