进度条由实线组成,点为步骤

时间:2015-09-28 14:14:07

标签: html css css3 svg css-shapes

我正在尝试创建一个垂直进度条,实线上有8个点(结尾处是第8个),其中每个点代表该过程中的一个步骤。请参阅随附的屏幕截图(在底部以防止此问题被分解)。

当然,我尝试用HTML和CSS制作一些东西,你可以在this fiddle(下面的代码)中看到。问题是,我找不到在浅绿线上创建7个点的方法,而不添加8个div(8个因为第一个也必须在那里)。

功能方面,我希望JS检查value - div的progressNow,将它多重显示100,并将其作为CSS高度添加到progressNow - 类。问题在于点会移动,而不是条形填充。 (这有意义吗?)

这让我想到了在屏幕截图中可以看到的形状创建一个SVG元素,它具有一个基于过程中第n步改变位置的渐变。我知道这会起作用,我知道我可以让它工作,但我想知道是否还有另一种,也许更容易实现我想要实现的目标。

HTML

<div id="progress">
    <div class="progressBar"></div>
    <div class="progressNow" value="1"></div>
    <div class="progressTotal"></div>
</div>

CSS

#progress {
    position: relative;
}

#progress .progressBar {
    height: 800px;
    width: 6px;
    background: #8fe4bf;
    position: absolute;
}

#progress .progressNow {
    height: 100px;
    width: 6px;
    background: #00b164;
    position: absolute;
}

#progress .progressNow::after {
    content: "";
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: #00b164;
    display: block;
    margin-left: -5px;
    position: absolute;
    top: 90px;
}

期望的结果(在这种情况下,value的{​​{1}}为progressNow

enter image description here

6 个答案:

答案 0 :(得分:11)

我的解决方案与@ Stewartside类似,不过它使用Flexbox来平等地定位所有内容。改变高度也很容易。

&#13;
&#13;
ul.progress-bar {
  height: 300px;
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  overflow: hidden;
}
ul.progress-bar::after {
  content: "";
  position: absolute;
  top: 0;
  left: 5px;
  background: #777;
  width: 5px;
  height: 100vh;
}
ul.progress-bar li {
  background: #000;
  border-radius: 100px;
  width: 15px;
  height: 15px;
  z-index: 1;
  position: relative;
}
ul.progress-bar li.stop ~ li {
  background: #777;
}
ul.progress-bar li.stop ~ li::after {
  height: 0;
}
ul.progress-bar li::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 5px;
  background: #000;
  width: 5px;
  height: 100vh;
}
&#13;
<ul class="progress-bar">
    <li>
    <li>
    <li>
    <li class="stop">
    <li>
</ul>
&#13;
&#13;
&#13;

出于某种原因,底部片段似乎没有显示在stacksnippet中,因此它位于jsfiddle上。

答案 1 :(得分:9)

这是一个非常小的编号的CSS解决方案。元素。在这种方法中,我们使用linear-gradientsradial-gradients的组合来生成垂直线和点。

#progress-bar元素生成lightgreen(初始)行和圆圈,同时将相同的渐变添加到子#progress-now元素,该元素相对于父元素绝对定位。唯一的区别是height元素的#progress-now是基于value属性确定的。

即使值是分数,解决方案也会起作用。我知道你正在使用它作为步跟踪器,但这只是一个额外的用途(吹我自己的小号:D)。

window.onload = function() {
  var val = document.getElementById('progress-now').getAttribute('value');
  var progress = (val * 50 > 400) ? 400 : val*50; /* 50 is 1/8th of height, 400 is height */
  document.getElementById('progress-now').setAttribute('style', 'height: ' + progress + 'px');
}
#progress-bar {
  position: relative;
  height: 400px;
  width: 200px;
  background: linear-gradient(to bottom, lightgreen 99.9%, transparent 99.9%), radial-gradient(circle at 50% 50%, lightgreen 25%, transparent 30%);
  background-position: 50% 0%, 50% 15px; /* 15px is 30% of 50px */
  background-size: 5px 100%, 50px 50px; /* 5px is the thickness of the bar, 50px is 1/8th of the height */
  background-repeat: no-repeat, repeat-y;
}
#progress-now {
  position: absolute;
  width: 200px;
  background: linear-gradient(to bottom, darkgreen 99.9%, transparent 99.9%), radial-gradient(circle at 50% 50%, darkgreen 25%, transparent 30%);
  background-position: 50% 0%, 50% 15px;
  background-size: 5px 100%, 50px 50px;
  background-repeat: no-repeat, repeat-y;
  z-index: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id='progress-bar'>
  <div id='progress-now' value='1.85'></div>
