#夏日挑战赛# HarmonyOS - 自定义组件之slider滑块 原创 精华

发布于 2022-7-15 09:46
浏览
4收藏

作者:范乐乐

本文正在参加星光计划3.0–夏日挑战赛

前言

最近在学习HarmonyOS开发相关知识,在项目开发过程中有用到slider滑块组件,本文主要结合HarmonyOS官网上的相关组件以及通用API,实现一个slider滑块组件。

效果演示

#夏日挑战赛# HarmonyOS - 自定义组件之slider滑块-开源基础软件社区

实现原理

1. 触发条件

基于HarmonyOS通用事件touchstart和touchmove,通过手指刚触摸屏幕时触发、手指触摸屏幕后移动时触发事件;

2. 实现slider滑块效果

通过touches触摸事件时的属性集合,返回屏幕触摸点的信息数组,拿到localX距离被触摸组件左上角横向距离,动态计算出子元素的宽度来实现slider滑块效果。

3. 实现百分比显示

通过HarmonyOS通用方法getBoundingClientRect()获取元素自身的宽度;通过滑动的距离除去元素自身的宽度,来实现滑块移动的百分比;

使用到的官方API

通用方法

getBoundingClientRect()

获取元素的大小及其相对于窗口的位置。

属性 类型 描述
width number 该元素的宽度。
height number 该元素的高度。
left number 该元素左边界距离窗口的偏移。
top number 该元素上边界距离窗口的偏移。

通用事件

名称 参数 描述 是否支持冒泡
touchstart TouchEvent 手指刚触摸屏幕时触发该事件。 是5+
touchmove TouchEvent 手指触摸屏幕后移动时触发该事件。 是5+
属性 类型 说明
touches Array<TouchInfo> 触摸事件时的属性集合,包含屏幕触摸点的信息数组。
属性 类型 说明
globalX number 距离屏幕左上角(不包括状态栏)横向距离。屏幕的左上角为原点。
globalY number 距离屏幕左上角(不包括状态栏)纵向距离。屏幕的左上角为原点。
localX number 距离被触摸组件左上角横向距离。组件的左上角为原点。
localY number 距离被触摸组件左上角纵向距离。组件的左上角为原点。

实现过程

hml部分:

    <div class="slider-wrapper">
        <div class="progressBox">
            <text>
                <span>{{progress}}%</span>
            </text>
        </div>
        <div class="content">
            <div id="slider" @touchstart="boxChoose" @touchmove="boxChoose"  style="width: 300px;">
                <div class="slider-main" style="width: {{ width }}"></div>
            </div>
            <div class="dot" style ="left : {{dotLeft}}"></div>
        </div>
        <div class="progress" >
            <text for="{{ (index,item) in stepArr }}">
                {{item}}
            </text>
        </div>
       
    </div>

css部分:

.slider-wrapper {
    width: 100%;
    display: flex;
    align-items: center;
    flex-direction: column;
    background-color: bisque;
}
.progressBox{
    margin-top:50px ;
    display: flex;
    justify-content: center;
    align-items: center;
}
.content{
    width: 300px;
    display: flex;
    align-items: center;
    flex-direction: column;
    position: relative;
    margin-top: 50px;
}

#slider {
    width: 300px;
    height: 15px;
    background-color: pink;
    display: flex;
    justify-content: center;
}
.slider-main {
    background-color: aqua;
    width: 0;
    height: 100%;
    position: absolute;
    left: 0;
    top: 0;
}
.dot {
    border-radius: 50px;
    width: 25px;
    height: 25px;
    background-color: #fff;
    border: 1px solid #409eff;
    position: absolute;
    top: -5px;

}

.progress{
    width: 300px;
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    font-size: 20px;
}

js部分:通过动态改变子元素width的宽度来实现slider滑块效果;给小圆dot相对于它父元素设置为绝对定位,通过动态改变left的值使圆块移动,把子元素width的宽度赋值给变量dotLeft,就可以实现小圆跟随滑块一起移动的效果。

export default {
    data: {
        progress:0,//百分比
        width: 0,
        step1: 1,//步长
        stepArr:[0,20,40,60,80,100],
        dotLeft:-10
    },
    boxChoose(e) {

        let box = this.$element('slider')

        let width = e.touches[0].localX // 获取点击时距离容器左边位置
        this.dotLeft = width
        let elementWidth = box.getBoundingClientRect().width -10 //元素的宽度 - 小圆的偏移量
        // 小圆的偏移量临界值
        if ( this.dotLeft >= elementWidth ) {
            this.dotLeft = elementWidth
        }
        if ( this.dotLeft <= -10 ) {
            this.dotLeft = -10
        }
        let compare = elementWidth / (100 / this.step1) // 根据步长计算每一步宽度
        this.width = Math.ceil(width / compare) * compare
        this.progress = Math.round(this.width / elementWidth *100)

        //限制临界值
        if(this.progress >= 100){
            this.progress = 100
        };
        if(this.progress <= 0){
            this.progress = 0
        }
    },
}

总结

这篇文章是我对学习鸿蒙动画API的一个练习,也算是一个比较常用的组件,后续部分功能还需完善,比如在样式、功能方面等等,希望可以和大家共同学习鸿蒙更多的知识,一起进步。

更多原创内容请关注:中软国际 HarmonyOS 技术团队

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
7
收藏 4
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