CSS实现步骤进度条——前端每日一练


效果展示

在这里插入图片描述


HTML布局文件

总体布局,一个大div盒子包裹所有内容,里面划分为div + button,六个⭕分别对应着六个子div;⭕下方就是两个button组件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>步骤条实现</title>
    <link rel="stylesheet" href="./style.css" />
</head>
<body>
    <div class="container">
        <div class="progress-container">
            <div id="progress" class="progress"></div>
            <div class="circle active">1</div>
            <div class="circle">2</div>
            <div class="circle">3</div>
            <div class="circle">4</div>
            <div class="circle">5</div>
            <div class="circle">6</div>
        </div>
        <button type="button" class="prev disabled" id="prev">上一步</button>
        <button type="button" class="next active" id="next">下一步</button>
    </div>
    <script src="./index.js"></script>
</body>
</html>

CSS样式

主要涉及内容:伪元素、flex弹性布局、:root自定义全局属性

* {
    margin: 0;
    padding: 0;
    /* border-box:当定义width和height时,
    border和padding的参数值被包含在width和height之内。*/
    box-sizing: border-box;
}

:root {
    /* 在: root选择器中定义自定义属性意味着它们可以作用于全局文档中所有元素。 */
    --color--: #dededf;
    --color_active--: #2396ef;
    --font_color--: #535455;
    --default_color--: #fff;
}

body,
html {
    /* 给一个元素中设置overflow: hidden,
    那么该元素的内容若超出了给定的宽度和高度属性,那么超出的部分将会被隐藏 */
    overflow: hidden;
    display: flex;
    justify-content: center;
    /* 将弹性 <div>元素的所有项目的居中对齐: */
    align-items: center;
    height: 100%;
}

.container {
    width: 100%;
    text-align: center;
}

.progress-container {
    width: 100%;
    width: 350px;
    display: flex;
    /* 均匀排列每个元素
    首个元素放置于起点,末尾元素放置于终点 */
    justify-content: space-between;
    position: relative;
    margin-bottom: 30px;
}

.progress-container::before {
    content: '';
    width: 100%;
    background-color: var(--color--);
}

.progress-container>.progress,
.progress-container::before {
    height: 5px;
    border-radius: 2px;
    position: absolute;
    left: 0;
    /* top: 50%——向上间隔50%的高度。由于自身的高度,单纯使用此属性并不会居中。 */
    top: 50%;
    /* transform: translateY(-50%)——向上移动自身高度的50%,与上个属性结合便可以实现垂直居中。 */
    transform: translateY(-50%);
    /* z-index 属性设置元素的堆叠顺序。
    拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。 */
    z-index: -1;
}

