如何在没有纵横比的情况下在 SVG 中保持图像的纵横比

Posted

技术标签:

【中文标题】如何在没有纵横比的情况下在 SVG 中保持图像的纵横比【英文标题】:How to maintain an image's aspect ratio inside an SVG without an aspect ratio 【发布时间】:2018-04-29 09:53:58 【问题描述】:

我有一个 SVG 可以正常用作遮蔽图像的剪切路径。 SVG 形状具有 preserveAspectRatio="none" 并且表现得如我所愿(全宽但保持静态高度)。

问题是我正在剪辑的图像与 SVG 一起被拉伸和挤压,而我希望它的行为与具有 background-size:cover; 的背景图像相同。 (始终填充 SVG,必要时进行裁剪,但保持纵横比)。

是否可以通过跨浏览器兼容性(最新的 Chrome、Firefox、Safari 和 Internat Explorer)做到这一点?

html

<div class="outer-wrapper">
  <div class="svg-wrapper">
    <!-- hidden SVG -->
    <svg class="shadow-svg">
      <!-- create drop shadow -->
      <filter id="drop-shadow">
        <feGaussianBlur in="SourceAlpha" stdDeviation="5"/>
        <feOffset dx="0" dy="0" result="offsetblur"/>
        <feFlood flood-color="rgb(0,0,0)" flood-opacity="0.75"/>
        <feComposite in2="offsetblur" operator="in"/>
        <feMerge>
          <feMergeNode/>
          <feMergeNode in="SourceGraphic"/>
        </feMerge>
      </filter>
      <!-- create shape-->
      <symbol id="shadow" viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
        <defs>
          <polygon id="clipShape" points="0 0 0 260 20 260 20 210 1350 210 1350 260 1370 260 1370 0 0 0" style="filter:url(#dropshadow)"/>
        </defs>
      </symbol>
      <!-- set shape as clipping path -->
      <clipPath id="clipPath">
        <use xlink:href="#clipShape" />
      </clipPath>
    </svg>
    <!-- visible SVG -->
    <svg class="shape-svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1370 260" enable-background="new 0 0 1370 260" xml:space="preserve" preserveAspectRatio="none">
      <!-- add drop shadow -->
      <use xlink:href="#shadow" />
      <!-- add clipping path shape -->
      <g transform="matrix(1 0 0 1 0 0)" clip-path="url(#clipPath)" >
        <!-- add image inside clipping path shape -->
        <image   xlink:href="https://www.unsplash.it/1370/260" transform="matrix(1 0 0 1 0 0)"></image>
      </g>
    </svg>
  </div><!-- .svg-wrapper -->
  <!-- text block -->
  <div class="header-text">
    <h2>Test Header Placeholder</h2>
    <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Velit exercitationem quibusdam sed natus blanditiis quia assumenda, magni tenetur veritatis itaque iure explicabo veniam maiores magnam architecto et corporis possimus.</p>    
  </div>
</div><!-- .outer-wrapper -->

SCSS:

* 
  margin: 0;
  padding: 0;


body 
  height: 100vh;
  background: repeating-linear-gradient(-45deg, palegreen, palegreen 3px, lightgreen 3px, lightgreen 40px);


.outer-wrapper 
  display: block;
  width: 100%;
  margin: 0 auto;


.svg-wrapper 
  width: 96%;
  height: 150px;
  margin: 0 auto;


.shadow-svg 
  width: 0;
  height: 0;
  position: absolute;


.shape-svg 
  width: 100%;
  height: 150px;
  filter: url(#drop-shadow);


.header-text 
  width: 90%;
  margin: -20px auto 0;
  font-family: monaco, courier;

CodePen Here

注意:它目前不适用于 Firefox 或 IE11。如果能帮助我在这些浏览器上运行所有这些,我将不胜感激。

谢谢。

【问题讨论】:

【参考方案1】:

您可以在 CSS 中使用掩码属性,而不是使用标签。它的作用类似于背景属性。

我试过这个并解决了这个问题。 https://clipping-masking.webflow.io/

.masked 
  mask-image: url(domain.com/image.sv ), none;
  mask-size: contain;
  mask-repeat: no-repeat;
  mask-position: center;

【讨论】:

【参考方案2】:

关于纵横比

您可以将 svg 设置为 div 的背景图像。并用 css 设置样式; background-size: cover;background-position: center bottom; 可能会成功。

这是对“为什么它在 MS-Edge 中不起作用?”问题的答案。

&lt;defs&gt; 元素中定义您的clipPath。 defs 元素应该是引用元素的祖先之一的直接子元素,但在您的示例中并非如此。将 defs 元素作为 &lt;svg&gt; 元素的子元素始终有效。来源:https://www.w3.org/TR/SVG/struct.html#DefsElement 生活准则:尽可能保持简单。这意味着不使用不必要的引用。只需在 &lt;clipPath&gt; 元素中显示剪切路径。 &lt;defs&gt; 元素对我来说最终看起来像这样,并且是 &lt;svg&gt; 元素的子元素。

<defs>
  <!-- set shape as clipping path -->
  <clipPath id="clipPath">
    <polygon points="0 0 0 260 20 260 20 210 1350 210 1350 260 1370 260 1370 0 0 0"/>
  </clipPath>
</defs>

【讨论】:

以上是关于如何在没有纵横比的情况下在 SVG 中保持图像的纵横比的主要内容,如果未能解决你的问题,请参考以下文章

如何保持并排图像的纵横比,保持图像高度相同并在图像之间固定填充?

如何在此应用程序中保持图像视图的纵横比? 【Android、ImageView、长宽比、ScrollView】

UIViewContentModeScaleAspectFill 不保持图像的纵横比

Java:保持JPanel背景图像的纵横比

保持 UIbuttons 背景图像的纵横比

css 保持图像的纵横比