</div>

以下是填充动画效果的版本。

window.onload = function() {
  var val = 0, progress = 0;

  function progressBar() {
    val += 0.005;
    progress = (val * 50 > 400) ? 400 : val * 50; /* 50 is 1/8th of height, 400 is height */
    document.getElementById('progress-now').setAttribute('style', 'height: ' + progress + 'px');
    if (val <= 8) anim = window.requestAnimationFrame(progressBar);
  }
  
  progressBar();
}
#progress-bar {
  position: relative;
  height: 400px;
  width: 200px;
  background: linear-gradient(to bottom, lightgreen 99.9%, transparent 99.9%), radial-gradient(circle at 50% 50%, lightgreen 25%, transparent 30%);
  background-position: 50% 0%, 50% 15px; /* 15px is 30% of 50px */
  background-size: 5px 100%, 50px 50px; /* 5px is the thickness of the bar, 50px is 1/8th of the height */
  background-repeat: no-repeat, repeat-y;
}
#progress-now {
  position: absolute;
  width: 200px;
  background: linear-gradient(to bottom, darkgreen 99.9%, transparent 99.9%), radial-gradient(circle at 50% 50%, darkgreen 25%, transparent 30%);
  background-position: 50% 0%, 50% 15px;
  background-size: 5px 100%, 50px 50px;
  background-repeat: no-repeat, repeat-y;
  z-index: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div id='progress-bar'>
  <div id='progress-now'></div>
</div>

答案 2 :(得分:6)

CSS

我的CSS解决方案基于多个div,允许您拥有任意数量的内容并确定完成的数量。

.complete {
  width: 5px;
  height: 50px;
  position: relative;
  background: green;
  margin-left: 8px;
}
.complete:after {
  content: '';
  width: 20px;
  height: 20px;
  border-radius: 50%;
  position: absolute;
  bottom: -7.5px;
  left: -8px;
  background: green;
  z-index: 100;
}
.not_complete {
  width: 5px;
  height: 50px;
  background: lightgreen;
  position: relative;
  margin-left: 8px;
}
.not_complete:after {
  content: '';
  width: 20px;
  height: 20px;
  border-radius: 50%;
  position: absolute;
  bottom: -7.5px;
  left: -8px;
  background: lightgreen;
  z-index: 100;
}
<div class="progress">
  <div class="complete"></div>
  <div class="complete"></div>
  <div class="not_complete"></div>
  <div class="not_complete"></div>
  <div class="not_complete"></div>
  <div class="not_complete"></div>
  <div class="not_complete"></div>
  <div class="not_complete"></div>
</div>

SVG

这也可以使用SVG g元素并将其与不同的填充一起使用。

请记住,SVG的高度需要与放在一起的所有元素相同或更大。

<svg width="20" height="445" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <g id="completed">
      <line x1="0" y1="5" x2="0" y2="40" style="stroke:green;stroke-width:3;" />
      <circle style="fill:green; stroke-width:0;" cx="0" cy="50" r="10" />
    </g>
    <g id="not_complete">
      <line x1="0" y1="5" x2="0" y2="40" style="stroke:lightgreen;stroke-width:3;" />
      <circle style="fill:lightgreen; stroke-width:0;" cx="0" cy="50" r="10" />
    </g>
  </defs>

  <use x="10" y="00" xlink:href="#completed" />
  <use x="10" y="55" xlink:href="#completed" />
  <use x="10" y="110" xlink:href="#not_complete" />
  <use x="10" y="165" xlink:href="#not_complete" />
  <use x="10" y="220" xlink:href="#not_complete" />
  <use x="10" y="275" xlink:href="#not_complete" />
  <use x="10" y="330" xlink:href="#not_complete" />
  <use x="10" y="385" xlink:href="#not_complete" />
</svg>

答案 3 :(得分:5)

你可以使用box-shadow来实现这种效果。这可以使用单个元素来实现,因为它使用box-shadow但是使用javascript很难改变颜色

