【问题标题】:Equivalent of "background-size: fill" for SVG <image> element等效于 SVG <image> 元素的“背景尺寸:填充”
【发布时间】:2017-11-20 19:39:36
【问题描述】:

我有一个 SVG 图形,其宽度是视口的百分比,其高度是固定的。在图形内部,我有一个 SVG image element,我希望始终填充其直接容器而不会扭曲,这与使用 CSS background-size: fill 实现的效果非常相似。

如何使用我的 SVG 来实现这一点?

这是问题的最小设置 (and a codepen):

<svg width=100% height=300>
  <rect width=100% height=300 stroke="blue" stroke-width=30 fill="transparent" />
  <image xlink:href="//unsplash.it/500/300" width=100% height=100% />
</svg>

在上面的 sn-p 中,无论视口宽度如何,我都需要图像填充整个容器而不失真(在本例中,容器是根 SVG)。

我无法切换到常规 HTML,因为我正在处理的图形将 SVG 剪贴蒙版应用于 image 元素。

我发现了这个问题,这似乎与我要问的问题很接近,但我认为不能回答我的问题:

How can I make my embedded svg image stetch to fill a container?

为了避免the XY problem,这里是the actual SVG graphic I'm working on。而我想要达到的(固定高度,可变宽度)结果:

【问题讨论】:

    标签: html svg


    【解决方案1】:

    Svg 图片缩放

    如果您向 svg 添加视图框,则 svg 知道如何缩放。
    现在添加与 svg 相同的 viewBox 比例,这样 svg 将始终与图像具有相同的比例。
    您始终可以将图像缩放到 viewBox 内部。
    然后它将始终随 svg 缩放。

    svg {
      border: 2px solid black;
    }
    <svg width="100%" height="100%" viewBox="0 0 500 300">
      <image width="500" height="300" xlink:href="//unsplash.it/500/300"/>
    </svg>

    【讨论】:

    • 这很好,但我需要能够限制 SVG 的高度,这意味着 SVG 将具有可变的纵横比,因此我无法将其编码到视图框中。
    【解决方案2】:

    要保持图片高度不变,设置视口高度和preserveAspectRatio = "none"的固定值

    <svg width="100%" height="300" viewBox="0 0 500 300" preserveAspectRatio = "none">
      <image width="500" height="300" xlink:href="//unsplash.it/500/300"/>
    </svg>

    UPD

    图片比例不变,使用preserveAspectRatio="xMinYMin slice"时高度保持不变

    <svg width="100%" height="300" viewBox="0 0 500 300" preserveAspectRatio="xMinYMin slice">
    
      <image width="100%" height="300" xlink:href="//unsplash.it/500/300" />
    </svg>

    UPD2

    我看了your codepen 喜欢这个主意。我已经在你的允许下完成了。修改了一些参数

    <svg width="100%" height="400" preserveAspectRatio="xMinYMin slice">
      <defs>
        <mask id="clipping">
          <rect width="100%" height="400" fill="white"/>
          <ellipse cx="50%" cy="120%" rx="75%" ry="37%"/>
        </mask>
        <linearGradient id="Gradient1" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stop-color="white"/>
          <stop offset="100%" stop-color="blue"/>
        </linearGradient>
      </defs>
    
      <rect   width="100%" height="400" fill="orange" mask="url(#clipping)" transform="translate(-20 12) rotate(-2.5)" />
      <image xlink:href="https://unsplash.it/1000/500" width="100%" height="400" mask="url(#clipping)" transform="translate(0 -10)" />
      <rect  width="100%" height="400" fill="url(#Gradient1)" mask="url(#clipping)" transform="translate(0 -10)" opacity="0.25" /> 
      
      </svg>

    【讨论】:

    • 这个也很有意思,就是图片失真了。
    • 当然可以,要么保留纵横比,要么扭曲图像。选择你想要的。
    • @NathanArthur 添加了一个选项。图片不失真,高度固定
    • @RobertLongson 也许我做错了整个事情(请参阅我的问题的结尾,了解我想要实现的目标),但我具体询问@987654327 的行为是否@ 可以在 SVG 中实现。含义——图像没有失真,其容器也没有保持其纵横比。
    • @Alexandr_T 谢谢!我将不得不阅读preserveAspectRatio 属性。它看起来超级有用。
    【解决方案3】:

    我最终使用了两个 SVG 和一个图像,该图像使用第一个 SVG 中定义的剪贴蒙版将其裁剪。我能够通过仅定义视图框而不是宽度和高度来使 SVG 缩放。我选择使用固定的纵横比,而不是像我最初计划的那样使用固定的高度、百分比宽度。

    body > * {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
    }
    
    img {
      clip-path: url(#clipper);
    }
    <svg viewBox="0 0 1000 500">
      <defs>
        <symbol id="arch" viewBox="0 0 1000 400">
          <path d="M0 0 H 1000 V 400 Q 500 300, 0 400" />
        </symbol>
        
        <clipPath id="clipper" clipPathUnits="objectBoundingBox">
          <path d="M0 0 H 1 V 1 Q .5 .75, 0 1" />
        </clipPath>
        
        <linearGradient id="Gradient1" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stop-color="#87AFBF"/>
          <stop offset="100%" stop-color="#002855"/>
        </linearGradient>
      </defs>
      
      <use href="#arch" width="100%" y="-40" fill="#F9B000" transform="translate(-20 12) rotate(-2.5)" />
    </svg>
    
    <img src="//unsplash.it/1000/400" alt="">
    
    <svg viewBox="0 0 1000 500">
      <use href="#arch" y="-50" fill="url(#Gradient1)" opacity="0.75" />
    </svg>

    CodePen

    【讨论】:

    • 你的决定非常中肯,没有我的缺点(+)
    猜你喜欢
    • 2016-02-26
    • 2011-04-17
    • 2014-06-07
    • 1970-01-01
    • 2023-03-10
    相关资源
    最近更新 更多