You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何变换SVG路径而不使其应用的渐变/滤镜随之变换?

如何让SVG图形旋转但渐变保持全局坐标不变?

初始代码与效果

以下是基础SVG代码,会渲染一个居中的正方形,带有垂直双色渐变(上半红色,下半绿色):

<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="gradient1" x1="50%" y1="0" x2="50%" y2="100%" gradientUnits="userSpaceOnUse">
      <stop offset="0%" style="stop-color:rgb(255,0,0); stop-opacity:1" />
      <stop offset="50%" style="stop-color:rgb(255,0,0); stop-opacity:1" />
      <stop offset="50%" style="stop-color:rgb(0,255,0); stop-opacity:1" />
    </linearGradient>
  </defs>

  <rect x="25" y="25" width="50" height="50" fill="url(#gradient1)" />
</svg>

需求

想要把正方形旋转成菱形,但保持渐变的垂直方向不变(渐变基于全局用户空间坐标,不随图形旋转),最终呈现上红下绿的菱形效果。

错误尝试及问题

直接给矩形添加transform="rotate(45, 50, 50)"时,图形和渐变会一起旋转,导致渐变跟着菱形倾斜,不符合需求。修改后的代码如下:

<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="gradient1" x1="50%" y1="0" x2="50%" y2="100%" gradientUnits="userSpaceOnUse">
      <stop offset="0%" style="stop-color:rgb(255,0,0); stop-opacity:1" />
      <stop offset="50%" style="stop-color:rgb(255,0,0); stop-opacity:1" />
      <stop offset="50%" style="stop-color:rgb(0,255,0); stop-opacity:1" />
    </linearGradient>
  </defs>

  <rect x="25" y="25" width="50" height="50" fill="url(#gradient1)" transform="rotate(45, 50, 50)" />
</svg>

解决方案

有两种可行的方法实现需求:

方法1:用裁剪路径分离变换与填充

先定义旋转后的矩形作为裁剪区域,再用渐变填充整个SVG画布,通过裁剪只显示旋转后的图形区域,这样渐变始终基于全局坐标:

<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="gradient1" x1="50%" y1="0" x2="50%" y2="100%" gradientUnits="userSpaceOnUse">
      <stop offset="0%" style="stop-color:rgb(255,0,0); stop-opacity:1" />
      <stop offset="50%" style="stop-color:rgb(255,0,0); stop-opacity:1" />
      <stop offset="50%" style="stop-color:rgb(0,255,0); stop-opacity:1" />
    </linearGradient>
    <!-- 定义旋转后的矩形作为裁剪路径 -->
    <clipPath id="rotatedRectClip">
      <rect x="25" y="25" width="50" height="50" transform="rotate(45, 50, 50)" />
    </clipPath>
  </defs>

  <!-- 用渐变填充整个画布,通过裁剪只保留旋转后的区域 -->
  <rect x="0" y="0" width="100" height="100" fill="url(#gradient1)" clip-path="url(#rotatedRectClip)" />
</svg>

方法2:给渐变添加反向变换

给渐变应用图形变换的逆变换,抵消图形旋转对渐变的影响。因为矩形旋转了45度,所以给渐变设置gradientTransform="rotate(-45, 50, 50)",让渐变反向旋转45度,最终呈现全局垂直的效果:

<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="gradient1" x1="50%" y1="0" x2="50%" y2="100%" gradientUnits="userSpaceOnUse"
                    gradientTransform="rotate(-45, 50, 50)">
      <stop offset="0%" style="stop-color:rgb(255,0,0); stop-opacity:1" />
      <stop offset="50%" style="stop-color:rgb(255,0,0); stop-opacity:1" />
      <stop offset="50%" style="stop-color:rgb(0,255,0); stop-opacity:1" />
    </linearGradient>
  </defs>

  <rect x="25" y="25" width="50" height="50" fill="url(#gradient1)" transform="rotate(45, 50, 50)" />
</svg>

方法对比

  • 方法1无需计算逆变换,逻辑直观,适合复杂变换场景;
  • 方法2代码更紧凑,适合简单变换场景,但需要准确匹配逆变换参数。

内容的提问来源于stack exchange,提问作者jemmons

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 16:15:57