【用CSS画个三角形实现漏斗定时器吧】

用CSS画个三角形实现漏斗定时器吧

CSS 三角形 漏斗 定时器

起源于面试官问我如何用css实现一个三角形。我一想这还不简单,我之前都没有把这一题放在我的面经里。然后。。。我就开始描述,发现自己描述不清。唉,果然好记性不如烂笔头,又一次深深的感悟了!回来,我就开始写样式。嗯,确实一写就又会了。
但是!写都写了,怎么能只画一个三角形。于是我又画了一个,又一个,又一个。。。成漏斗了。那就索性再加点动画,做个漏斗定时器吧。


提示:以下是本篇文章正文内容,下面案例可供参考
css三角形,定时器

一、CSS三角形?

确实是一个比较基础的内容了。主要通过设置一个盒子的border。一个没有宽高的盒子,设置border的宽度,颜色为透明。然后再设置三角形对应方向上的border颜色为你想要的颜色。
在这里插入图片描述


        .triangle-up {
            /* 水平垂直居中 */
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            /* 画三角形 */
            border: 50px solid transparent;
            border-top-color: white;
            border-top-left-radius: 5px;
            border-top-right-radius: 5px;
            z-index: 5;
            /* 要让沙子叠到下面的漏斗上面 */
        }

        .triangle-down {
            /* 水平垂直居中 */
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            /* 画三角形 */
            border: 50px solid transparent;
            border-bottom-color: rgb(231, 107, 221);
            border-bottom-left-radius: 5px;
            border-bottom-right-radius: 5px;
        }

二、组个漏斗

漏斗由上下两个三角组成triangle-up和triangle-down,上面的是白色,下面的是粉色。内部再添加有颜色的三角triangle-up-inner和triangle-down-inner,固定好位置与外层的三角重叠。js控制内部三角的border的宽度变化。初始时,上面全是沙子,则内部蓝色三角的border宽度和外部相等;下方内部三角为白色,也覆盖外层。每隔一段时间,沙子下落,triangle-up-inner的边框宽度减少,triangle-down-inner的边框宽度也减少。
为沙子添加下落的动画。

1.HTML结构

    <div class="container">
        <!-- 漏斗 -->
        <div class="triangle-up">
            <div class="triangle-up-inner">
                <div class="sand-box">
                    <!-- 沙子 -->
                    <div class="sand sand1"></div>
                    <div class="sand sand2"></div>
                    <div class="sand sand3"></div>
                    <div class="sand sand4"></div>
                    <div class="sand sand5"></div>
                    <div class="sand sand6"></div>
                </div>
            </div>
        </div>
        <div class="triangle-down">
            <div class="triangle-down-inner"></div>
        </div>
    </div>

上面画两个三角形,一个是最外层的三角,设置为白色;里面的是漏斗的填充物,设置为蓝色。下面的两个三角行也是同样的设置。然后再加点沙子。

2.CSS样式

代码如下(示例):

        .triangle-up-inner {
            border: 50px solid transparent;/* 漏斗定时开始,上面全蓝,随着 */
            border-top-color: rgb(17, 20, 167);/* 蓝色 */
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
        }

        .triangle-down-inner {
            border: 50px solid transparent;/* 蓝色 */
            border-bottom-color: white;
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            
        }
         .sand {
            position: absolute;
            width: 5px;
            height: 5px;
            border-radius: 5px;
            background-color: rgb(17, 20, 167);
        }

        .sand1 {
            left: 2px;
            animation: sandDown 1s linear infinite;
        }

        .sand2 {
            animation: sandDown 1.6s linear infinite;
        }

        .sand3 {
            left: -1px;
            animation: sandDown 2.2s linear infinite;
        }

        .sand4 {
            left: 1px;
            animation: sandDown 2.3s linear infinite;
        }

        .sand5 {
            animation: sandDown 2.6s linear infinite;
        }

        .sand6 {
            left: -2px;
            animation: sandDown 3.2s linear infinite;
        }

        @keyframes sandDown {
            from {
                transform: translateY(0);
            }

            to {
                transform: translateY(45px);
            }
        }

3.JS漏斗定时器

无非就是开一个定时器,每隔一定的时间,上下三角的边框宽度变化。之前想练练手,考虑用requestAnimationFrame()去做。发现有点大材小用,requestAnimationFrame()提供逐帧渲染的方式去实现动画,重绘的频率和屏幕刷新的频率保持一致。但是这里的话不太合适也麻烦,因为我需要的是漏斗隔固定时间下降1px(css最小单位是1px或0.5px),不需要逐帧的渲染。所以用个定时器setInterval就够了。每隔delay,漏斗的边框宽度减少1px。delay的计算根据border的宽度得到的。
但是确实是setInterval定时会有一丢丢误差,一直开着,也会导致累计误差。没办法,只能用new Date()计算每次定时的时延,然后把时延加到下一次的定时器里。这样总的时延就少了(因此漏斗是定时一分钟)。

        /* 设置一个一分钟的无限循环定时器 */
        let t = 60;
        var triangle = document.querySelector('.triangle-up');
        var triangle_down = document.querySelector('.triangle_down');
        const height = triangle.offsetHeight/2;//获取漏斗的高度
        var triangle_up_inner = document.querySelector('.triangle-up-inner');
        var triangle_down_inner = document.querySelector('.triangle-down-inner');
        var sandBox = document.querySelector('.sand-box');
        var step =- 1;//设置移动的步长
        var delay = (t-1)/height*1000;
        //初始化,漏斗上边是满的,下边是空的
        function init() {
            triangle_up_inner.style.borderWidth = `${height}px`;
            triangle_down_inner.style.borderWidth = `${height}px`;
        }
        init();
        let begin = +new Date();
        play();
        function play() {
            let startTime=+new Date();
            let timer = setTimeout(function down(){
                let offset = +new Date()-startTime-delay;//修正定时器时间
                var up_inner_height = triangle_up_inner.offsetHeight/2;
                if ((up_inner_height + step) <= 0 ) {
                    console.log(+new Date()-begin);
                    begin = +new Date();
                    clearTimeout(timer);
                    init();
                    play();
                } else {//设置1秒中移动一个step
                    triangle_up_inner.style.borderWidth = `${up_inner_height + step}px`;
                    triangle_down_inner.style.borderWidth = `${up_inner_height + step}px`;
                    clearTimeout(timer);
                    startTime =+new Date();
                    setTimeout(down,delay-offset);
                }
            },delay)            
        }

总结

写个博客确实挺花时间。我要去刷算法题了。唉,今年找实习可真难。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值