将全尺寸图像的大小和比例与 SVG 视图框匹配

Posted

技术标签:

【中文标题】将全尺寸图像的大小和比例与 SVG 视图框匹配【英文标题】:Match size and scale of fullsize image to SVG viewbox 【发布时间】:2018-06-25 18:45:31 【问题描述】:

我有一份团队成员名单。每个成员元素都由一个在白色框内裁剪成圆形的图像组成。当您将鼠标悬停在框上时,图像将变为全尺寸。它的灵感来自this website:

我用 SVG 实现了同样的动画。但是,在上面的网站中,每张图片都是 300X350 - 与白色容器盒的大小相同。这创建了从蒙版图像到全尺寸图像的完美过渡 - 似乎没有任何东西跳跃或移动。 另一方面,我的图片有多种尺寸。结果,SVG 的可见部分要么放大要么缩小图像,当你将鼠标悬停时,整个图像似乎会跳跃

如何使全尺寸图像的比例和大小与 SVG 视图框中的大小相匹配,使其看起来不会移动?

JSFiddle:http://jsfiddle.net/mzechar/afnxkt2h/2/

html:

 <li>
            <a href="#">
              <article>
                <div>

                  <!-- The masked image -->
                  <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 100 100">
                        <defs>
                                <clipPath id="circle">
                                        <circle cx="50" cy="50" r="35"/>
                                </clipPath>
                        </defs>
                        <image   preserveAspectRatio="xMinYMin slice" xlink:href="team/finishedBW/CCK.jpg__.jpg" clip-path="url(#circle)"/>
                </svg>
                </div>

                <!-- The full revealed image -->
                <img class="img-full" src="team/finishedBW/CCK.jpg__.jpg" >

                <!-- The circle ring -->
                <svg viewBox="0 0 100 100" class="circle-ring">
        <circle cx="50" cy="50" r="35" stroke="white" stroke- fill="transparent" />
    </svg>

                <div class="bio">
                  <h2>Chun-Kang Chen</h2>
                  <h4>Article Subtitle</h4>
                </div>
              </article>
            </a>
          </li>
          <li>

CSS:

.team-listing
    position:relative;
    margin-top:40px;
    margin-right:auto;
    margin-left:auto;


.team-listing li
    display:inline-block;
    overflow: hidden;
    float:left;
    height: 340px;
    list-style-position:inside;
    margin: 1px 1px 1px 1px;
    background-color:#fff;


.team-listing ul
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    flex-direction: row;
    flex-flow: row wrap;
    flex-shrink: 1;
    flex-grow: 1;
    float: left;
    min-width: 0;
    max-width: 100%;
    position: relative;
    filter: drop-shadow(5px 5px 5px rgba(2,2,22,0.1));


a 
  display: inline-block;


article 
  position: relative;
  width: 300px;
  height: 350px;
  /* prevent scaled circle ring from triggering hover */
  overflow: hidden;



/* create the colour overlay */
article:after 
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: none;
  background: rgba(0, 255, 255, .2);
  z-index: 3;



/* place full image above SVG */
.img-full 
  position: absolute;
  top: 0;
  right:0;
  z-index: 2;
  /* hide the full image initially */
  display: none;


.circle-ring 
  position: absolute;
  top: 0;
  z-index: 3;
  /* initially hidden with opacity so it can be animated */
  opacity: 0;
  transform-origin: 50% 50%;
  transform: scale(1.8);
  transition: transform .3s ease, opacity .4s ease;


a:hover .img-full,
a:hover article:after 
  position:absolute;
  display: block;


a:hover .circle-ring 
  opacity: 1;
  transform: scale(1);


.bio 
  position: absolute;
  bottom: 0;
  padding: 1rem 2rem;
  color: #000;
  /* keep text above SVG, full image and overlay */
  z-index: 4;


a:hover .bio 
  color: #FFF;



/* general */
h2,
h4 
  margin: 0;
  font-family: sans-serif;


h4 
  font-weight: 300;

【问题讨论】:

当您可以将一个元素用于标准视图和悬停视图(如我们的灵感 360i.com)时,为什么要加载同一张图片两次? 我最初尝试过这样做,但我不知道如何在悬停时获得圆形轮廓(请参阅此处的原始代码:jsfiddle.net/mzechar/em5yh164 和此处发布:***.com/questions/50937186/…) 【参考方案1】:

对 SVG 内容有信心。无需在其间定义两个 &lt;svg&gt; 元素和 HTML &lt;img&gt;。只需将图像放置在&lt;svg&gt; 父级内的&lt;image&gt; 标记中,然后根据悬停状态设置/删除剪辑路径。

剪辑路径本身保留在单独但隐藏的&lt;svg&gt; 中,因此它可以重复用于多个图像。

如果图像尺寸和位置都不同,因此它们显示正确的剪辑内容,最好不要依赖preserveAspectRatio,而是绝对设置它们。 (在 &lt;svg&gt; 元素上设置 overflow:hidden 更多的是一种预防措施,因为规范已经改变了一点,无论这是否是默认值。)

a 
    display: inline-block;

article 
    position: relative;
    width: 300px;
    height: 350px;
    overflow: hidden;

