代码之家  ›  专栏  ›  技术社区  ›  iceiceicy

两个容器之间的自定义形状线,其颜色类似于进度条。

  •  1
  • iceiceicy  · 技术社区  · 6 年前

    enter image description here

    基于上面的图片,我想实现的是:

    1. 一旦容器到达视区的中间,其文本背景将变为黄色。
    2. 另外,当用户向下或向上滚动时,中间的箭头将慢慢地填充黄色,直到用户到达下一个容器的中间视区。

    现在,我设法使焦点容器将其文本背景更改为黄色,并且我已经显示了进度条形状,但我不知道 如何在用户滚动操作(如进度条)中将其更改为黄色。另外,第一个进度条需要从右开始,而第二个进度条将从左开始,反之亦然。

    P/S:我正在考虑只使用图像,但是为了确保像进度条一样将其变为黄色是不可能的。

    $(document).ready(function() {
        var winHeight = $(window).height(),
            topLimit = winHeight * .2;
    
        $(window).on('scroll', function() {
            $('.parent').each(function() {
                var thisTop = $(this).offset().top - $(window).scrollTop();
                if (thisTop <= topLimit) {
                    $(this).addClass('highlight');
                } else {
                    $(this).removeClass('highlight');
                }
            });
        });
    });
    .parent {
      margin-top: 50px;
      height: 250px;
    }
    
    .img-col {
      width: 50%;
      height: 250px;
      background-color: green; 
      float:left;
    }
    
    .text-col {
      width: 50%;
      height: 250px;
      background-color: blue; 
      float: right;
    }
    
    .highlight .text-col {
      background-color: yellow;
    }
    
    .middle-line {
      height: 1px;
      width: 100%;
      position: relative;
      background: #000;
      margin-top: 50px;
    }
    
    .vertical-right {
      height: 20px;
      width: 1px;
      background: #000;
      position: absolute;
      right: 0;
      bottom: 0;
    }
    
    .vertical-left {
      height: 20px;
      width: 1px;
      background: #000;
      position: absolute;
      left: 0;
      top: 0;
    }
    
    .vertical-right-bottom {
      height: 20px;
      width: 1px;
      background: #000;
      position: absolute;
      right: 0;
      top: 0;
    }
    
    .vertical-left-top {
      height: 20px;
      width: 1px;
      background: #000;
      position: absolute;
      left: 0;
      bottom: 0;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <html>
    <body>
    <div class="parent">
        <div class="img-col"></div>
        <div class="text-col">Some text here</div>
    </div>
    
    <div class="middle-line">
      <div class="vertical-right"></div>
      <div class="vertical-left"></div>
    </div>
    
    <div class="parent">
        <div class="text-col" style="float: left;">Some text here</div>
        <div class="img-col" style="float: right;"></div>
    </div>
    
    <div class="middle-line">
      <div class="vertical-right-bottom"></div>
      <div class="vertical-left-top"></div>
    </div>
    
    <div class="parent">
        <div class="img-col"></div>
        <div class="text-col">Some text here</div>
    </div>
    
    <div class="middle-line">
      <div class="vertical-right"></div>
      <div class="vertical-left"></div>
    </div>
    
    <div class="parent">
        <div class="text-col" style="float: left;">Some text here</div>
        <div class="img-col" style="float: right;"></div>
    </div>
    
    <div class="parent"></div>
    </body>
    </html>
    3 回复  |  直到 6 年前
        1
  •  4
  •   jla    6 年前

    文本背景更改

    当文本背景到达视区中心时,改变它是相对简单的,并且可以用一些精心构建的CSS类和一点javascript来完成。

    主列表中的每个项目都有几个组件,包括几个需要更改背景颜色的文本框。我们在每个文本框中添加一个类-我们称之为 .colour-animate . 在我们的CSS中,我们添加了 transition 属性使动画平滑淡出。

    .colour-animate {
        transition: background-color 0.3s;
    }
    

    现在是javascript。

    如果主列表中的每个项都有类名 .item 我们可以遍历 item s并检查每个都是否在视区中心上方。这是一个简单的计算:

    if ( items[ i ].getBoundingClientRect().top < ( window.innerHeight / 2 ) ) {
        // do stuff
    }
    

    如果是这样,那么我们将遍历 彩色动画 那个孩子 项目 . 对于每一个 彩色动画 我们可以改变背景色。对于每一个 项目 在视区中心下方,我们重置了它的背景色。 .彩色动画 孩子们。这意味着如果我们向上滚动页面,黄色将重置。

    背景更改的完整代码:

    var items = document.getElementsByClassName( "item" );
    
    function scroll() {
        for ( var i = 0; i < items.length; i++ ) {
            var colours = items[ i ].getElementsByClassName( "colour-animate" );
            if ( items[ i ].getBoundingClientRect().top < ( window.innerHeight / 2 ) ) {
              for ( var j = 0; j < colours.length; j++ ) {
                colours[ j ].style.backgroundColor = "rgba( 255,208,0,0.7 )";
               }
            } else {
               for ( var j = 0; j < colours.length; j++ ) {
                colours[ j ].style.backgroundColor = "";
               }
            }
        }
    }
    
    
    window.onscroll = function () {
        window.requestAnimationFrame(scroll); 
    } 
    window.onload = scroll();
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
        background-color: #111;
        padding: 50px;
    }
    .item {
        background-image: url( https://upload.wikimedia.org/wikipedia/en/f/f7/Leger_railway_crossing.jpg );
        background-size: cover;
        position: relative;
        display: flex;
        justify-content: flex-start;
        margin: 40px auto;
    }
    .item.right {
        justify-content: flex-end;
    }
    .item .description {
        width: 33%;
        padding: 30px;
        color: #fff;
        background-color: rgba( 0,0,0,0.7);
    }
    .item .header {
        font-size: 150%;
        position: absolute;
        top: 0;
        left: auto;
        right: 0;
        padding: 10px 50px;
        color: #fff;
        background-color: #000;
    }
    .item .header.left {
        left: 0;
        right: auto;
    }
    .colour-animate {
        transition: background-color 0.3s;
    }
    <div class="item">
        <div class="header colour-animate">Title 1</div>
        <div class="description colour-animate">
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet ante malesuada, aliquam libero sit amet, varius lectus.</p>
        </div>
    </div>
    
    <div class="item right">
        <div class="header colour-animate left">Title 2</div>
        <div class="description colour-animate">
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet ante malesuada, aliquam libero sit amet, varius lectus.</p>
        </div>
    </div>
    
    <div class="item">
        <div class="header colour-animate">Title 3</div>
        <div class="description colour-animate">
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet ante malesuada, aliquam libero sit amet, varius lectus.</p>
        </div>
    </div>
    
    <div class="item right">
        <div class="header colour-animate left">Title 4</div>
        <div class="description colour-animate">
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet ante malesuada, aliquam libero sit amet, varius lectus.</p>
        </div>
    </div>
    
    <div class="item">
        <div class="header colour-animate">Title 5</div>
        <div class="description colour-animate">
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet ante malesuada, aliquam libero sit amet, varius lectus.</p>
        </div>
    </div>

    设置箭头分隔符的动画

    在滚动时设置箭头图形的动画是一个非常有趣的问题。它可能最好用CSS SVG来解决。

    首先将箭头绘制为SVG向量。您可以在向量编辑器中执行此操作,或者因为它是一个非常简单的图形,所以手动执行此操作可能更容易。您的SVG代码如下所示:

    <svg width="100%" height="100px" viewBox="0 0 1000 100" preserveAspectRatio="none">
        <path fill="none" stroke="#ffffff" stroke-width="2" d="M01000 0 L1000 50 L500 50 L 510 30 L510 70 L500 50 L 0 50 L0 100" />
    </svg>
    

    如前所述,只使用路径绘制非常重要。

    现在要在滚动时设置黄色的动画,需要绘制与第一条相同的第二条路径,但它是黄色的。并为它添加一个新的类名-假设您使用 .scroll-animate . 您的完整SVG可能如下所示:

    <svg width="100%" height="100px" viewBox="0 0 1000 100" preserveAspectRatio="none">
         <path fill="none" stroke="#ffffff" stroke-width="2" d="M01000 0 L1000 50 L500 50 L 510 30 L510 70 L500 50 L 0 50 L0 100" />
         <path fill="none" stroke="#ffd000" stroke-width="2" d="M01000 0 L1000 50 L500 50 L 510 30 L510 70 L500 50 L 0 50 L0 100" class="scroll-animate" />
    </svg>
    

    有一篇精彩的小文章在 CSS Tricks 这解释了如何设置SVG路径的动画。基本上你可以用 .getTotalLength() 做你的 滚动动画 路径的笔划-短划线长度等于该长度。这意味着您可以通过将路径的笔划偏移量从该长度设置为0来从开始到结束滑动路径。要将此附加到滚动,我们将使笔划偏移等于路径的长度乘以视区中路径的滚动位置除以视区高度。

    var paths = document.getElementsByClassName( "scroll-animate" ),
        length = paths[ 0 ].getTotalLength();
    
    function scroll() {
        for ( var i = 0; i < paths.length; i++ ) {
            paths[ i ].style.strokeDashoffset = length * ( paths[ i ].getBoundingClientRect().top / window.innerHeight );
        }
    }
    
    window.onscroll = function () {
        window.requestAnimationFrame(scroll); 
    }
    

    这不仅会在向下滚动时使黄色箭头成为动画,而且会在向上滚动时使其反转。

    结果

    完整的代码(或者您可以查看 codepen 其中:

    var items = document.getElementsByClassName( "item" ),
        paths = document.getElementsByClassName( "scroll-animate" ),
        length = paths[ 0 ].getTotalLength();
    
    for ( var i = 0; i < paths.length; i++ ) {
        paths[ i ].style.strokeDasharray = length;
        paths[ i ].style.strokeDashoffset = length;
    }
    
    function scroll() {
        for ( var i = 0; i < items.length; i++ ) {
            var colours = items[ i ].getElementsByClassName( "colour-animate" );
            if ( items[ i ].getBoundingClientRect().top < ( window.innerHeight / 2 ) ) {
              for ( var j = 0; j < colours.length; j++ ) {
                colours[ j ].style.backgroundColor = "rgba( 255,208,0,0.7 )";
               }
            } else {
               for ( var j = 0; j < colours.length; j++ ) {
                colours[ j ].style.backgroundColor = "";
               }
            }
        }
        
        for ( var i = 0; i < paths.length; i++ ) {
            paths[ i ].style.strokeDashoffset = length * ( paths[ i ].getBoundingClientRect().top / window.innerHeight );
        }
    }
    
    
    window.onscroll = function () {
        window.requestAnimationFrame(scroll); 
    } 
    window.onload = scroll();
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
        background-color: #111;
        padding: 50px;
    }
    .item {
        background-image: url( https://upload.wikimedia.org/wikipedia/en/f/f7/Leger_railway_crossing.jpg );
        background-size: cover;
        position: relative;
        display: flex;
        justify-content: flex-start;
        margin: 10px auto;
    }
    .item.right {
        justify-content: flex-end;
    }
    .item .description {
        width: 33%;
        padding: 30px;
        color: #fff;
        background-color: rgba( 0,0,0,0.7);
    }
    .item .header {
        font-size: 150%;
        position: absolute;
        top: 0;
        left: auto;
        right: 0;
        padding: 10px 50px;
        color: #fff;
        background-color: #000;
    }
    .item .header.left {
        left: 0;
        right: auto;
    }
    .colour-animate {
        transition: background-color 0.3s;
    }
    <div class="item">
        <div class="header colour-animate">Title 1</div>
        <div class="description colour-animate">
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet ante malesuada, aliquam libero sit amet, varius lectus.</p>
        </div>
    </div>
    
    <svg width="100%" height="100px" viewBox="0 0 1000 100" preserveAspectRatio="none">
       <path fill="none" stroke="#ffffff" stroke-width="2" d="M01000 0 L1000 50 L500 50 L 510 30 L510 70 L500 50 L 0 50 L0 100" />
        <path fill="none" stroke="#ffd000" stroke-width="2" d="M01000 0 L1000 50 L500 50 L 510 30 L510 70 L500 50 L 0 50 L0 100" class="scroll-animate" />
    </svg>
    
    <div class="item right">
        <div class="header colour-animate left">Title 2</div>
        <div class="description colour-animate">
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet ante malesuada, aliquam libero sit amet, varius lectus.</p>
        </div>
    </div>
    
    <svg width="100%" height="100px" viewBox="0 0 1000 100" preserveAspectRatio="none">
       <path fill="none" stroke="#ffffff" stroke-width="2" d="M01000 0 L1000 50 L500 50 L 510 30 L510 70 L500 50 L 0 50 L0 100" />
        <path fill="none" stroke="#ffd000" stroke-width="2" d="M01000 0 L1000 50 L500 50 L 510 30 L510 70 L500 50 L 0 50 L0 100" class="scroll-animate" />
    </svg>
    
    <div class="item">
        <div class="header colour-animate">Title 3</div>
        <div class="description colour-animate">
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet ante malesuada, aliquam libero sit amet, varius lectus.</p>
        </div>
    </div>
    
    <svg width="100%" height="100px" viewBox="0 0 1000 100" preserveAspectRatio="none">
       <path fill="none" stroke="#ffffff" stroke-width="2" d="M01000 0 L1000 50 L500 50 L 510 30 L510 70 L500 50 L 0 50 L0 100" />
        <path fill="none" stroke="#ffd000" stroke-width="2" d="M01000 0 L1000 50 L500 50 L 510 30 L510 70 L500 50 L 0 50 L0 100" class="scroll-animate" />
    </svg>
    
    <div class="item right">
        <div class="header colour-animate left">Title 4</div>
        <div class="description colour-animate">
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet ante malesuada, aliquam libero sit amet, varius lectus.</p>
        </div>
    </div>
    
    <svg width="100%" height="100px" viewBox="0 0 1000 100" preserveAspectRatio="none">
       <path fill="none" stroke="#ffffff" stroke-width="2" d="M01000 0 L1000 50 L500 50 L 510 30 L510 70 L500 50 L 0 50 L0 100" />
        <path fill="none" stroke="#ffd000" stroke-width="2" d="M01000 0 L1000 50 L500 50 L 510 30 L510 70 L500 50 L 0 50 L0 100" class="scroll-animate" />
    </svg>
    
    <div class="item">
        <div class="header colour-animate">Title 5</div>
        <div class="description colour-animate">
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sit amet ante malesuada, aliquam libero sit amet, varius lectus.</p>
        </div>
    </div>
        2
  •  1
  •   Twisty    6 年前

    可能有很多方法可以做到这一点。带有透明部分的图像。带边框颜色或简单边距的智能CSS用法。我不确定什么是最好的,因为我们不使用实际的代码,但在这一点上更多的是一个模型。

    考虑以下内容。

    $(function() {
      var winHeight = $(window).height(),
        topLimit = winHeight * .2;
    
      $(window).on('scroll', function() {
        $('.parent').each(function() {
          var thisTop = $(this).offset().top - $(window).scrollTop();
          if (thisTop <= topLimit) {
            $(this).addClass('highlight');
          } else {
            $(this).removeClass('highlight');
          }
        });
        $(".line-wrap").each(function() {
          var thisTop = $(this).offset().top - $(window).scrollTop();
          if (thisTop <= topLimit) {
            if ($(".mid-line", this).hasClass("top-right")) {
              $(this).css("background-image", "linear-gradient(to right, rgba(255,255,0,0), rgba(255,255,0,1))");
            } else {
              $(this).css("background-image", "linear-gradient(to left, rgba(255,255,0,0), rgba(255,255,0,1))");
            }
          } else {
            $(this).css("background-image", "");
          }
        });
      });
    });
    .content {
      padding: 0;
      margin: 0;
      background: #000;
    }
    
    .parent {
      margin-top: 50px;
      height: 250px;
      background-color: black;
    }
    
    .img-col {
      width: 50%;
      height: 250px;
      background-color: black;
      float: left;
    }
    
    .text-col {
      width: 50%;
      height: 250px;
      background-color: blue;
      float: right;
    }
    
    .highlight .text-col {
      background-color: yellow;
    }
    
    .line-wrap {
      /* Line Color */
      background: #FFF;
    }
    
    .mid-line {
      /* Spacing and Borders */
      height: 19px;
      width: calc(100% - 1px);
      background: black;
      border: 0;
    }
    
    .top-right {
      /* Verticals Sides */
      margin-top: 50px;
      margin-right: 1px;
      margin-bottom: 1px;
    }
    
    .top-left {
      /* Verticals Sides */
      margin-top: 50px;
      margin-left: 1px;
      margin-bottom: 1px;
    }
    
    .bottom-left {
      margin-left: 1px;
    }
    
    .bottom-right {
      margin-right: 1px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div class="content">
      <div class="parent">
        <div class="img-col"></div>
        <div class="text-col">Some text here</div>
      </div>
    
      <div class="line-wrap">
        <div class="mid-line top-right">
        </div>
        <div class="mid-line bottom-left">
        </div>
      </div>
    
      <div class="parent">
        <div class="text-col" style="float: left;">Some text here</div>
        <div class="img-col" style="float: right;"></div>
      </div>
    
      <div class="line-wrap">
        <div class="mid-line top-left">
        </div>
        <div class="mid-line bottom-right">
        </div>
      </div>
    
      <div class="parent">
        <div class="img-col"></div>
        <div class="text-col">Some text here</div>
      </div>
    
      <div class="line-wrap">
        <div class="mid-line top-right">
        </div>
        <div class="mid-line bottom-left">
        </div>
      </div>
    
      <div class="parent">
        <div class="text-col" style="float: left;">Some text here</div>
        <div class="img-col" style="float: right;"></div>
      </div>
    
      <div class="parent"></div>
    </div>

    使用相同的进度代码,您可以只为不同的背景着色。我认为有点CSS的风格可能是不错的,因此透明的梯度背景。如果你想做更多的步骤,让梯度改变或者增长,你只需要把滚动动作切成更多的薄片。

    希望有帮助。

        3
  •  1
  •   simboonlong    6 年前

    $(document).ready(function() {
        var winHeight = $(window).height(),
            topLimit = winHeight * .2;
    
        $(window).on('scroll', function() {
            $('.parent').each(function() {
                var thisTop = $(this).offset().top - $(window).scrollTop();
                if (thisTop <= topLimit) {
                    $(this).addClass('highlight');
                    $(this).next('.middle-line').addClass('is-active');
                } else {
                    $(this).removeClass('highlight');
                    $(this).next('.middle-line').removeClass('is-active');
                }
            });
        });
    });
    .parent {
      margin-top: 50px;
      height: 250px;
    }
    
    .img-col {
      width: 50%;
      height: 250px;
      background-color: green; 
      float:left;
    }
    
    .text-col {
      width: 50%;
      height: 250px;
      background-color: blue; 
      float: right;
    }
    
    .highlight .text-col {
      background-color: yellow;
    }
    
    .middle-line.is-active::before,
    .middle-line.is-active::after {
      width: 50%;
    }
    
    .middle-line.is-active .vertical-bottom,
    .middle-line.is-active .vertical-top {
      height: 20px;
    }
    
    .middle-line.is-active::before {
      transition: width 0.2s 0.2s ease-in;
    }
    
    .middle-line.is-active::after {
      transition: width 0.2s 0.4s ease-out;
    }
    
    .middle-line.is-active .vertical-bottom {
      transition: height 0.2s 0.6s ease-out;
    }
    
    .middle-line.is-active .vertical-top {
      transition: height 0.2s ease-in;
    }
    
    .middle-line {
      height: 1px;
      width: 100%;
      position: relative;
      margin-top: 50px;
    }
    
    .middle-line::before,
    .middle-line::after {
      content: '';
      position: absolute;
      background: #000;
      height: 100%;
      width: 0;
    }
    
    .middle-line::before {
      transition: width 0.2s 0.4s ease-out;
      right: 0;
    }
    
    .middle-line::after {
      transition: width 0.2s 0.2s ease-in;
    
      right: 50%;
    }
    
    .middle-line.alternate::before {
      left: 0;
    }
    
    .middle-line.alternate::after {
      left: 50%;
    }
    
    .middle-line.alternate .vertical-top {
      left: 0;
      right: auto;
    }
    
    .middle-line.alternate .vertical-bottom {
      left: auto;
      right: 0;
    }
    
    .vertical-top {
      transition: height 0.2s 0.6s ease-out;
      height: 0;
      width: 1px;
      background: #000;
      position: absolute;
      top: -20px;
      right: 0;
      bottom: 0;
    }
    
    .vertical-bottom {
      transition: height 0.2s ease-in;
      height: 0;
      width: 1px;
      background: #000;
      position: absolute;
      left: 0;
      top: 0;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <html>
    <body>
    <div class="parent">
        <div class="img-col"></div>
        <div class="text-col">Some text here</div>
    </div>
    
    <div class="middle-line">
      <div class="vertical-top"></div>
      <div class="vertical-bottom"></div>
    </div>
    
    <div class="parent">
        <div class="text-col" style="float: left;">Some text here</div>
        <div class="img-col" style="float: right;"></div>
    </div>
    
    <div class="middle-line alternate">
      <div class="vertical-top"></div>
      <div class="vertical-bottom"></div>
    </div>
    
    <div class="parent">
        <div class="img-col"></div>
        <div class="text-col">Some text here</div>
    </div>
    
    <div class="middle-line">
      <div class="vertical-top"></div>
      <div class="vertical-bottom"></div>
    </div>
    
    <div class="parent">
        <div class="text-col" style="float: left;">Some text here</div>
        <div class="img-col" style="float: right;"></div>
    </div>
    
    <div class="middle-line alternate">
        <div class="vertical-top"></div>
        <div class="vertical-bottom"></div>
    </div>
    
    <div class="parent"></div>
    </body>
    </html>

    我已经编辑了您的标记,并通过CSS管理动画。