HTML移动端 实现刻度尺效果

作者: 白吟灵 | 来源:发表于2017-10-20 15:25 被阅读419次

    前言

    在薄荷app的用户信息页看到在记录身高时,利用左右滑动刻度尺来取值。原本以为是h5实现,但上网搜索后并没有找到相关博客和文章,倒是有很多android的控件实现。所以就想自己实现一个看看。

    需求

    因为只是做一个demo,那就实现简单的效果就可以:

    1. 刻度区间[0,100]
    2. 有倒三角标记,指示当前刻数
    3. 用户左右滑动刻度尺区域,能够动态获取倒三角指示的刻数

    效果图

    效果图

    实现过程

    以下讲述关键的实现步骤,也可以直接下载文章最后的github源码。

    页面绘制

    页面其实很好绘制,一个刻度文本<span>节点和一个包裹刻度尺的<div>容器。难点在于刻度尺的展示和倒三角的实现。

    • 倒三角的实现
    //html
    <div id="triangle"></div>
    
    //css样式
    #triangle {
        width: 0;
        height: 0;
        margin: 0 auto;
        z-index: 199;
        border-top: 1rem solid rgb(190, 98, 75);
        border-left: 1rem solid transparent;
        border-right: 1rem solid transparent;
    }
    

    倒三角是一个没有内容的div,高度0,宽度0,为了让其居中,设置marigin:0 auto。通过设置左右边框透明、上边框1rem粗可以画出倒三角的效果。

    • 刻度尺实现
    //html
    <div id="ruler" data-offset="0">
                <ul id="ruler-ul">
                    <li>
                        <span>10</span>
                    </li>
                    <li>
                        <span>20</span>
                    </li>
                    <li>
                        <span>30</span>
                    </li>
                    //更多的刻度
              </ul>
    </div>
    
    //css样式
    #ruler-container {
        position: relative;
        overflow: hidden;
        width: 20rem;
        height: 5rem;
        border: 1px solid rgb(147, 184, 47);
    }
    
    #ruler ul {
        transform: translateX(10rem);
        width: 100rem;
        height: 4rem;
        position: relative;
    }
    
    #ruler ul li{
        width: 6.5rem;
        height: 100%;
        text-align: right;
        background: url(./ruler.png) top left no-repeat;
        background-size: 100px auto;
        float: left;
        list-style: none;
    }
    
    1. 刻度尺其实是一个无序列表,每一个刻度都是其中一个列表项。
    2. ul元素的宽度尽量设置非常大,并将其父div的overflow属性设置为hidden,保证列表项在一行上。
    3. 刻度线使用一张背景图片实现,设置background-size和background属性,可以让其达到合适的排列效果。同时需要float:left消除空隙。list-style:none也是必须的,不然会有默认的圆点。

    至此,页面的布局算是完成了。

    滑动事件响应

    实现滑动效果就是计算手指滑动距离,来设置#ruler的tansform:translateX(距离)样式。

    • 首先记录手指触碰到屏幕时的x坐标
        ruler.addEventListener('touchstart', function (event) {
            //手指按下时的坐标
            offsetX = event.touches[0].clientX;
            //初始化第一次滑动的距离为0
            moveBefore = 0;
        });
    
    • 当手指在屏幕上滑动时将其x坐标记录下来,跟按下时的x坐标相减计算出偏移量,将该偏移量赋给#ruler的样式,同时除以单位刻度的长度unit获取移动的刻度数,保留两位小数显示
        rulerUl.addEventListener('touchmove', function (event) {
            //获取滑动时手指的动态坐标
            var move = event.touches[0].clientX;
            //上一次计算出的刻度尺移动距离
            var offset = ruler.dataset.offset;
            //原来是string,转换为float方便计算
            offset = parseFloat(offset);
            var tempMove = 0;
            var len = 0;
            //相对于手指按下时的距离,除以10是因为要将px转换为rem单位
            tempMove = move - offsetX;
            tempMove /= 10;
            //计算两次滑动间的距离
            len = offset + (tempMove - moveBefore);
            len = parseFloat(len);
            //边界判断,最大偏移长度65rem
            if (len - 0.0 < 0 && len > -65) {
                //将结果保存下来,下一次滑动时取出参与计算
                moveX = tempMove;
                ruler.dataset.offset = len;
                moveBefore = moveX;
                //设置样式
                ruler.style = "transform: translateX(" + len + "rem)";
                //显示刻度,保留2位小数
                num.innerText = -((len / unit).toFixed(2));
            }
        }, false);
    

    源码地址

    github地址

    总结

    一时兴起做了这个demo,简单的实现了刻度尺滑动效果。但是也有一些问题:

    1. 因为浮点数精度问题会出现无法滑动到0或100的情况,因为此时已经满足滑动事件中的if条件,后面的样式修改等语句不会执行。
    2. 虽然使用了rem单位来处理不同设备,但是因为刻度线使用了背景图片来实现,不同的设备宽度下精度会受到影响。
    3. 我只是一个学了3个月前端的新人,代码中肯定还有很多我不知道的不规范的地方,,希望能帮我指出。

    如果能帮到你,我将十分荣幸。

    相关文章

      网友评论

        本文标题:HTML移动端 实现刻度尺效果

        本文链接:https://www.haomeiwen.com/subject/cikvuxtx.html