【问题标题】:List / Grid / Tile view transitions using jquery or javascript使用 jquery 或 javascript 的列表/网格/平铺视图转换
【发布时间】:2021-12-21 00:40:57
【问题描述】:

我想用Jquery/JS实现list/grid/tile视图。

我已经浏览了很多关于带有动画的网格/列表视图,但只有网格/列表视图解决方案。 但我需要网格/列表视图以及动画(即过渡效果)。我附上了过渡效果的样本video

【问题讨论】:

    标签: javascript jquery css animation css-transitions


    【解决方案1】:

    这是我的基本实现。我试图创建像视频一样的输出。
    这个想法是将列表项包装在一个包装器中。包装器是静态放置的,列表项是绝对放置的。当视图更改时,包装器会根据样式表或容器规则自动排列。但是在动画之后移动列表项。

    var pos = [];
    var offs = null;
    
    function init() {
      offs = $(".container").first().offset();
      $(".wrapper").each(function (i) {
        updatePositions();
        $(this).children(0).css({
          top: pos[i].top,
          left: pos[i].left
        });
      });
    }
    
    $(document).ready(function () {
      init();
    });
    
    $(window).resize(function () {
      init();
    })
    
    function updatePositions() {
      $(".wrapper").each(function(index) {
        var tp = $(this).offset().top - offs.top;
        var lf = $(this).offset().left - offs.left;
        pos[index] = {
          top: tp,
          left: lf
        };
      });
    }
    
    function grid() {
      if ($(".wrapper").first().hasClass("gv-wrapper")) return;
      updatePositions();
      $(".wrapper").each(function(index) {
        $(this).removeClass("dv-wrapper cv-wrapper");
        $(this).addClass("gv-wrapper");
    
        $(this).children(0).css({
          opacity: 0.8,
          top: pos[index].top,
          left: pos[index].left
        });
      });
    
      updatePositions();
      $(".wrapper").each(function(index) {
        $(this).children(0).children(0).removeClass("dv-video cv-video");
        $(this).children(0).children(1).removeClass("dv-details cv-details");
        $(this).children(0).children(0).first().addClass("gv-video");
        $(this).children(0).children(1).last().addClass("gv-details");
        $(this).children(0).animate({
          height: "100px",
          width: "200px",
          opacity: 1,
          top: pos[index].top,
          left: pos[index].left
        }, 1000, "swing");
      });
    }
    
    
    function detailed() {
      if ($(".wrapper").first().hasClass("dv-wrapper")) return;
    
      updatePositions();
    
      $(".wrapper").each(function(index) {
        $(this).removeClass("gv-wrapper cv-wrapper");
        $(this).addClass("dv-wrapper");
    
        $(this).children(0).css({
          opacity: 0.8,
          top: pos[index].top,
          left: pos[index].left
        });
      });
    
      updatePositions();
      $(".wrapper").each(function(index) {
        $(this).children(0).children(0).removeClass("gv-video cv-video");
        $(this).children(0).children(1).removeClass("gv-details cv-details");
        $(this).children(0).children(0).first().addClass("dv-video");
        $(this).children(0).children(1).last().addClass("dv-details");
    
        $(this).children(0).animate({
          height: "100px",
          width: "95%",
          opacity: 1,
          top: pos[index].top,
          left: pos[index].left
        }, 1000, "swing");
      });
    }
    
    
    function collapsed() {
      if ($(".wrapper").first().hasClass("cv-wrapper")) return;
    
      updatePositions();
      $(".wrapper").each(function(index) {
        $(this).removeClass("dv-wrapper gv-wrapper");
        $(this).addClass("cv-wrapper");
    
        $(this).children(0).css({
          opacity: 0.8,
          top: pos[index].top,
          left: pos[index].left
        });
      });
    
      updatePositions();
      $(".wrapper").each(function(index) {
        $(this).children(0).children(0).removeClass("dv-video gv-video");
        $(this).children(0).children(1).removeClass("dv-details gv-details");
        $(this).children(0).children(0).first().addClass("cv-video");
        $(this).children(0).children(1).last().addClass("cv-details");
    
        $(this).children(0).animate({
          height: "50px",
          width: "94%",
          opacity: 1,
          top: pos[index].top,
          left: pos[index].left
        }, 1000, "swing");
      });
    
    }
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      counter-reset: number;
      background-color: #ffffff;
      padding: 24px;
    }
    
    i.fas {
      margin: 5px;
    }
    
    i.fas:hover {
      background-color: white;
    }
    
    .container {
      width: 500px;
      min-height: 90vh;
      margin: 0 auto;
      background-color: #ADC2A9;
      border: 1px dotted gray;
      font-size: 0.7em;
      position: relative;
    }
    
    .wrapper {
      margin: 10px 10px;
      /* to debug enable the color */
      /*background-color: darkcyan;*/
    }
    
    .record {
      position: absolute;
      width: 95%;
      top: 0px;
      left: 0px;
      background-color: #D3E4CD;
    }
    
    .record:first-child:before {
      counter-increment: number;
      content: counter(number);
      position: absolute;
      top: 10%;
      left: 10%;
      font-size: 23px;
      color: blue
    }
    
    .video {
      width: 200px;
      height: 100px;
      background: linear-gradient(white 40%, #5e819ef8);
    }
    
    
    /* list view */
    
    .dv-wrapper {
      height: 100px;
      width: 95%;
      float: left;
    }
    
    .dv-video {}
    
    .dv-details {
      position: absolute;
      width: calc(100% - 200px);
      top: 0px;
      right: 0px;
      float: right;
      padding-left: 10px;
      overflow: hidden;
    }
    
    
    /* grid view */
    
    .gv-wrapper {
      height: 100px;
      width: 200px;
      float: left;
    }
    
    .gv-video {
      float: left;
    }
    
    .gv-details {
      position: absolute;
      left: 0px;
      bottom: 0px;
      padding-left: 10px;
      overflow: hidden;
    }
    
    
    /* collapsed view */
    
    .cv-wrapper {
      height: 50px;
      width: 80%;
    }
    
    .cv-video {
      float: left;
      display: none;
    }
    
    .cv-details {
      padding-left: 10px;
      overflow: hidden;
    }
    
    .details p {
      width: 100%;
      text-overflow: ellipsis;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet" />
    
    <div style="margin: 0 50%; width: 100px; transform: translate(-50%);">
      <i class="fas fa-list" onclick="detailed()"></i>
      <i class="fa fa-th" onclick="grid()"></i>
      <i class="fas fa-bars" onclick="collapsed()"></i>
    </div>
    <div class="container">
      <div class="dv-wrapper wrapper">
        <div class="record">
          <div class="video dv-video"></div>
          <div class="details dv-details">
            <p>1 Lorem ipsum dolor sit amet consectetur adipiorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt, dolor.</p>
          </div>
        </div>
      </div>
      <div class="dv-wrapper wrapper">
        <div class="record">
          <div class="video dv-video"></div>
          <div class="details dv-details">
            <p>2 Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt, dolor.</p>
          </div>
        </div>
      </div>
      <div class="dv-wrapper wrapper">
        <div class="record">
          <div class="video dv-video"></div>
          <div class="details dv-details">
            <p>3 Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt, dolor.</p>
          </div>
        </div>
      </div>
      <div class="dv-wrapper wrapper">
        <div class="record">
          <div class="video dv-video"></div>
          <div class="details dv-details">
            <p>4 Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt, dolor.</p>
          </div>
        </div>
      </div>
      <div class="dv-wrapper wrapper">
        <div class="record">
          <div class="video dv-video"></div>
          <div class="details dv-details">
            <p>5 Lorem ipsum dolor sit amet consectetur adipisicing elit. Deserunt, dolor.</p>
          </div>
        </div>
      </div>
    
    </div>

    这只是一个演示代码。它可以通过多种方式进行改进。我们可以将包装器放入现有的网格或弹性容器中,并为内容项设置动画,如上所示。
    让我知道是否有现成的第三方可以减少或改进上述代码。

    【讨论】:

      【解决方案2】:

      代码

      https://codepen.io/shahriarkh/pen/NWvOyry?editors=0110

      单击网格上方的“更改样式”按钮以切换动画。


      来了!
      我使用了grid,因为它是可动画的,因为它是一个二维网格,而blockflex 都是一维的。

      但是,右侧出现的滚动条有问题。这该死的烦人,我找不到解决它的方法。在 JS 代码的第 9 行中,每张卡片应该向左移动 120px * N,但是当滚动条出现时,它不再是 120,而是变得比 120 大一点(比如 126)。我不知道它是从哪里来的......虽然当你将overflow-y: hidden 添加到body 时,120 可以正常工作,但这不是一个适用的解决方法(你需要滚动!)。

      更新

      我找到了解决方案!使用overflow-y: scroll + scrollbar-width: none 可以解决问题。但是,您需要以某种方式让用户知道该页面是可滚动的。


      顺便说一句,原始视频是什么?我想知道它是否是一个网页,并且有人已经这样做了:) 此外,Framer Motion 可能是一个不错的选择,而不是编码。

      【讨论】:

      • 我真的很喜欢 :)
      • 感谢您的解决方案。如果您能像视频中一样提供平铺视图动画,那就太好了。
      • 在视频中您可以看到 3 个按钮:1.网格视图 2. 列表视图 3. 平铺视图(即仅列表视图,但动画将从下到上) >> 查看视频一次,您可以在第三个按钮单击时看到动画..跨度>
      • 我明白了。我认为如果你把它作为一个单独的问题来问会更好:)
      【解决方案3】:

      我知道这看起来与您想要的结果不完全一样,但也许它适合您,或者您可以在此基础上进行构建。我只是在宽度和间隔上使用了一个过渡来在变换中有一个小的延迟。

      function toggle(){
        var k= 0;
        var i = setInterval(function(){
      t = $('.test').length;
      if(k>t){
       clearInterval(t)
      }
      $('.test').eq(k).toggleClass("test2");
      k++;
      
        },120)
      }
      
      setTimeout(function(){
        toggle()
      },1000)
      .wrap {
        width:500px;
        min-height:100vh;
        position:relative;
        margin: 0 auto;
      }
      .test {
        color:white;
        margin:10px;
        background:black;
        width:100px;
        height:100px;
        float:left;
        -webkit-transition: width 1s ease-in-out;
        -moz-transition: width 1s ease-in-out;
        -o-transition: width 1s ease-in-out;
        transition: width 1s ease-in-out;
      }
      .test2 {
        width:100%;
      }
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <div class="wrap">
      <div class="test"></div>
      <div class="test"></div>
      <div class="test"></div>
      <div class="test"></div>
      <div class="test"></div>
      <div class="test"></div>
      <div class="test"></div>
      
        </div>

      如果您希望它与视频中的完全一样,您可能必须使用 translate-x translate-y

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-11
        • 2011-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-08
        • 2012-01-18
        相关资源
        最近更新 更多