沿矩形边框的进度条 [英] Progress bar along the borders of a rectangle

查看:109
本文介绍了沿矩形边框的进度条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想弄清楚如何在矩形周围实现进度条。让我们来形容一下我的div 500x300带有5px(黑色)边框。



我希望进度条从左上角开始,然后转到 - >右角 - > bottom - 右角 - >左下角 - >并返回起点。



解决方案

纯CSS:



使用多个线性渐变作为背景并适当地定位它们。方法如下:




  • 为每个创建4个薄的线性渐变元素的边框。边框的粗细确定 background-size 。也就是说,如果边框厚度为5px,那么产生顶部和底部边框的线性渐变将是 100%5px (100%宽度5px高度),而生成左和右边框将是 5px 100%(3px width 100%height)。

  • 最初 设置为不会显示任何边框。在动画期间,我们将每个背景渐变动画化到其正确的位置。


  • 我在下面的代码段中使用了CSS关键帧,所以它自动从开始到结束结束(也就是说,它只有在完整的边框被绘后停止),但是如果你想对它进行更多的控制(并说,在进度条中途停止它),那么你可以使用JS和修改 background



      .progress {height:300px; width:500px;背景:线性梯度(到右,黑99.99%,透明),线性梯度(到底部,黑99.99%,透明),线性梯度(到右,黑99.99%,透明) ,黑色99.99%,透明); background-size:100%5px,5px 100%,100%5px,5px 100%;背景重复:无重复;动画:进步4s线性前进; background-position:-500px 0px,495px -300px,500px 295px,0px 300px;} @ keyframes progress {0%{background-position:-500px 0px,495px -300px,500px 295px,0px 300px; } 25%{background-position:0px 0px,495px -300px,500px 295px,0px 300px; } 50%{background-position:0px 0px,495px 0px,500px 295px,0px 300px; } 75%{background-position:0px 0px,495px 0px,0px 295px,0px 300px; } 100%{background-position:0px 0px,495px 0px,0px 295px,0px 0px; }}  

     <! -  prefix free library is only避免浏览器前缀 - >< script src =https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js>< / script>< div class =progress>< / div>  






    没有自动动画的CSS版本

    这是接受输入的代码段的CSS版本百分比值并基于此设置边框。在文本框中输入0到100之间的值,然后点击Enter。



      window.onload = function(){var progress = document.querySelector('。progress'),totalLength =(progress.offsetWidth * 2)+(progress.offsetHeight * 2); var btn = document.querySelector('#enter'),progressVal = document.querySelector('#progress'); btn.addEventListener('click',function(){input =(progressVal.value> 100)?100:progressVal.value; borderLen =(input / 100)* totalLength; console.log(borderLen); if ; = progress.offsetWidth){backgroundPos ='background-position:'+(-500 + borderLen)+'px 0px,495px -300px,500px 295px,0px 300px'; progress.setAttribute('style',backgroundPos);} else if(borderLen< =(progress.offsetWidth + progress.offsetHeight)){backgroundPos ='background-position:0px 0px,495px'+(-300 +(borderLen  -  progress.offsetWidth))+'px,500px 295px, 0px 300px'; progress.setAttribute('style',backgroundPos);} else if(borderLen< =(progress.offsetWidth * 2 + progress.offsetHeight)){backgroundPos ='background-position:0px 0px,495px 0px, +(500  - (borderLen  -  progress.offsetWidth  -  progress.offsetHeight))+'px 295px,0px 300px'; progress.setAttribute('style',backgroundPos);} else {backgroundPos ='background-position:0px 0px,495px 0px,0px 295px,0px'+(300  - (borderLen  - (progress.offsetWidth * 2) -  progress.offsetHeight))+'px'; progress.setAttribute('style',backgroundPos); }});};  

      .progress {height:300px ; width:500px; margin-top:20px;背景:线性梯度(到右,黑99.99%,透明),线性梯度(到底部,黑99.99%,透明),线性梯度(到右,黑99.99%,透明) ,黑色99.99%,透明); background-size:100%5px,5px 100%,100%5px,5px 100%;背景重复:无重复; background-position:-500px 0px,495px -300px,500px 295px,0px 300px;}  

     <! - 前缀免费库只是为了避免浏览器前缀 - >< script src =https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7 /prefixfree.min.js\"> ;</script> ;<input id ='progress'type ='text'/>< button id ='enter'>设置进度< / button>< div class =progress>< / div>  






    使用SVG:



    使用SVG,方法如下:




    • 创建一个单独的路径元素,使其形成框的边框,并使用 getTotalLength()方法。

    • 设置 stroke-dasharray 的属性<$ c> / c> c> $ c> path ,以使路径最初不可见。

    • 通过修改 stroke-dashoffset



    再次,我使用动画自动触发从开始到结束的移动完成,但是如果你想要一个进度条效果,你可以删除动画,并根据进度的百分比设置偏移。



     window.onload = function(){var progress = document.querySelector('。progress path'); var borderLen = progress.getTotalLength()+ 5,offset = borderLen; progress.style.strokeDashoffset = borderLen; progress.style.strokeDasharray = borderLen +','+ borderLen; anim = window.requestAnimationFrame(progressBar); function progressBar(){offset  -  = 1; progress.style.strokeDashoffset = offset; Anim = window.requestAnimationFrame(progressBar); if(offset< 0)window.cancelAnimationFrame(anim); }};  

      .progress {height:300px; width:500px;}。progress svg {height:100%; width:100%;} path {stroke:black; stroke-width:5; fill:none;}  

     < div class = > < svg viewBox ='0 0 510 310'preserveAspectRatio ='none'> < path d ='M5,5 505,5 505,305 5,305 5,2.5'/> <! -  end是起点 - 笔划宽度/ 2  - > < / svg>< / div>  




    b

    不自动动画的SVG版本



    这是接受输入百分比值的代码段的SVG版本并基于此设置边界。在文本框中输入0到100之间的值,然后点击Enter。



      window.onload = function(){var progress = document.querySelector('。progress path'); var borderLen = progress.getTotalLength()+ 5,offset; progress.style.strokeDashoffset = borderLen; progress.style.strokeDasharray = borderLen +','+ borderLen; var btn = document.querySelector('#enter'),progressVal = document.querySelector('#progress'); btn.addEventListener('click',function(){input =(progressVal.value> 100)?100:progressVal.value; offsetToSet =(input / 100)* borderLen; console.log(borderLen  -  offsetToSet); progress。 style.strokeDashoffset = borderLen  -  offsetToSet;});};  

      .progress {height:300px; width:500px;}。progress svg {height:100%; width:100%;} path {stroke:black; stroke-width:5; fill:none;}  

     < input id ='progress 'type ='text'/>< button id ='enter'>设置进度< / button>< div class =progress < svg viewBox ='0 0 510 310'preserveAspectRatio ='none'> < path d ='M5,5 505,5 505,305 5,305 5,2.5'/> <! -  end是起点 - 笔划宽度/ 2  - > < / svg>< / div>  


    I'm trying to figure out how to implement progressbar around rectangle. Let's image that I have div 500x300 with 5px (black) border.

    I would like that progress bar started in left top corner then goes to -> right corner -> bottom - right corner -> left bottom corner -> and back on start point.

    解决方案

    Pure CSS:

    This effect can be achieved with CSS using multiple linear gradients as background and positioning them appropriately. The approach is as follows:

    • Create 4 thin linear-gradient backgrounds for each border of the element. The thickness of the border determines the background-size. That is, if border thickness is 5px then the linear gradients that produce the top and bottom borders would be 100% 5px (100% width 5px height) whereas those that produce left and right borders would be 5px 100% (3px width 100% height).
    • Initially the background-position is set such that none of the borders would be visible. During animation we animate each of the background gradients into its correct position. This produces the effect of having an animated border.

    I have used CSS keyframes in the below snippet and so it automatically animates from start to end (that is, it stops only after full border is painted) but if you wish to have more control over it (and say stop it midway as in a progress bar) then you could use JS and modify background-position based on the percentage of progress.

    .progress {
      height: 300px;
      width: 500px;
      background: linear-gradient(to right, black 99.99%, transparent), linear-gradient(to bottom, black 99.99%, transparent), linear-gradient(to right, black 99.99%, transparent), linear-gradient(to bottom, black 99.99%, transparent);
      background-size: 100% 5px, 5px 100%, 100% 5px, 5px 100%;
      background-repeat: no-repeat;
      animation: progress 4s linear forwards;
      background-position: -500px 0px, 495px -300px, 500px 295px, 0px 300px;
    }
    @keyframes progress {
      0% {
        background-position: -500px 0px, 495px -300px, 500px 295px, 0px 300px;
      }
      25% {
        background-position: 0px 0px, 495px -300px, 500px 295px, 0px 300px;
      }
      50% {
        background-position: 0px 0px, 495px 0px, 500px 295px, 0px 300px;
      }
      75% {
        background-position: 0px 0px, 495px 0px, 0px 295px, 0px 300px;
      }
      100% {
        background-position: 0px 0px, 495px 0px, 0px 295px, 0px 0px;
      }
    }

    <!-- prefix free library is only to avoid browser prefixes -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
    
    <div class="progress"></div>


    CSS version without automatic animation:

    Here is the CSS version of the snippet which accepts an input percentage value and sets the border based on that. Provide a value between 0 and 100 in the text box and click Enter.

    window.onload = function() {
      var progress = document.querySelector('.progress'),
        totalLength = (progress.offsetWidth * 2) + (progress.offsetHeight * 2);
    
      var btn = document.querySelector('#enter'),
        progressVal = document.querySelector('#progress');
    
      btn.addEventListener('click', function() {
        input = (progressVal.value > 100) ? 100 : progressVal.value;
        borderLen = (input / 100) * totalLength;
        console.log(borderLen);
        if (borderLen <= progress.offsetWidth) {
          backgroundPos = 'background-position: ' + (-500 + borderLen) + 'px 0px, 495px -300px, 500px 295px, 0px 300px';
          progress.setAttribute('style', backgroundPos);
        } else if (borderLen <= (progress.offsetWidth + progress.offsetHeight)) {
          backgroundPos = 'background-position: 0px 0px, 495px ' + (-300 + (borderLen - progress.offsetWidth)) + 'px, 500px 295px, 0px 300px';
          progress.setAttribute('style', backgroundPos);
        } else if (borderLen <= (progress.offsetWidth * 2 + progress.offsetHeight)) {
          backgroundPos = 'background-position: 0px 0px, 495px 0px, ' + (500 - (borderLen - progress.offsetWidth - progress.offsetHeight)) + 'px 295px, 0px 300px';
          progress.setAttribute('style', backgroundPos);
        } else {
          backgroundPos = 'background-position: 0px 0px, 495px 0px, 0px 295px, 0px ' + (300 - (borderLen - (progress.offsetWidth * 2) - progress.offsetHeight)) + 'px';
          progress.setAttribute('style', backgroundPos);
        }
      });
    };

    .progress {
      height: 300px;
      width: 500px;
      margin-top: 20px;
      background: linear-gradient(to right, black 99.99%, transparent), linear-gradient(to bottom, black 99.99%, transparent), linear-gradient(to right, black 99.99%, transparent), linear-gradient(to bottom, black 99.99%, transparent);
      background-size: 100% 5px, 5px 100%, 100% 5px, 5px 100%;
      background-repeat: no-repeat;
      background-position: -500px 0px, 495px -300px, 500px 295px, 0px 300px;
    }

    <!-- prefix free library is only to avoid browser prefixes -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
    <input id='progress' type='text' />
    <button id='enter'>Set Progress</button>
    <div class="progress"></div>


    With SVG:

    With SVG, the approach would be as follows:

    • Create a single path element such that it forms the border of the boxand get its length using the getTotalLength() method.
    • Set the stroke-dasharray and stroke-dashoffset properties of the path such that the path is invisible initially.
    • By modifying the stroke-dashoffset based on the percentage of progress we can produce a progress bar like effect.

    Again I have used animations to automatically trigger the movement from start to finish but if you want a progress bar like effect, you can remove the animation and just set the offset based on percentage of progress.

    window.onload = function() {
      var progress = document.querySelector('.progress path');
      var borderLen = progress.getTotalLength() + 5,
        offset = borderLen;
      progress.style.strokeDashoffset = borderLen;
      progress.style.strokeDasharray = borderLen + ',' + borderLen;
      anim = window.requestAnimationFrame(progressBar);
    
      function progressBar() {
        offset -= 1;
        progress.style.strokeDashoffset = offset;
        anim = window.requestAnimationFrame(progressBar);
        if (offset < 0)
          window.cancelAnimationFrame(anim);
      }
    };

    .progress {
      height: 300px;
      width: 500px;
    }
    .progress svg {
      height: 100%;
      width: 100%;
    }
    path {
      stroke: black;
      stroke-width: 5;
      fill: none;
    }

    <div class="progress">
      <svg viewBox='0 0 510 310' preserveAspectRatio='none'>
        <path d='M5,5 505,5 505,305 5,305 5,2.5' />
        <!-- end is start point - stroke width/2 -->
      </svg>
    </div>


    SVG version without automatic animation:

    Here is the SVG version of the snippet which accepts an input percentage value and sets the border based on that. Provide a value between 0 and 100 in the text box and click Enter.

    window.onload = function() {
      var progress = document.querySelector('.progress path');
      var borderLen = progress.getTotalLength() + 5,
        offset;
      progress.style.strokeDashoffset = borderLen;
      progress.style.strokeDasharray = borderLen + ',' + borderLen;
      
      var btn = document.querySelector('#enter'),
          progressVal = document.querySelector('#progress');
        
        btn.addEventListener('click', function(){
            input = (progressVal.value > 100) ? 100 : progressVal.value;
            offsetToSet = (input/100) * borderLen;
            console.log(borderLen - offsetToSet);
            progress.style.strokeDashoffset = borderLen - offsetToSet;
        });
    };

    .progress {
      height: 300px;
      width: 500px;
    }
    .progress svg {
      height: 100%;
      width: 100%;
    }
    path {
      stroke: black;
      stroke-width: 5;
      fill: none;
    }

    <input id='progress' type='text'/>
    <button id='enter'>Set Progress</button>
    <div class="progress">
      <svg viewBox='0 0 510 310' preserveAspectRatio='none'>
        <path d='M5,5 505,5 505,305 5,305 5,2.5' />
        <!-- end is start point - stroke width/2 -->
      </svg>
    </div>

    这篇关于沿矩形边框的进度条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