注意:我使用jquery仅显示向进度条添加更多内容的效果 单击正文上的任意位置以查看结果

$('body').click(function () {
    var x = parseInt($('.progressNow').css('top')) + 10;
    $('.progressNow').css({
        top: x
    })
    if (x > 90 - 800) {      $('.circle').css('background','#00b164')
    }
    if(x > 180 -800){
        $('.circle').css('box-shadow','0 90px 0 0 #00b164, 0 180px 0 0 #8fe4bf, 0 270px 0 0 #8fe4bf, 0 360px 0 0 #8fe4bf, 0 450px 0 0 #8fe4bf, 0 540px 0 0 #8fe4bf')
    }
    if(x > 270 -800){
        $('.circle').css('box-shadow','0 90px 0 0 #00b164, 0 180px 0 0 #00b164, 0 270px 0 0 #8fe4bf, 0 360px 0 0 #8fe4bf, 0 450px 0 0 #8fe4bf, 0 540px 0 0 #8fe4bf')
    }    
})
#progress {
    overflow:hidden;
    width:15px;
    padding-left:5px;
    height:800px;
    position: relative;
}
#progress .progressBar {
    height: 800px;
    width: 6px;
    background: #8fe4bf;
    position: absolute;
}
#progress .progressNow {
    height: 800px;
    top:-800px;
    width: 6px;
    background: #00b164;
    position: absolute;
}
.circle{
    content:"";
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: #8fe4bf;
    display: block;
    margin-left: -5px;
    position: absolute;
    top: 90px;
    box-shadow:0 90px 0 0 #8fe4bf, 0 180px 0 0 #8fe4bf, 0 270px 0 0 #8fe4bf, 0 360px 0 0 #8fe4bf, 0 450px 0 0 #8fe4bf, 0 540px 0 0 #8fe4bf;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<div id="progress">
    <div class="progressBar"></div>
    <div class="circle"></div>
    <div class="progressNow" value="1"></div>
</div>

答案 4 :(得分:5)

我的评论变成了答案。 它使用隐藏的<progress>后面的emty <div>来绘制所需的输出。

这不是很灵活,必须事先为5/6选项编写CSS:0,20%,40%,60%,80%,100%

.hide-it {
  position: absolute;
  left: -100%;
}

#myprogress {
  height: 25em;
  position: relative;
  float: left;
  width: 0.5em;
  background: linear-gradient(to bottom, #00B18E 0%, #CFF8F0 0%, #CFF8F0);
  margin: 1em 9em 1em 1em;
  color:#00B18E;
  box-shadow:0 0 15em 1em black;
}
#myprogress:after {
  content: '     Progress 0%';
  position:relative;
  z-index: 1;
  white-space: pre;
  top:-1%;
}
#myprogress:before {
  content: '';
  position: absolute;
  z-index: 1;
  top: -0.2em;
  left: -.25em;
  width: 1em;
  height: 1em;
  border-radius: 50%;
  box-shadow: inset 0 0 0 15px #00B18E;
}

[value="20"] + #myprogress {
  background: linear-gradient(to bottom, #00B18E 20%, #CFF8F0 20%, #CFF8F0);
}

[value="20"] + #myprogress:before {
  box-shadow: inset 0 0 0 15px #00B18E, 0 5em 0 0 #00B18E;
}
[value="20"] + #myprogress:after {
  content:'     Progress 20%';
  top:19%;
}

[value="40"] + #myprogress {
  background: linear-gradient(to bottom, #00B18E 40%, #CFF8F0 40%, #CFF8F0);
}

[value="40"] + #myprogress:before {
  box-shadow: inset 0 0 0 15px #00B18E, 0 5em 0 0 #00B18E, 0 10em 0 0 #00B18E;
}
[value="40"] + #myprogress:after {
  content:'     Progress 40%';
  top:39%;
}