.progress-container>.progress {
    background-color: var(--color_active--);
    transition: all .3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.progress-container>.circle {
    display: flex;
    justify-content: center;
    align-items: center;
    border: 4px solid var(--color--);
    width: 40px;
    height: 40px;
    color: var(--font_color--);
    border-radius: 50%;
    background-color: var(--default_color--);
    transition: all .35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.progress-container>.circle.active {
    border-color: var(--color_active--);
}

.prev,
.next {
    /* CSS outline: none; */
    /* 表示使outline属性无效,使绘制于元素周围的一条线无效。 */
    outline: none;
    /* 标签元素不设置边框属性或者取消边框属性 */
    /* 设置0浏览器依然会渲染,占用内存,设置none就不会渲染 */
    border: none;
    /* display: inline-block不设置宽度时,内容撑开宽度;
    不会独占一行,支持宽高,代码换行被解析成空格 */
    display: inline-block;
    background-color: var(--color--);
    padding: 8px 16px;
    border-radius: 5px;
    color: var(--font_color--);
    transition: all .3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
    cursor: pointer;
}

/* a.active 是对class=active的a标签生效 */
/* a:active 是对按下的a标签生效 */
.prev:active,
.next:active {
    transform: scale(.9);
}

.prev.disabled,
.next.disabled {
    cursor: not-allowed;
    background-color: var(--color--);
    color: var(--font_color--);
}

.prev.active,
.next.active {
    background-color: var(--color_active--);
    color: var(--default_color--);
}

.next {
    margin-left: 15px;
}

relative:生成相对定位的元素,相对于其正常位置进行定位
absolute:生成绝对定位的元素,相对于static定位以外的第一个父元素进行定位

top: 50%;向上间隔50%的高度,由于存在自身的高度,到哪都使用该属性并不会显示居中。
transform: translateY(-50%);向上移动相对自身高度的50%,和上一个属性结合可以实现垂直居中显示。


JavaScript操作逻辑

const $ = v => document.querySelector(v);
const $$ = v => document.querySelectorAll(v);
const prevBtn = $("#prev");
const nextBtn = $("#next");
const progress = $("#progress");
const circleElements = $$(".circle");
const min = 0, max = circleElements.length - 1;
let currentActive = 0;

nextBtn.addEventListener("click", () => {
    if (nextBtn.classList.contains('disabled')) return;
    if (currentActive >= max - 1) {
        // currentActive = min;
        handleClass(nextBtn).addClass("disabled").removeClass("active");
    }
    if (currentActive <= max - 1) {
        currentActive++;
    }
    if (currentActive > 0) {
        handleClass(prevBtn).addClass("active").removeClass("disabled");
    }
    update();
});

prevBtn.addEventListener("click", () => {
    if (prevBtn.classList.contains('disabled')) return;
    if (currentActive <= 1) {
        // currentActive = max -  1;
        handleClass(prevBtn).addClass("disabled").removeClass("active");
    }
    if (currentActive > 0) {
        currentActive--;
    }
    if (currentActive <= max - 1) {
        handleClass(nextBtn).addClass("active").removeClass("disabled");
    }
    update();
});

function handleClass(el) {
    let methods = {
        addClass,
        removeClass
    };
    function addClass(c) {
        el.classList.add(c);
        return methods;
    };
    function removeClass(c) {
        el.classList.remove(c);
        return methods;
    }
    return methods
}

function update() {
    circleElements.forEach((item, index) => {
        if (index <= currentActive) {
            // classLIst属性返回元素的类名,作为DOMTokenList对象
            item.classList.add('active');
        } else {
            item.classList.remove('active');
        }
    });
    // toFixed() 方法可把 Number 四舍五入为指定小数位数的数字。
    progress.style.width = (100 / max * currentActive).toFixed(4) + '%';
}

关键点如下:

  • toFixed:该方法可以把Number四舍五入为指定小数数位的数字;
  • 语法:number.toFixed(x)

  • classList对象:HTML5给每一个元素新增加了一个classList对象,该对象保存有控制当前元素类名的各个方法和属性。
  • Element.classList是一个只读属性,返回一个元素的类属性的DOMTokenList集合。
var oBtn = document.getElementById("btn");
var oCon = document.getElementById("con");
oBtn.onclick = function () {
    
    // oCon.className = "red";
    console.log(oCon.className); //red

    oCon.className = "con show red";

    //这个red类已经存在于元素的属性中,那么它将被忽略
    oCon.className += " red";
    console.log(oCon.classList.length); //3

    //在原有的类名基础上添加一个类名
    oCon.classList.add("red");

    // 在原有的类名基础上 移出某一个类名
    oCon.classList.remove("con");

    // 如果有这个类名 则删除这个类名,如果没有 则添加减去
    oCon.classList.toggle("blue");

    // 判断元素是否包含某一个类名
    console.log(oCon.classList.contains("con"));

    // 根据索引 获取类名
    console.log(oCon.classList.item(0)); //con
}
  • forEach方法:用于调用数组的每一个元素,并且把元素传递给回调函数。
  • 注意:forEach()对于空数组是不会执行回调函数的

补充:JavaScript的this关键字

面向对象语言中this指的是当前对象的一个引用

但是在JavaScript中this并不是固定不变的,而是随着执行环境的改变发生变化:

  • 在方法中,this表示这个方法所属的对象。
  • 若单独使用,则this表示全局对象。
  • 在函数中,this表示全局对象。
  • 在函数中,严格模式this是未定义的。
  • 在事件中,this表示接收事件的元素。
  • 类似call和apply方法可以把this引用到任何对象中。

在函数的内部,this的数值取决于函数被调用的方式:

由于下面的代码并不是在严格模式,并且this的数值不是由该调用设置的,因此this的默认数值指向全局对象,浏览器就是window。

function f1(){
  return this;
}
//在浏览器中:
f1() === window;   //在浏览器中,全局对象是 window

//在 Node 中:
f1() === globalThis;
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现一个圆形进度条的动态效果,可以使用CSS中的@keyframes动画和transform属性。 首先,创建一个包含圆形进度条的div元素,并设定其宽高和边框样式,使它呈现为圆形。 然后,使用CSS的@keyframes创建一个动画序列,在序列中设置进度条的旋转角度。例如,可以从0°开始旋转,到360°结束,表示进度条的完整程度。 接下来,在CSS中,为进度条的div元素添加animation属性,将刚才创建的动画序列应用于进度条上,并设定动画的持续时间、重复次数等。 最后,通过设置transform-origin属性,将进度条的旋转中心设置为圆心,使得进度条动画在圆形元素中心点进行旋转,形成动态效果。 例如,下面是一个实现50%进度的圆形进度条CSS代码示例: ```css .circle { width: 100px; height: 100px; border: 5px solid #ccc; border-radius: 50%; animation: progress 2s linear infinite; transform-origin: center center; } @keyframes progress { 0% { transform: rotate(0deg); } 100% { transform: rotate(180deg); } } ``` 这个示例中,圆形进度条的宽高为100px,边框为5px粗的灰色线条。动画序列progress中,进度条从0°开始旋转到180°,持续2秒,线性变化,并无限循环播放。进度条的旋转中心被设置为圆心。 这样,通过CSS实现了一个圆形进度条的动态效果。可以根据需要修改代码中的数值,实现不同的进度和动画效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值