【问题标题】:animate line under two css tabs两个 css 选项卡下的动画线
【发布时间】:2020-08-23 23:42:18
【问题描述】:

请问我想知道如何使用 JS 或 Jquery 或 Vue Transitions 创建像这样的动画(我正在使用引导程序)。

当我点击 TAB2 时,我想将 TAB1 下的线向右移动。我怎样才能使 div 动画从左到右平滑地移动,反之亦然?

这是我的代码:

<div class="col-md-12">
  <div class="col-md-6">
        <p>TAB1</p>
  </div>
  <div class="col-md-6">
        <p>TAB2</p>
  </div>
</div>
<div class="col-md-6">
<span style="height:10px;background-color:"></span>
</div>

【问题讨论】:

标签: jquery css vue.js bootstrap-4


【解决方案1】:

我做了两个不同的版本。

第一个是特定于 Vue 的,它也实现了悬停效果,以便在移动选项卡时移动栏,如果未单击选项卡则返回。

第二个示例是纯 JavaScript 版本,它仅在单击新选项卡时移动栏。

/* Vue Section */
new Vue({
  el: '#app',
  computed: {
    lineStyles() {
      return this.lineTemp == null ? this.line : this.lineTemp;
    }
  },
  mounted() {
    const tab = document.getElementById('nav-tab-1');
    if (tab) {
      let styles = {
        left: tab.offsetLeft,
        width: tab.clientWidth
      }
      this.line = styles;
    }
  },
  data() {
    return {
      currentTab: 2,
      line: {
        left: 0,
        width: 69
      },
      lineTemp: null
    }
  },
  methods: {
    onTabClick(evt) {
      const tab = evt.target
      let styles = {
        left: tab.offsetLeft,
        width: tab.clientWidth
      }
      this.line = styles;
    },
    onTabMouseEnter(evt) {
      const tab = evt.target
      let styles = {
        left: tab.offsetLeft,
        width: tab.clientWidth
      }
      this.lineTemp = styles;
    },
    onTabMouseLeave() {
      this.lineTemp = null;
    }
  }
})


/* Plain JS section */
function onTabClick(evt) {
  setLineStyle(evt.target)
}

function setLineStyle(tab) {
  let line = document.querySelector('.tabs2 > .line')
  line.style.left = tab.offsetLeft + "px";
  line.style.width = tab.clientWidth + "px";
}

