CSS reveal from corner animation

后端 未结 5 486
小蘑菇
小蘑菇 2020-12-13 14:34

I am trying to achieve an animation effect as follows:

When a banner is shown, the bottom right corner of the next banner should be visible. When you click on this c

相关标签:
5条回答
  • 2020-12-13 14:59

    This should work for any browser with transition support: https://jsfiddle.net/freer4/cqqxjjgu/1/

    Essentially, make a really big cover slide, with the same background color as your next slide, and pull it over your current slide. Then fade out to reveal the next slide.

    So a little adjustment on the html:

    <div class="banners">
      <div class="image active" style="background-color: black;">
        <div class="content">
          Slide 1
        </div>
        <div class="spanner"></div>
        <div class="corner" style="background-color: cyan;"></div>      
      </div>
    
      <div class="image" style="background-color: cyan;">
        <div class="content">
          Slide 2
        </div>
        <div class="spanner"></div>
        <div class="corner" style="background-color: magenta;"></div>
      </div>
    
      <div class="image" style="background-color: magenta;">
        <div class="content">
          Slide 3
        </div>
        <div class="spanner"></div>
        <div class="corner" style="background-color: black;"></div>
      </div>
    </div>
    

    Change the jQuery to select either the next slide or the first if there are no more:

    $(document).ready(function () {
        $('.corner').click(function() {
            var $parent = $(this).parent();
            $parent.removeClass("active");
            if ($parent.next().length){
                $parent.next().addClass("active");
            } else {
                $parent.prevAll().last().addClass("active");
            }
        });
    });
    

    And set up some intricate transitions you can adjust the timing of:

    .image {
        width: 100%;
        height: 100%;
        position: absolute;
        left: 0;
        top: 0;
        overflow:hidden;
        z-index:1;
        transition:z-index 2s step-end, 1s opacity 1s ease-in-out;
        text-align:center;
        opacity:0;
    }
    .image.active{
        opacity:1;
        z-index:2;
        transition:z-index 2s step-end, 0s opacity 0s;
    }
    
    .corner {
        width: 200%;
        height: 200%;
        position: absolute;
        top: -100%;
        left: -100%;
        clip-path: polygon(100% 0, 0 70%,  0 100%, 100% 100%, 100% 0, 100% 0);
        z-index:3;
        margin-left:150%;
        margin-top:150%;
        transition:2s top ease-in-out, 2s left ease-in-out, 0s margin 2s;
    }
    .image.active .corner{
      top:0;
      left:0;
      margin-top:0;
      margin-left:0;
      transition:0s top ease-in-out 1s, 0s left ease-in-out 1s, 2s margin ease-in-out 1s;
    }
    

    Aside: This example is completely flexible (doesn't care about size):

    .banners {
        width: 100%;
        height: 100%;
    }
    

    Or with images: https://jsfiddle.net/freer4/ens7caaL/

    0 讨论(0)
  • 2020-12-13 14:59

    This will work everywhere, even in IE/Edge. It's based on CSS transitions and replacing CSS classes via JavaScript.

    I'm using rotated rectangle to crop images. Demo of main principle (contains a lot of hardcoded, previously calculated values):

    *,
    *:before,
    *:after {
      box-sizing: border-box;
    }
    
    body {
      margin: 0;
      height: 100vh;  
      display: flex;
      align-items: center;
      justify-content: center;
    }
    
    div {
      width: 300px;
      height: 200px;
      border: 1px solid red;
      position: relative;
    }
    
    div:after {
      content: "";
      position: absolute;
      left: -86.6px;
      top: 50px;
      width: 359.8px;
      height: 240px;
      transform-origin: 0 0;
      transform: rotate(-30deg);
      border: 1px solid blue;
    }
    <div></div>

    Main demo (there are a lot of hardcoded values). For better understanding how it works you can add border to .slide-cropper:

    $(document).ready(function() {
      $(".banners").on("click", ".slide-cropper.next .slide-content", function() {
        var $container = $(this).closest(".slide");
        
        $(".slide-cropper").removeClass("prev")
          .removeClass("current")
          .removeClass("next");
    
        $(this).closest(".slide-cropper").addClass("current");
    
        var $prevContainer;
        if ($container.prev().length) {
          $prevContainer = $container.prev();
        } else {
          $prevContainer = $container.siblings(":last");
        }
        $prevContainer.find(".slide-cropper").addClass("prev");
    
        var $nextContainer;
        if ($container.next().length) {
          $nextContainer = $container.next();
        } else {
          $nextContainer = $container.siblings(":first");
        }
        $nextContainer.find(".slide-cropper").addClass("next");
      });
    });
    *,
    *:before,
    *:after {
      box-sizing: border-box;
    }
    
    /* all body styles are just for demo */
    /* just centering the slider */
    body {
      margin: 0;
      height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
      overflow: hidden;
    }
    
    .banners {
      width: 300px;
      height: 200px;
      position: relative;
    }
    
    .slide {
      width: 100%;
      height: 100%;
    }
    
    .slide .slide-cropper {
      position: absolute;
      left: -86.6px;
      top: 50px;
      width: 359.8px;
      height: 323.2px;
      transform-origin: 0 0;
      transform: rotate(-30deg);
      overflow: hidden;
      transition: height 2s linear;
    }
    
    .slide-content {
      position: absolute;
      background-size: 100% 100%;
      left: 100px;
      top: 0;
      width: 300px;
      height: 200px;
      transform: rotate(30deg);
      transform-origin: 0 0;
      z-index: 0;
      
      /* just styles for text */
      /* using flexbox to center text */
      display: flex;
      justify-content: center;
      align-items: center;
      color: #fff;
      font-size: 3em;
    }
    
    .slide1 .slide-content {
      background-image: url("https://i.stack.imgur.com/tt875.jpg");
    }
    
    .slide2 .slide-content {
      background-image: url("https://i.stack.imgur.com/hzbmw.jpg");
    }
    
    .slide3 .slide-content {
      background-image: url("https://i.stack.imgur.com/4UxLW.jpg");
    }
    
    .slide-cropper.prev {
      height: 0;
      z-index: 3;
    }
    
    .slide-cropper.current {
      height: 240px;
      transition-delay: 2s;
      z-index: 2;
    }
    
    .slide-cropper.next {
      z-index: 1;
    }
    
    /* Fix for IE */
    .slide-cropper.current {
      pointer-events: none;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div class="banners">
      <div class="slide slide1">
        <div class="slide-cropper current">
          <div class="slide-content">
            Slide 1
          </div>
        </div>
      </div>
    
      <div class="slide slide2">
        <div class="slide-cropper next">
          <div class="slide-content">
            Slide 2
          </div>
        </div>
      </div>
    
      <div class="slide slide3">
        <div class="slide-cropper">
          <div class="slide-content">
            Slide 3
          </div>
        </div>
      </div>
    </div>

    To understand how it works I moved all calculations to CSS variables AKA CSS custom properties. They work in many browsers but not in combination with CSS calc function. This example works perfectly only in Chrome but will help to understand and modify this example (just replace CSS variables with calculated hardcoded values). Also you can move this calculations to CSS preprocessor or JavaScript code.

    $(document).ready(function() {
      $(".banners").on("click", ".slide-cropper.next .slide-content", function() {
        var $container = $(this).closest(".slide");
        
        $(".slide-cropper").removeClass("prev")
          .removeClass("current")
          .removeClass("next");
    
        $(this).closest(".slide-cropper").addClass("current");
    
        var $prevContainer;
        if ($container.prev().length) {
          $prevContainer = $container.prev();
        } else {
          $prevContainer = $container.siblings(":last");
        }
        $prevContainer.find(".slide-cropper").addClass("prev");
    
        var $nextContainer;
        if ($container.next().length) {
          $nextContainer = $container.next();
        } else {
          $nextContainer = $container.siblings(":first");
        }
        $nextContainer.find(".slide-cropper").addClass("next");
      });
    });
    *,
    *:before,
    *:after {
      box-sizing: border-box;
    }
    
    html {
      --width: 300px;
      --height: 200px;
      /* rotate for image cropping */
      --rotate-angle: 30deg;
      /* sin 30 degrees for image cropping */
      --sin-rotate-angle: 0.5;
      /* cos 30 degrees for image cropping */
      --cos-rotate-angle: 0.8660254037844386;
      /* clipper ratio for width, can be from 0 to 1 */
      --clipper-ratio: 0.45;
      --animation-timeout: 2s;
    }
    
    /* all body styles are just for demo */
    /* just centering the slider */
    body {
      margin: 0;
      height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
      overflow: hidden;
    }
    
    .banners {
      width: var(--width);
      height: var(--height);
      position: relative;
    }
    
    .slide {
      width: 100%;
      height: 100%;
    }
    
    .slide .slide-cropper {
      position: absolute;
      left: calc(-1 * var(--height) * var(--sin-rotate-angle) * var(--cos-rotate-angle));
      top: calc(var(--height) * var(--sin-rotate-angle) * var(--sin-rotate-angle));
      width: calc(var(--height) * var(--sin-rotate-angle) + var(--width) * var(--cos-rotate-angle));
      height: calc(var(--height) * var(--cos-rotate-angle) + var(--width) * var(--sin-rotate-angle));
      transform-origin: 0 0;
      transform: rotate(calc(-1 * var(--rotate-angle)));
      overflow: hidden;
      transition: height var(--animation-timeout) linear;
    }
    
    .slide-content {
      position: absolute;
      background-size: 100% 100%;
      left: calc(var(--height) / 2);
      width: var(--width);
      height: var(--height);
      transform: rotate(var(--rotate-angle));
      transform-origin: 0 0;
      z-index: 0;
      
      /* just styles for text */
      display: flex;
      justify-content: center;
      align-items: center;
      color: #fff;
      font-size: 3em;
    }
    
    .slide1 .slide-content {
      background-image: url("https://i.stack.imgur.com/tt875.jpg");
    }
    
    .slide2 .slide-content {
      background-image: url("https://i.stack.imgur.com/hzbmw.jpg");
    }
    
    .slide3 .slide-content {
      background-image: url("https://i.stack.imgur.com/4UxLW.jpg");
    }
    
    .slide-cropper.prev {
      height: 0;
      z-index: 3;
    }
    
    .slide-cropper.current {
      height: calc(var(--height) * var(--cos-rotate-angle) + var(--clipper-ratio) * var(--width) * var(--sin-rotate-angle));
      transition-delay: var(--animation-timeout);
      z-index: 2;
    }
    
    .slide-cropper.next {
      z-index: 1;
    }
    
    /* Fix for IE */
    .slide-cropper.current {
      pointer-events: none;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div class="banners">
      <div class="slide slide1">
        <div class="slide-cropper current">
          <div class="slide-content">
            Slide 1
          </div>
        </div>
      </div>
    
      <div class="slide slide2">
        <div class="slide-cropper next">
          <div class="slide-content">
            Slide 2
          </div>
        </div>
      </div>
    
      <div class="slide slide3">
        <div class="slide-cropper">
          <div class="slide-content">
            Slide 3
          </div>
        </div>
      </div>
    </div>

    To change this to fullscreen you need to set --width: 100vw and --height: 100vh. (Of course, then you'll have to replace CSS variables with hardcoded values to work in all browsers). Demo:

    $(document).ready(function() {
      $(".banners").on("click", ".slide-cropper.next .slide-content", function() {
        var $container = $(this).closest(".slide");
        
        $(".slide-cropper").removeClass("prev")
          .removeClass("current")
          .removeClass("next");
    
        $(this).closest(".slide-cropper").addClass("current");
    
        var $prevContainer;
        if ($container.prev().length) {
          $prevContainer = $container.prev();
        } else {
          $prevContainer = $container.siblings(":last");
        }
        $prevContainer.find(".slide-cropper").addClass("prev");
    
        var $nextContainer;
        if ($container.next().length) {
          $nextContainer = $container.next();
        } else {
          $nextContainer = $container.siblings(":first");
        }
        $nextContainer.find(".slide-cropper").addClass("next");
      });
    });
    *,
    *:before,
    *:after {
      box-sizing: border-box;
    }
    
    html {
      --width: 100vw;
      --height: 100vh;
      /* rotate for image cropping */
      --rotate-angle: 30deg;
      /* sin 30 degrees for image cropping */
      --sin-rotate-angle: 0.5;
      /* cos 30 degrees for image cropping */
      --cos-rotate-angle: 0.8660254037844386;
      /* clipper ratio for width, can be from 0 to 1 */
      --clipper-ratio: 0.45;
      --animation-timeout: 2s;
    }
    
    /* all body styles are just for demo */
    /* just centering the slider */
    body {
      margin: 0;
      height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
      overflow: hidden;
    }
    
    .banners {
      width: var(--width);
      height: var(--height);
      position: relative;
    }
    
    .slide {
      width: 100%;
      height: 100%;
    }
    
    .slide .slide-cropper {
      position: absolute;
      left: calc(-1 * var(--height) * var(--sin-rotate-angle) * var(--cos-rotate-angle));
      top: calc(var(--height) * var(--sin-rotate-angle) * var(--sin-rotate-angle));
      width: calc(var(--height) * var(--sin-rotate-angle) + var(--width) * var(--cos-rotate-angle));
      height: calc(var(--height) * var(--cos-rotate-angle) + var(--width) * var(--sin-rotate-angle));
      transform-origin: 0 0;
      transform: rotate(calc(-1 * var(--rotate-angle)));
      overflow: hidden;
      transition: height var(--animation-timeout) linear;
    }
    
    .slide-content {
      position: absolute;
      background-size: 100% 100%;
      left: calc(var(--height) / 2);
      width: var(--width);
      height: var(--height);
      transform: rotate(var(--rotate-angle));
      transform-origin: 0 0;
      z-index: 0;
      
      /* just styles for text */
      display: flex;
      justify-content: center;
      align-items: center;
      color: #fff;
      font-size: 3em;
    }
    
    .slide1 .slide-content {
      background-image: url("https://i.stack.imgur.com/tt875.jpg");
    }
    
    .slide2 .slide-content {
      background-image: url("https://i.stack.imgur.com/hzbmw.jpg");
    }
    
    .slide3 .slide-content {
      background-image: url("https://i.stack.imgur.com/4UxLW.jpg");
    }
    
    .slide-cropper.prev {
      height: 0;
      z-index: 3;
    }
    
    .slide-cropper.current {
      height: calc(var(--height) * var(--cos-rotate-angle) + var(--clipper-ratio) * var(--width) * var(--sin-rotate-angle));
      transition-delay: var(--animation-timeout);
      z-index: 2;
    }
    
    .slide-cropper.next {
      z-index: 1;
    }
    
    /* Fix for IE */
    .slide-cropper.current {
      pointer-events: none;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div class="banners">
      <div class="slide slide1">
        <div class="slide-cropper current">
          <div class="slide-content">
            Slide 1
          </div>
        </div>
      </div>
    
      <div class="slide slide2">
        <div class="slide-cropper next">
          <div class="slide-content">
            Slide 2
          </div>
        </div>
      </div>
    
      <div class="slide slide3">
        <div class="slide-cropper">
          <div class="slide-content">
            Slide 3
          </div>
        </div>
      </div>
    </div>

    Also demo with CSS variables that work in Firefox (Firefox is not friendly with combination of CSS variables and transform: rotate, so I just replaced transform: rotate with hardcoded values):

    $(document).ready(function() {
      $(".banners").on("click", ".slide-cropper.next .slide-content", function() {
        var $container = $(this).closest(".slide");
        
        $(".slide-cropper").removeClass("prev")
          .removeClass("current")
          .removeClass("next");
    
        $(this).closest(".slide-cropper").addClass("current");
    
        var $prevContainer;
        if ($container.prev().length) {
          $prevContainer = $container.prev();
        } else {
          $prevContainer = $container.siblings(":last");
        }
        $prevContainer.find(".slide-cropper").addClass("prev");
    
        var $nextContainer;
        if ($container.next().length) {
          $nextContainer = $container.next();
        } else {
          $nextContainer = $container.siblings(":first");
        }
        $nextContainer.find(".slide-cropper").addClass("next");
      });
    });
    *,
    *:before,
    *:after {
      box-sizing: border-box;
    }
    
    html {
      --width: 100vw;
      --height: 100vh;
      /* sin 30 degrees for image cropping */
      --sin-rotate-angle: 0.5;
      /* cos 30 degrees for image cropping */
      --cos-rotate-angle: 0.8660254037844386;
      /* clipper ratio for width, can be from 0 to 1 */
      --clipper-ratio: 0.45;
      --animation-timeout: 2s;
    }
    
    /* all body styles are just for demo */
    /* just centering the slider */
    body {
      margin: 0;
      height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
      overflow: hidden;
    }
    
    .banners {
      width: var(--width);
      height: var(--height);
      position: relative;
    }
    
    .slide {
      width: 100%;
      height: 100%;
    }
    
    .slide .slide-cropper {
      position: absolute;
      left: calc(-1 * var(--height) * var(--sin-rotate-angle) * var(--cos-rotate-angle));
      top: calc(var(--height) * var(--sin-rotate-angle) * var(--sin-rotate-angle));
      width: calc(var(--height) * var(--sin-rotate-angle) + var(--width) * var(--cos-rotate-angle));
      height: calc(var(--height) * var(--cos-rotate-angle) + var(--width) * var(--sin-rotate-angle));
      transform-origin: 0 0;
      transform: rotate(-30deg);
      overflow: hidden;
      transition: height var(--animation-timeout) linear;
    }
    
    .slide-content {
      position: absolute;
      background-size: 100% 100%;
      left: calc(var(--height) / 2);
      width: var(--width);
      height: var(--height);
      transform: rotate(30deg);
      transform-origin: 0 0;
      z-index: 0;
      
      /* just styles for text */
      display: flex;
      justify-content: center;
      align-items: center;
      color: #fff;
      font-size: 3em;
    }
    
    .slide1 .slide-content {
      background-image: url("https://i.stack.imgur.com/tt875.jpg");
    }
    
    .slide2 .slide-content {
      background-image: url("https://i.stack.imgur.com/hzbmw.jpg");
    }
    
    .slide3 .slide-content {
      background-image: url("https://i.stack.imgur.com/4UxLW.jpg");
    }
    
    .slide-cropper.prev {
      height: 0;
      z-index: 3;
    }
    
    .slide-cropper.current {
      height: calc(var(--height) * var(--cos-rotate-angle) + var(--clipper-ratio) * var(--width) * var(--sin-rotate-angle));
      transition-delay: var(--animation-timeout);
      z-index: 2;
    }
    
    .slide-cropper.next {
      z-index: 1;
    }
    
    /* Fix for IE */
    .slide-cropper.current {
      pointer-events: none;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div class="banners">
      <div class="slide slide1">
        <div class="slide-cropper current">
          <div class="slide-content">
            Slide 1
          </div>
        </div>
      </div>
    
      <div class="slide slide2">
        <div class="slide-cropper next">
          <div class="slide-content">
            Slide 2
          </div>
        </div>
      </div>
    
      <div class="slide slide3">
        <div class="slide-cropper">
          <div class="slide-content">
            Slide 3
          </div>
        </div>
      </div>
    </div>

    0 讨论(0)
  • 2020-12-13 15:11

    A simple example accomplishing this effect with no javascript:
    https://jsfiddle.net/freer4/j2159b1e/2/

    html, body{
      height:100%;
      width:100%;
      margin:0;
      padding:0;
    }
    .banners {
      position:relative;
      background:#000;
      width: 100%;
      height: 100%;
      overflow:hidden;
    }
    .banners input{
      display:none;
    }
    .slide1{
      background-image: url(https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT5T6nwVYWsbzLcLF-JNxnGXFFFwkZMBcCMbaqeTevuldkxHg0N);
    }
    .slide2{
      background-image:url(http://www.rd.com/wp-content/uploads/sites/2/2016/02/06-train-cat-shake-hands.jpg);
    }
    .slide3{
      background-image:url(https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKr6YlGNsqgJzvgBBkq1648_HsuDizVn_ZXC6iQp9kjXFzLvs1BA);
    }
    .image {
      display:block;
      height:100%;
      width:100%;
      position: absolute;
      overflow:hidden;
      z-index:1;
      text-align:center;
      background-position:0 0;
      background-size:cover;
      transition:z-index 1s step-end;
      clip-path: polygon(100% 0, 100% 100%, 100% 100%, 0 100%, 0 0);
      animation-duration: 2s;
      animation-name: clipout;
    }
    input:checked + .image{
      z-index:3;
      transition:z-index 1s step-end;
      clip-path: polygon(100% 0, 100% 50%, 50% 100%, 0 100%, 0 0);
      animation-duration: 2.2s;
      animation-name: clipin;
      cursor:default;
    }
    .image:nth-child(2),
    input:checked + * + * + .image{
      z-index:2;
      cursor:pointer;
    }
    
    
    .content{
      color:#FFF;
      display:inline-block;
      vertical-align:middle;
      font-family:arial;
      text-transform:uppercase;
      font-size:24px;
      opacity:0;
      transition:0s opacity 1s;
    }
    input:checked + .image .content{
      opacity:1;
      transition:0.8s opacity 0.8s;
    }
    .spanner{
      vertical-align:middle;
      width:0;
      height:100%;
      display:inline-block;
    }
    
    @keyframes clipout {
      from { clip-path: polygon(100% 0, 100% 50%, 50% 100%, 0 100%, 0 0); }
      50%  { clip-path: polygon(100% 0, 100% -100%, -100% 100%, 0 100%, 0 0); }
      51%   { clip-path: polygon(100% 0, 100% 100%, 100% 100%, 0 100%, 0 0); }
      to   { clip-path: polygon(100% 0, 100% 100%, 100% 100%, 0 100%, 0 0); }
    }
    @keyframes clipin{
      from { clip-path: polygon(100% 0, 100% 100%, 100% 100%, 0 100%, 0 0); }
      50%  { clip-path: polygon(100% 0, 100% 100%, 100% 100%, 0 100%, 0 0); }
      to   { clip-path: polygon(100% 0, 100% 50%, 50% 100%, 0 100%, 0 0); }  
    }
    <div class="banners">
      <input type="radio" id="slide1" name="slides" checked="checked" />
      <label class="image slide1" for="slide1">
        <div class="content">
          Slide 1
        </div>
        <div class="spanner"></div>
      </label>
      <input type="radio" id="slide2" name="slides"  />
      <label class="image slide2" for="slide2">
        <div class="content">
          Slide 2
        </div>
        <div class="spanner"></div>
      </label>
      <input type="radio" id="slide3" name="slides"  />
      <label class="image slide3" for="slide3">
        <div class="content">
          Slide 3
        </div>
        <div class="spanner"></div>
      </label>
    </div>

    Basically, just use keyframes to animate the clip path. Get fancy with the z-indexes and some sibling selectors.

    0 讨论(0)
  • 2020-12-13 15:11

    This sample working on Firefox, Chrome, IE.

    For change sliding rule change transition

    $(document).ready(function () {
        $('.angle').click(function() {
            var $parent = $(this).parent();
            $parent.removeClass("current");
            if ($parent.next().length){
            	$parent.next().addClass("current");
            } else {
            	$parent.prevAll().last().addClass("current");
            }
        });
    });
    body{
      height:100%;
      width:100%;
    }
    
    .slideShow {
        width: 100%;
        height: 100%;
    }
    
    .image {
        width: 100%;
        height: 100%;
        position: absolute;
        left: 0;
        top: 0;
        overflow:hidden;
        z-index:1;
        transition:z-index 2s step-end, 1s opacity 1s ease-in-out;
        text-align:center;
        opacity:0;
        background-size:100% 100%;
        background-attachment:fixed;
    }
    .image.current{
        opacity:1;
        z-index:2;
        transition:z-index 2s step-end, 0s opacity 0s;
    }
    
    .angle {
        width: 200%;
        height: 200%;
        position: absolute;
        top: -100%;
        left: -100%;
        clip-path: polygon(100% 0, 0 70%,  0 100%, 100% 100%, 100% 0, 100% 0);
        z-index:3;
        margin-left:150%;
        margin-top:150%;
        transition:2s top ease-in-out, 2s left ease-in-out, 0s margin 2s;
        background-size:100% 100%;
        background-attachment:fixed;
    }
    .image.current .angle{
      top:0;
      left:0;
      margin-top:0;
      margin-left:0;
      transition:0s top ease-in-out 1s, 0s left ease-in-out 1s, 2s margin ease-in-out 1s;
    }
    .main{
      color:#FFF;
      display:inline-block;
      vertical-align:middle;
      font-family:arial;
      text-transform:uppercase;
      font-size:24px;
    }
    .middle{
      vertical-align:middle;
      width:0;
      height:100%;
      display:inline-block;
    }
    
    .image1, .image3 .angle{
      background-image: url(http://i3.imgbus.com/doimg/4c5o0m8m6o5n4e0.png);
    }
    .image1 .angle, .image2{
      background-image:url(http://i4.imgbus.com/doimg/1c7obm6m1o3nbb0.png);
    }
    .image2 .angle, .image3{
      background-image:url(http://i3.imgbus.com/doimg/ccbo5m2m8o8n759.jpg);
    }
    <div class="slideShow">
      <div class="image image1 current">
        <div class="main">
        </div>
        <div class="middle"></div>
        <div class="angle" style="background-color: cyan;"></div>      
      </div>
    
      <div class="image image2" style="background-color: cyan;">
        <div class="main">
        </div>
        <div class="middle"></div>
        <div class="angle" style="background-color: magenta;"></div>
      </div>
      
      <div class="image image3" style="background-color: magenta;">
        <div class="main">
        </div>
        <div class="middle"></div>
        <div class="angle"></div>
      </div>
    </div>

    Also you can use SildeShow Maker softwares like Amazing Slider.

    easy download, easy use: download link

    it's very powerful software. see Screenshot

    0 讨论(0)
  • 2020-12-13 15:14

    This is an answer without the use of clip-path, because browser compatibility on DOM elements other than svg is low.

    I see now that Vadim had the same idea as me with the rotated container (hadn't checked back here until I had finished), but from what I can tell there are still enough differences between our answers to justify posting my solution:

    $(document).ready(function() {
      $(".slider").on("click",".next",function() {
        if ($(this).prev().length) {$(this).prev().removeClass("curr");} else {$(this).siblings().last().removeClass("curr");} //deactivate current slide
        if ($(this).next().length) {$(this).next().addClass("next");} else {$(this).siblings().first().addClass("next");} //prepare slide that follows next slide
        $(this).removeClass("next").addClass("curr"); //activate next slide
      });
    });
    .slider, .slider .img {
      width: 55vw;
      height: calc(55vw / 16*9);
      background: #000 center/contain no-repeat;
    }
    .slider {position:relative; margin:0 auto; overflow:hidden;}
    
    .slider .slide {
      position: absolute;
      z-index: 0;
      width: 250%;
      height: 0;
      transform: translateX(-50%) rotate(-20deg);
      transform-origin: 50% 0;
      transition:z-index 0s 0.7s, height 0.7s;
      overflow: hidden;
    }
    .slider .slide.next {z-index:1; height:155%; opacity:0.5; transition:z-index 0s 1.1s, height 0s 0.7s; cursor:pointer;}
    .slider .slide.curr {z-index:2; height:135%; opacity:1.0; transition:z-index 0s 1.1s, height 0.4s 0.7s, opacity 0.7s;}
    
    .slider .slide .img {margin-left:50%; transform:rotate(20deg); transform-origin:0 0;}
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div class="slider">
      <div class="slide curr"><div class="img" style="background-image:url(https://placeimg.com/640/480/animals);"></div></div>
      <div class="slide next"><div class="img" style="background-image:url(https://placeimg.com/640/480/people);"></div></div>
      <div class="slide"><div class="img" style="background-image:url(https://placeimg.com/640/480/nature);"></div></div>
      <div class="slide"><div class="img" style="background-image:url(https://placeimg.com/640/480/tech);"></div></div>
      <div class="slide"><div class="img" style="background-image:url(https://placeimg.com/640/480/arch);"></div></div>
    </div>
    codepen: https://codepen.io/anon/pen/JJQRvM
    jsfiddle: https://jsfiddle.net/tq2hw7b9/5/

    • Instead of clip-path I just change the height of the slide containers, using transition for the animation effects.

    IE TROUBLES

    Unfortunately, as usual, IE processes transform:rotate() differently from other browsers. Visually the rotations happen, but the browser still seems to reserve the original space of the elements, so therefor the exposed corner of the next slide is not clickable because the current slide is 'covering' it. Using the -ms- or -webkit- prefix doesn't make a difference.

    The following code snippet DOES work in IE:

    $(document).ready(function() {
      $(".slider .corner").on("click",function() {
      	var $next = $(this).siblings(".next");
        if ($next.prev().length) {$next.prev().removeClass("curr");} else {$next.siblings(".slide").last().removeClass("curr");} //deactivate current slide
        if ($next.next(".slide").length) {$next.next().addClass("next");} else {$next.siblings().first().addClass("next");} //prepare slide that follows next slide
        $next.removeClass("next").addClass("curr"); //activate next slide
      });
    });
    .slider, .slider .img {
      width: 55vw;
      height: calc(55vw / 16*9);
      background: #000 center/contain no-repeat;
    }
    .slider {position:relative; margin:0 auto; overflow:hidden;}
    
    .slider .corner {
      position: absolute;
      z-index: 3;
      bottom: 0;
      right: 0;
      width: 100%;
      height: 21%;
      transform: rotate(-20deg);
      transform-origin: 100% 0;
      cursor: pointer;
    }
    
    .slider .slide {
      position: absolute;
      z-index: 0;
      width: 250%;
      height: 0;
      transform: translateX(-50%) rotate(-20deg);
      transform-origin: 50% 0;
      transition:z-index 0s 0.7s, height 0.7s;
      overflow: hidden;
    }
    .slider .slide.next {z-index:1; height:155%; opacity:0.5; transition:z-index 0s 1.1s, height 0s 0.7s;}
    .slider .slide.curr {z-index:2; height:135%; opacity:1.0; transition:z-index 0s 1.1s, height 0.4s 0.7s, opacity 0.7s;}
    
    .slider .slide .img {margin-left:50%; transform:rotate(20deg); transform-origin:0 0;}
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div class="slider">
      <div class="slide curr"><div class="img" style="background-image:url(https://placeimg.com/640/480/animals);"></div></div>
      <div class="slide next"><div class="img" style="background-image:url(https://placeimg.com/640/480/people);"></div></div>
      <div class="slide"><div class="img" style="background-image:url(https://placeimg.com/640/480/nature);"></div></div>
      <div class="slide"><div class="img" style="background-image:url(https://placeimg.com/640/480/tech);"></div></div>
      <div class="slide"><div class="img" style="background-image:url(https://placeimg.com/640/480/arch);"></div></div>
      <div class="corner"></div>
    </div>
    codepen: https://codepen.io/anon/pen/GEbrzQ
    jsfiddle: https://jsfiddle.net/8ggqndj1/

    • I added an extra <div class="corner"> that covers all the slides.
    • The click-handler in JS is now bound to this .corner, and at the start of the handler a reference to the next slide is stored into a variable, which is used in the rest of the code.
    • In CSS there is also a new rule for the .corner.

    SLIDE-ARRAY IN JS

    Have a look at the code snippet below, for a list of slides in JS (if someone needs it):

    $(document).ready(function() {
      var slides = [
      	2, //index for next slide
        "https://placeimg.com/640/480/animals",
        "https://placeimg.com/640/480/people",
        "https://placeimg.com/640/480/nature",
        "https://placeimg.com/640/480/tech",
        "https://placeimg.com/640/480/arch"
      ];
      
    //INITIALIZE SLIDESHOW--------------------
      $(".slider").css("background-image","url("+slides[2]+")"); //set next slide
      $(".slider .current .img").css("background-image","url("+slides[1]+")"); //set current slide, and set slide-height to slideshow-height
      
    //SLIDESHOW CLICK-HANDLER--------------------
      $(".slider .current").on("click",function(e){e.stopPropagation();});
      $(".slider").on("click",function() {
      	$(this).children(".current").animate({height:0},700,function(){
        	$(this).children(".img").css("background-image","url("+slides[slides[0]]+")"); //set the current slide to the next slide
        	$(this).css("height","155%"); //cover entire slide
          if (slides[0]==slides.length-1) {slides[0]=1;} else {++slides[0];} //increase/loop index for next slide
          $(this).parent().css("background-image","url("+slides[slides[0]]+")"); //set the next slide to the next slide after that
          $(this).animate({height:"135%"},400); //reveal corner for next slide
        });
      });
    });
    .slider, .slider .img {
      width: 55vw;
      height: calc(55vw / 16*9);
      background: #000 center/contain no-repeat;
    }
    .slider {margin:0 auto; cursor:pointer; overflow:hidden;}
    
    .slider .current {
      width: 250%;
      height: 135%;
      transform: translateX(-50%) rotate(-20deg);
      transform-origin: 50% 0;
      overflow: hidden;
      cursor: default;
    }
    .slider .current .img {margin-left:50%; transform:rotate(20deg); transform-origin:0 0;}
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div class="slider"><div class="current"><div class="img"></div></div></div>
    codepen: https://codepen.io/anon/pen/EXBgew
    jsfiddle: https://jsfiddle.net/qghv9bnh/13/

    • It may hold some preferences for some, although I think my first solution is a lot cleaner, faster, and flexible for adding extra slides (certainly when you use a CMS like WordPress or Joomla):
      1. The images are only loaded when you actually use the slider, so users save bandwidth for every slide they don't click on.
      2. The HTML is very concise and will never grow no matter how many slides you have, so your HTML will look cleaner (but if you use PHP to include them it will look just as clean, even cleaner).

    Can't really think of anything else, as I said, I prefer the first one. But none the less, it may come in handy for someone.

    0 讨论(0)
提交回复
热议问题