如何使用HTML,CSS和JavaScript构建响应式动态进度栏

我们的目标是建立一个简单而有效的响应式进度栏,该栏执行以下操作:

  • 有四个步骤完成。
  • 每一步骤都有defaultactive以及complete状态。
  • 可以逐步进行直到完成。

Screen-Shot-2020-09-12-at-2.35.47-PM

HTML

为了减少冗余并提高可重用性,我们跟踪Vue组件中的所有状态。在DOM中,这会动态生成任意数量的必需步骤。

注意:本机JavaScript(ECMAScript)或任何其他框架都可以完成此操作。Vue的使用仅出于说明目的。

进度栏使用基本标记。有:

  • 基于当前步骤的具有计算类的容器: progressClasses
  • 静态背景轨道: progress__bg
  • 一个循环遍历每个步骤并stepClasses根据当前步骤应用的循环。

每个步骤都有:

  • 一个progress__indicator包含选中图标的图标,如果该步骤完成,该图标将可见。
  • 一个progress__label包含该步骤的标签文本。
<div
  id="app"
  :class="progressClasses"
>
  <div class="progress__bg"></div>
  
  <template v-for="(step, index) in steps">
    <div :class="stepClasses(index)">
      <div class="progress__indicator">
        <i class="fa fa-check"></i>
      </div>
      <div class="progress__label">
        {{step.label}}
      </div>
    </div>
  </template>
  
  <div class="progress__actions">
    <div
      class="btn"
      v-on:click="nextStep(false)"
    >
      Back
    </div>
    <div
      class="btn"
      v-on:click="nextStep"
    >
      Next
    </div>
    <div>
      Step:
      {{currentStep ? currentStep.label : "Start"}}
    </div>
  </div>
</div>

为简单起见,progress__actions控制行进方向的控件嵌套在进度条本身内。

CSS(SCSS)

这是我们要做的繁重工作。JS将根据当前步骤动态应用此处定义的类。

首先,让我们选择一些颜色来使用:

$gray:  #E5E5E5;
$gray2: #808080;
$blue:  #2183DD;
$green: #009900;
$white: #FFFFFF;

现在定义.progress类:将进度条的内容保存在一起的容器。

.progress {
  position: absolute;
  top: 15vh;
  width: 0%;
  height: 10px;
  background-color: $blue;
  transition: width .2s;
}

我们的进度条需要一个进度条.progress__bg将像轨道一样运行。这将是灰色的,在前进到下一步时会被彩色条覆盖。

.progress__bg {
  position: absolute;
  width: 100vw;
  height: 10px;
  background-color: $gray;
  z-index: -1;
}

每个.progress__step步骤都包含一个圆形步骤,该步骤将随着进度条的前进而突出显示并填充。

.progress__step {
  position: absolute;
  top: -8px;
  left: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  
  @for $i from 1 through 5 {
    &.progress__step--#{$i} {
      left: calc(#{$i * 20}vw - 9px);
    }
  }
}

它还包含圆形.progress__indicator和标签文本.progress__label。它们的默认样式在之外定义.progress__step

.progress__indicator {
  width: 25px;
  height: 25px;
  border: 2px solid $gray2;
  border-radius: 50%;
  background-color: $white;
  margin-bottom: 10px;
  
  .fa {
    display: none;
    font-size: 16px;
    color: $white;
  }
}

.progress__label {
  position: absolute;
  top: 40px;
}

现在,让我们继续嵌套在内部.progress__step并定义处于活动状态的步骤。

&.progress__step--active {
  color: $blue;
  font-weight: 600;
}

接下来,将步骤定义为完整状态。:默认的样式.progress__indicator,并.progress__label在完整状态时被覆盖。

&.progress__step--complete {
  .progress__indicator {
    background-color: $green;
    border-color: $blue;
    color: $white;
    display: flex;
    align-items: center;
    justify-content: center;
  }
    
  .progress__indicator .fa {
    display: block;
  }
  
  .progress__label {
    font-weight: 600;
    color: $green;
  }
}

JavaScript

如前所述,这将根据您如何实现步骤逻辑,在更大的上下文中实现,使用何种框架和模式等而有所不同。

本示例使用Vue组件演示:

  • 根据当前状态计算进度条的类。
  • 根据当前状态计算每个步骤的类。
var app = new Vue({
el: '#app',
data: {
currentStep: null,
steps: [
{"label": "one"},
{"label": "two"},
{"label": "three"},
{"label": "complete"}
]
},
methods: {
nextStep(next=true) {
const steps = this.steps
const currentStep = this.currentStep
const currentIndex = steps.indexOf(currentStep)
// handle back
if (!next) {
if (currentStep && currentStep.label === 'complete') {
return this.currentStep = steps[steps.length - 1]           
}
if (steps[currentIndex - 1]) {
return this.currentStep = steps[currentIndex - 1] 
}
return this.currentStep = { "label": "start" }   
}
// handle next
if (this.currentStep && this.currentStep.label === 'complete') {
return this.currentStep = { "label": "start" }
}
if (steps[currentIndex + 1]) {
return this.currentStep = steps[currentIndex + 1]
}
this.currentStep = { "label": "complete" }   
},
stepClasses(index) {
let result = `progress__step progress__step--${index + 1} `
if (this.currentStep && this.currentStep.label === 'complete' ||
index < this.steps.indexOf(this.currentStep)) {
return result += 'progress__step--complete'
}
if (index === this.steps.indexOf(this.currentStep)) {
return result += 'progress__step--active'
}
return result
}
},
computed: {
progressClasses() {
let result = 'progress '
if (this.currentStep && this.currentStep.label === 'complete') {
return result += 'progress--complete'
}
return result += `progress--${this.steps.indexOf(this.currentStep) + 1}`
}
}
})

结论

最后,您将拥有以下效果:

如何使用HTML,CSS和JavaScript构建响应式动态进度栏

 

点击阅读原文

本文来自投稿,不代表微擎百科立场,如若转载,请注明出处:https://www.w7.wiki/develop/4369.html

发表评论

登录后才能评论