/* bind events on load */
window.onload = function() {
  const tabs = document.querySelectorAll('.tabs2 > .nav > .nav-item')
  tabs.forEach((tab, index) => {
    tab.onclick = onTabClick;
    
    if(index == 0) setLineStyle(tab);
  })
}
.line {
  position: absolute;
  bottom: 0;
  transition: left 0.5s ease-in-out, width 0.5s 0.10s;
  height: 10px;
  background-color: blue;
  left: 0;
  width: 69px;
  pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<link href="https://unpkg.com/bootstrap@4.4.1/dist/css/bootstrap.min.css" rel="stylesheet" />

<!-- Vue Section -->
<div id="app">
  <h4>Vue Option with hover effect</h4>
  <div class="position-relative">
    <ul class="nav">
      <li v-for="i in 3" :id="`nav-tab-${i}`" class="nav-item" @click="onTabClick" @mouseenter="onTabMouseEnter" @mouseleave="onTabMouseLeave">
        <a class="nav-link" href="#">
          Tab {{ i }}
        </a>
      </li>
    </ul>
    <div class="line" :style="{ left: `${lineStyles.left}px`, width: `${lineStyles.width}px` }"></div>
  </div>
</div>
<hr />

<!-- Plain Javascript Section -->
<div>
  <h4>Plain javascript option with only click</h4>
  <div class="tabs2 position-relative">
    <ul class="nav">
      <li class="nav-item">
        <a class="nav-link" href="#">
          Tab 1
        </a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">
          Long tab 2
        </a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">
          Tab 3
        </a>
      </li>
    </ul>
    <div class="line"></div>
  </div>
</div>

【讨论】:

    【解决方案2】:

    请尝试下面的这个代码。我希望你能得到包括动画在内的解决方案。

    .tab p {
        display: inline-block;
        margin-right: 30px;
        position: relative;
        margin-bottom: 0;
        font-size: 30px;
    }
        
    .tab p:last-child {
        margin-right: 0px;
    }
        
    .tab p:before {
        content: '';
        position: absolute;
        left: 0;
        bottom: 0;
        width: 0;
        height: 5px;
        background-color: #8C076E;
        -webkit-transition: .5s;
        transition: .5s
    }
        
    .tab p:hover:before {
        width: 100%
    }
    <div class="col-md-12">
        <div class="tab">
            <p>TAB1</p>
            <p>TAB2</p>
        </div>
    </div>

    【讨论】:

      【解决方案3】:

      试试这个,这是我自制的可能会有帮助,我没有使用引导程序,只是一个简单的方法:

      <!DOCTYPE html>
      <html>
        <head>
          <meta name="viewport" content="width=device-width, initial-scale=1">
          <style>
            /* mymenu container can be anything you want */
            .menuwrap {
              margin-top: 0px; 
              padding:0px; 
              background-color: white ; 
              overflow: auto; 
              white-space: nowrap; 
              width: 100%; 
              height: 75px;
            }
      
            .mylinec { 
              margin-left: 0px; 
              top: 0px; 
              position: relative; 
              background-color: blue; 
              height: 5px; 
              width:100px; 
            } 
      
            .mybutton {
              width:100px;
              background: transparent; 
              border:0px; 
              color: black; 
              padding: 10px 15px; 
              text-align: center; 
              text-decoration: none; 
              display: inline-block; 
              font-size: 13px; 
              margin: 0px 0px; 
              cursor: pointer; 
              -webkit-transition-duration: 0.4s; 
              /* Safari */ 
              transition-duration: 0.4s; 
              //if need shadow; 
              //box-shadow: 0px 5px 18px
            }
          </style>
        </head>
        <body style="text-align:left; margin: 0px;">
          <div class="menuwrap" id="menu">
            <input type="button" class="mybutton" id="tab1" value="Tab 1" onClick="req_divmleft(this.offsetLeft), animatethisline()"/>
            <input type="button" class="mybutton" id="tab2" value="Tab 2" onClick="req_divmleft(this.offsetLeft), animatethisline()"/>
            <input type="button" class="mybutton" id="tab3" value="Tab 3" onClick="req_divmleft(this.offsetLeft), animatethisline()"/>
        
            <div id="myline" class ="mylinec"></div>
          </div>
      
          <!-- Need storage or variable for the history click or this can be hide you change type="hidden"  -->
      
          <input type="text" class="" id="txtstart" value="0" />
          <input type="text" class="" id="txtdestination" value="0" />
      
          <script>
            // request elements left
            function req_divmleft(clicked_offsetLeft) { 
              document.getElementById("txtdestination").value = clicked_offsetLeft; 
            }
      
            function animatethisline() {
              // get delay var left from left start
              var getdlm = document.getElementById("txtstart");
              // get destination (active moves)
              var getlm = document.getElementById("txtdestination");
              var leslide = document.getElementById("myline");
      
              leslide.animate([ 
                // keyframes 
                { transform: "translateX("+getdlm.value+"px)" }, 
                { transform: "translateX("+getlm.value+"px)" }
              ], { // timing options 
                duration: 1000, 
                easing: "ease-out",
                fill: "both"
              });
      
              setTimeout(getdelx, 100);
      
              function getdelx() {
                getdlm.value = getlm.value;
              }
            }
          </script>
        </body>
      </html>

      【讨论】:

        【解决方案4】:

        .navbar {
                    list-style: none;
                    margin: 50px auto;
                    max-width: 720px;
                    padding: 0;
                    width: 100%;
                }
        
                .navbar-item {
                    background: #fff;
                    display: block;
                    float: left;
                    margin: 0;
                    padding: 0;
                    width: 20%;
                    text-align: center;
                }
        
                .navbar-item:first-child {
                    border-radius: 3px 0 0 3px;
                }
        
                .navbar-item:last-child {
                    border-radius: 0 3px 3px 0;
                }
        
                .navbar-item.navbar-item-active a {
                    color: #e80000;
                }
        
                .navbar-item a {
                    color: #313131;
                    display: block;
                    padding-top: 20px;
                    padding-bottom: 20px;
                    text-decoration: none;
                }
        
                .navbar-item a:hover {
                    color: #e80000;
                }
        
                .navbar-indicator {
                    position: relative;
                    z-index: 0;
                }
        
                .navbar-indicator .navbar-item:last-child:before,
                .navbar-indicator .navbar-item:last-child:after {
                    content: '';
                    display: block;
                    position: absolute;
                    pointer-events: none;
                    -webkit-transition: left 1.3s ease;
                    transition: left 1.3s ease;
                }
        
                .navbar-indicator .navbar-item:last-child:before {
                    border: 6px solid transparent;
                    border-top-color: #e80000;
                    width: 0;
                    height: 0;
                    top: 0;
                    left: 10%;
                    margin-left: -3px;
                }
        
                .navbar-indicator .navbar-item:last-child:after {
                    background: #e80000;
                    top: -6px;
                    bottom: -6px;
                    left: 0;
                    width: 20%;
                    z-index: -1;
                }
        
                .navbar-indicator .navbar-item:nth-child(1).navbar-item-active~.navbar-item:last-child:after {
                    left: 0%;
                }
        
                .navbar-indicator .navbar-item:nth-child(1).navbar-item-active~.navbar-item:last-child:before {
                    left: 10%;
                }
        
                .navbar-indicator .navbar-item:nth-child(2).navbar-item-active~.navbar-item:last-child:after {
                    left: 20%;
                }
        
                .navbar-indicator .navbar-item:nth-child(2).navbar-item-active~.navbar-item:last-child:before {
                    left: 30%;
                }
        
                .navbar-indicator .navbar-item:nth-child(3).navbar-item-active~.navbar-item:last-child:after {
                    left: 40%;
                }
        
                .navbar-indicator .navbar-item:nth-child(3).navbar-item-active~.navbar-item:last-child:before {
                    left: 50%;
                }
        
                .navbar-indicator .navbar-item:nth-child(4).navbar-item-active~.navbar-item:last-child:after {
                    left: 60%;
                }
        
                .navbar-indicator .navbar-item:nth-child(4).navbar-item-active~.navbar-item:last-child:before {
                    left: 70%;
                }
        
                .navbar-indicator .navbar-item:nth-child(1):hover~.navbar-item:last-child:after {
                    left: 0% !important;
                }
        
                .navbar-indicator .navbar-item:nth-child(1):hover~.navbar-item:last-child:before {
                    left: 10% !important;
                }
        
                .navbar-indicator .navbar-item:nth-child(2):hover~.navbar-item:last-child:after {
                    left: 20% !important;
                }
        
                .navbar-indicator .navbar-item:nth-child(2):hover~.navbar-item:last-child:before {
                    left: 30% !important;
                }
        
                .navbar-indicator .navbar-item:nth-child(3):hover~.navbar-item:last-child:after {
                    left: 40% !important;
                }
        
                .navbar-indicator .navbar-item:nth-child(3):hover~.navbar-item:last-child:before {
                    left: 50% !important;
                }
        
                .navbar-indicator .navbar-item:nth-child(4):hover~.navbar-item:last-child:after {
                    left: 60% !important;
                }
        
                .navbar-indicator .navbar-item:nth-child(4):hover~.navbar-item:last-child:before {
                    left: 70% !important;
                }
        
                .navbar-indicator .navbar-item:last-child:hover:before,
                .navbar-indicator .navbar-item:last-child.navbar-item-active:before {
                    left: 90% !important;
                }
        
                .navbar-indicator .navbar-item:last-child:hover:after,
                .navbar-indicator .navbar-item:last-child.navbar-item-active:after {
                    left: 80% !important;
                }
        
                *,
                *:before,
                *:after {
                    box-sizing: border-box;
                }
        
                .navbar:before,
                .navbar:after {
                    content: " ";
                    display: table;
                }
        
                .navbar:after {
                    clear: both;
                }
        
                html {
                    background-color: #313131;
                    font-family: 'Open Sans', sans-serif;
                    font-weight: 800;
                }
        
                .toggle {
                    color: #fff;
                    font-family: sans-serif;
                    text-align: center;
                }
        <!doctype html>
        <html lang="en">
        
        <head>
            <!-- Required meta tags -->
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <title>css animate border left to right - tabmenu</title>
        </head>
        <body>
            <ul class="navbar navbar-indicator">
                <li class="navbar-item"><a href="#">Menu 1</a></li>
                <li class="navbar-item"><a href="#">Menu 2</a></li>
                <li class="navbar-item navbar-item-active"><a href="#">Menu 3</a></li>
                <li class="navbar-item"><a href="#">Menu 4</a></li>
                <li class="navbar-item"><a href="#">Menu 5</a></li>
            </ul>
        </body>
        
        </html>

        【讨论】:

          【解决方案5】:

          如果你想这样做,请在两个按钮和 然后用你需要的宽度做一个 div 的孩子,并给它position:absolute。只需在悬停和焦点或你需要的伪类上调整左右值,希望你能理解

          【讨论】:

            【解决方案6】:

            我已经使用这个简单的跨浏览器 css 库来创建大量动画。 希望这会帮助您解决问题。 (您可以在文本的一侧制作一个 div 并为其底部边框设置动画以从左向右平滑移动) 只需使用它即可制作动画

            animate.css

            animate.css > github

            【讨论】:

              【解决方案7】:

              您可以使用这个简单的示例作为参考,它使用的是 jQuery。

              $(document).on('click', '.slider-tabs .nav-link', function() {
                handleTabChange($(this));
              });
              
              handleTabChange($('.slider-tabs .active'));
              
              function handleTabChange(tab) {
                var nav = tab.closest('.nav');
                $('.indicator', nav).css({
                  width: tab.outerWidth(),
                  left: tab.position().left
                });
                tab.siblings().removeClass('active');
                tab.addClass('active');
              }
              .slider-tabs.nav {
                position: relative;
                margin: 10px;
              }
              
              .slider-tabs.nav .nav-link.active {
                background: transparent !important;
                color: #8b076e;
              }
              
              .slider-tabs.nav .indicator {
                position: absolute;
                top: 100%;
                min-width: 0;
                width: 0;
                height: 5px;
                background: red;
                transition: left .3s, width .3s;
              }
              <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
              <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
              
              <nav class="nav nav-pills slider-tabs">
                <a class="text-sm-center nav-link active" href="#">Active</a>
                <a class="text-sm-center nav-link" href="#">Products</a>
                <a class="text-sm-center nav-link" href="#">Services</a>
                <a class="text-sm-center nav-link" href="#">Link</a>
                <a class="text-sm-center nav-link disabled" href="#">Disabled</a>
                <div class="indicator"></div>
              </nav>

              【讨论】:

                猜你喜欢
                • 2020-06-23
                • 2021-11-27
                • 2023-02-14
                • 1970-01-01
                • 2020-07-12
                • 2017-10-06
                • 1970-01-01
                • 1970-01-01
                • 2015-12-25
                相关资源
                最近更新 更多