[value="60"] + #myprogress {
  background: linear-gradient(to bottom, #00B18E 60%, #CFF8F0 60%, #CFF8F0);
}
[value="60"] + #myprogress:before {
  box-shadow: inset 0 0 0 15px #00B18E, 0 5em 0 0 #00B18E, 0 10em 0 0 #00B18E, 0 15em 0 0 #00B18E;
}
[value="60"] + #myprogress:after {
  content:'     Progress 60%';
  top:59%;
}
[value="80"] + #myprogress {
  background: linear-gradient(to bottom, #00B18E 80%, #CFF8F0 80%, #CFF8F0);
}
[value="80"] + #myprogress:before {
  box-shadow: inset 0 0 0 15px #00B18E, 0 5em 0 0 #00B18E, 0 10em 0 0 #00B18E, 0 15em 0 0 #00B18E, 0 20em 0 0 #00B18E;
}
[value="80"] + #myprogress:after {
  content:'     Progress 80%';
  top:79%;
}
[value="100"] + #myprogress {
  background: linear-gradient(to bottom, #00B18E 100%, #CFF8F0 100%, #CFF8F0);
}
[value="100"] + #myprogress:before {
  box-shadow: inset 0 0 0 15px #00B18E, 0 5em 0 0 #00B18E, 0 10em 0 0 #00B18E, 0 15em 0 0 #00B18E, 0 20em 0 0 #00B18E, 0 25em 0 0 #00B18E;
}
[value="100"] + #myprogress:after {
  content:'     Progress 100%';
  top:99%;
}
<progress class="hide-it" value="0" max="100">
</progress>
  <div id="myprogress"></div>
<progress class="hide-it" value="20" max="100">
</progress>
  <div id="myprogress"></div>
<progress class="hide-it" value="40" max="100">
</progress>
  <div id="myprogress"></div>
<progress class="hide-it" value="60" max="100">
</progress>
  <div id="myprogress"></div>
<progress class="hide-it" value="80" max="100">
</progress>
  <div id="myprogress"></div>
<progress class="hide-it" value="100" max="100">
</progress>
  <div id="myprogress"></div>

The codepen to play with

答案 5 :(得分:3)

SVG

这是一个带有一系列点的功能滚动条 点是单一路径。 栏上的滚动效果是通过javascript修改的线性渐变 文本百分比是svg文本元素,javascript修改此元素的y属性。

(我在这个解决方案上花了很多时间)

var start = document.getElementById("gradstart");
var stop = document.getElementById("gradstop");
var max = Math.max(document.body.scrollHeight, document.body.offsetHeight,
  document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
max -= document.documentElement.clientHeight;

var process = document.getElementById("process");

function gradientScroll() {
  var top = (window.pageYOffset || document.documentElement.scrollTop)
  var amount = Math.round((top / max) * 100.0);
  process.setAttribute("y", (amount) + "%");
  process.innerHTML = amount + "%";
  start.setAttribute("offset", amount + "%");
  stop.setAttribute("offset", amount + "%");
}

window.addEventListener("scroll", function() {
  window.requestAnimationFrame(gradientScroll);
});
<svg height="800px" viewBox="0 0 100 700" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <linearGradient x1="0" x2="0" y1="0%" y2="100%" id="grad">
      <stop id="gradstart" offset="50%" stop-color="firebrick" />
      <stop id="gradstop" offset="50%" stop-color="pink" />
    </linearGradient>
  </defs>
  <path fill="url(#grad)" d="m20,0 0,50 
                       a10 10 0 0 0 0,20
                       v50
                       a10 10 0 0 0 0,20
                       v50
                       a10 10 0 0 0 0,20
                       v50
                       a10 10 0 0 0 0,20
                       v50
                       a10 10 0 0 0 0,20
                       v50
                       a10 10 0 0 0 0,20
                       v50
                       a10 10 0 0 0 0,20
                       v50
                       a10 10 0 0 0 0,20
                       v50
                       a10 10 0 0 0 0,20
                       v50
                       a10 10 0 0 0 0,20
                       h5
                       a10 10 0 0 0 0,-20
                       v-50
                       a10 10 0 0 0 0,-20
                       v-50
                       a10 10 0 0 0 0,-20
                       v-50
                       a10 10 0 0 0 0,-20
                       v-50
                       a10 10 0 0 0 0,-20
                       v-50
                       a10 10 0 0 0 0,-20
                       v-50
                       a10 10 0 0 0 0,-20
                       v-50
                       a10 10 0 0 0 0,-20
                       v-50
                       a10 10 0 0 0 0,-20
                       v-50
                       a10 10 0 0 0 0,-20
                       v-100Z"></path>
  <text id="process" text-anchor="middle" x="60" y="50">Amount</text>
</svg>