วิธีรักษาอัตราส่วนภาพของรูปภาพภายใน SVG โดยไม่มีอัตราส่วนภาพ

ฉันมี SVG ทำงานอย่างถูกต้องเป็นเส้นทางการตัดที่ปิดบังรูปภาพ รูปร่าง SVG มี PreservAspectRatio="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="/th#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="/th#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 width="1370" height="260" 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 -->

เอสซีเอสเอส:

* {
  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 ที่นี่

หมายเหตุ: ขณะนี้ยังไม่สามารถใช้งานได้ใน Firefox หรือ IE11 ฉันขอขอบคุณสำหรับความช่วยเหลือในการทำให้ทั้งหมดนี้ทำงานได้บนเบราว์เซอร์เหล่านั้นเช่นกัน

ขอบคุณ


person Chris_Heu    schedule 16.11.2017    source แหล่งที่มา


คำตอบ (2)


เกี่ยวกับอัตราส่วนภาพ

คุณสามารถตั้งค่า svg เป็นภาพพื้นหลังของ div ได้ และจัดสไตล์ด้วย css; background-size: cover; และ background-position: center bottom; อาจจะช่วยได้

นี่คือคำตอบของคำถาม "เหตุใดจึงไม่ทำงานใน MS-Edge"

  • กำหนด clipPath ของคุณในองค์ประกอบ <defs>
  • องค์ประกอบ defs ควรเป็นลูกโดยตรงของหนึ่งในบรรพบุรุษขององค์ประกอบอ้างอิง ซึ่งไม่ใช่กรณีในตัวอย่างของคุณ การวางองค์ประกอบ defs เป็นลูกขององค์ประกอบ <svg> จะใช้งานได้เสมอ ที่มา: https://www.w3.org/TR/SVG/struct.html#DefsElement
  • กฎแห่งชีวิต: ทำให้เรียบง่ายเมื่อทำได้ นั่นหมายถึงไม่ใช้การอ้างอิงที่ไม่จำเป็น เพียงแสดงเส้นทางการตัดภายในองค์ประกอบ <clipPath> องค์ประกอบ <defs> กลายเป็นแบบนี้สำหรับฉันและเป็นลูกขององค์ประกอบ <svg>

<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>

person Rob Monhemius    schedule 16.11.2017

แทนที่จะใช้แท็ก คุณสามารถใช้คุณสมบัติมาสก์ใน 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;
}

person Herosimo Sribiko    schedule 04.08.2020