article::after 
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    display: none;
    background: rgba(0, 255, 255, .2);
    z-index: 3;

.portrait 
    position: relative;
    width: 300px;
    height: 300px;
    overflow: hidden;

.portrait image 
    clip-path: url(#circle);

a:hover .portrait image 
    clip-path: none;

a:hover article:after 
  position: absolute;
  display: block;

.ring 
    fill: none;
    stroke: white;
    stroke-width: 1;
    opacity: 0;
    transform-origin: 50% 50%;
    transform: scale(1.8);
    transition: transform .3s ease, opacity .4s ease;

a:hover .ring 
    opacity: 1;
    transform: scale(1);

.bio 
    position: absolute;
    bottom: 0;
    padding: 1rem 2rem;
    color: #000;

h2 
    font-size: 1.5em;
    font-weight: bold;

h4 
    font-weight: 300;

h2, h4 
    margin: 0;
    font-family: sans-serif;
<svg  >
  <clipPath id="circle">
    <circle cx="150" cy="150" r="100"/>
  </clipPath>
</svg>
<a href="#">
  <article>
    <svg class="portrait" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
      <!-- no automatic sizing for SVG image, width and height must be set -->
      <image   x="-100" y="0"
             xlink:href="http://api.leafsnap.com/v1/team/images/columbia/Neeraj.jpg?h=300"/>
      <circle class="ring" cx="150" cy="150" r="100" />
    </svg>
    <div class="bio">
      <h2>Chun-Kang Chen</h2>
      <h4>Article Subtitle</h4>
    </div>
  </article>
</a>

【讨论】:

您对如何让图像也填充白色容器框有什么建议吗? &lt;svg&gt; 的宽度和高度设置为100%(如果&lt;article&gt; 是您的意思。)显然,您还必须调整&lt;image&gt; 的尺寸。两种选择:绝对定位和手动找到正确的纵横比,或者像你一样,将宽度/高度设置为 100% 和 preserveAspectRatio="... slice" 我愿意接受这个答案 - 但我不知道如何像在 OP 中那样添加背景颜色和背景图像(线性渐变) 我已经用article::after 重新添加了覆盖,它仍然像以前一样工作。你的问题在哪里有梯度? - 如果您想知道为什么看不到图像,那是一个安全问题。请参阅jsfiddle.net/0wa65etj,它可以工作。【参考方案2】:

剪裁你的图片,扔掉那些无用的标签,每张图片只使用一次。 希望这会有所帮助:

section.team 
  margin: auto;
  background: #fefefe;


.team-listing 
  position: relative;
  margin: 40px auto 0;
  display: flex;
  filter: drop-shadow(5px 5px 5px rgba(2, 2, 22, 0.1));


.team-listing li 
  overflow: hidden;
  height: 350px;
  list-style: none;
  margin: 1px;
  background-color: #fff;


article 
  position: relative;
  top: 0;
  width: 300px;
  height: 300px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;


.img-full 
  -webkit-clip-path: circle(30% at 50% 50%);
  clip-path: circle(30% at 50% 50%);
  width: 500px;


a:hover .img-full 
  -webkit-clip-path: none;
  clip-path: none;
  filter: sepia(100%);


.circle-ring 
  position: absolute;
  top: 0;
  z-index: 3;
  opacity: 0;
  transform-origin: 50% 50%;
  transform: scale(1.8);
  transition: transform 0.3s ease, opacity 0.4s ease;


a:hover .circle-ring 
  opacity: 1;
  transform: scale(1);


.bio 
  position: absolute;
  bottom: 0;
  margin: 2rem;
  color: #000;


a:hover .bio > h2 
  color: #fff;


h2,
h4 
  margin: 0;
  font-family: sans-serif;


h4 
  font-weight: 300;
<section class="content-wrapper team">
  <ul class="team-listing">
    <li>
      <a href="#">
        <article>
          <img class="img-full" src="https://i.imgur.com/6eRLJ4I.jpg" >
          <svg viewBox="0 0 100 100" class="circle-ring">
              <circle cx="50" cy="50" r="35" stroke="white" stroke- fill="transparent" />
          </svg>
        </article>
        <div class="bio">
          <h2>Article Title</h2>
          <h4>Article Subtitle</h4>
        </div>
      </a>
    </li>
    <li>
      <a href="#">
        <article>
          <img class="img-full" src="https://i.imgur.com/6eRLJ4I.jpg" >
          <svg viewBox="0 0 100 100" class="circle-ring">
                  <circle cx="50" cy="50" r="35" stroke="white" stroke- fill="transparent" />
              </svg>
        </article>
        <div class="bio">
          <h2>Article Title</h2>
          <h4>Article Subtitle</h4>
        </div>
      </a>
    </li>
  </ul>
</section>

【讨论】:

以上是关于将全尺寸图像的大小和比例与 SVG 视图框匹配的主要内容,如果未能解决你的问题,请参考以下文章

调整图像大小以使大小与指定的纵横比匹配[重复]

相机表面视图图像看起来拉伸

以统一大小调整多个图像的大小并保持比例

网页设计——颜色随数值大小渐变!

如何调整图片kb大小

允许滚动视图的高度根据图像大小而改变