美文网首页
Vue定制尺子,支持各种自定义,使用简单方便

Vue定制尺子,支持各种自定义,使用简单方便

作者: Jeff_Kitty | 来源:发表于2021-04-23 16:28 被阅读0次

    看到网上很多关于Vue的尺子组件,有一些上传到npm官网的,但是使用并不方便,支持的定制化也不够用,抽空写了一个,总体来说主要是样式写好,效果是基于better-scroll实现的,支持bounce效果,自动识别最近的刻度,只需要传入自己的最大值和最小值,就会帮你算出一个包含最大值的最大刻度,整体效果不错,由于是demo,没有基于任何UI效果,要达到自己设计师要求的UI效果,可以将这份代码拷贝过去自己改造定义一个尺子的Vue组件来使用,效果图:

    有点大了

    页面DOM结构如下,样式采用的stylus预处理语法,个人觉得stylus就是为css而生的,相比less,sass好用很多,请现在webpack.config.js里面配上处理stylus的规则,

    <template>

        <div class="box">

            <div class="arrow">{{value}}</div>

            <div class="wrapper ruler">

                <ul ref="ul" :style="{width: ul_width + 'px'}">

                    <li v-for="(v, i) in ruler_max_num" :key="i">

                        <label>{{v * 10}}</label>

                        <span v-for="(e, d) in 10" :key="d"></span>

                    </li>

                </ul>

            </div>

        </div>

    </template>

    样式如下:

    <style lang="stylus" rel="stylesheet/stylus" scoped>

    .box

        .arrow

            font-weight 500

            width 100%

            height 20px

            text-align center

            position relative

            top -20px

            &::after

                content ''

                position absolute

                left 50%

                top 110px

                transform translateX(-50%)

                border 8px solid black

                border-color black  transparent transparent transparent

        .ruler

            font-size 12px

            width 100%

            padding-top 100px

            >ul

                width 100%

                height 80px

                border 1px solid #ddd

                border-left none

                border-right none

                display flex

                justify-content space-between

                background #fff

                >li

                    height 18px

                    display flex

                    justify-content space-between

                    box-sizing border-box

                    position relative

                    &:first-child

                        position relative

                        &::before

                            position absolute

                            content ""

                            left -1px

                            top 0

                            height 11px

                            width 1px

                            background black

                            opacity 0.8

                    &::after

                        position absolute

                        content ""

                        right 0

                        top 0

                        height 15px

                        width 1px

                        background black

                    >label

                        position absolute

                        right -6px

                        bottom -16px

                    >span

                        width 10px

                        height 11px

                        box-sizing border-box

                        border-right 1px solid black

                        opacity 0.8

                        position relative

                        &::after

                            position absolute

                            content ""

                            left 50%

                            top 0

                            transform translateX(-50%)

                            height 8px

                            width 1px

                            background black

                            opacity 0.5

    </style>

    js代码如下:

    <script>

    import BScroll from 'better-scroll'

    export default {

        props: {

            max_val: { // 需要

                type: Number,

                default() {

                    return 168

                }

            },

            min_val: {

                type: Number,

                default() {

                    return 0

                }

            }

        },

        data() {

            return {

                split_val: 10,

                value: 0

            }

        },

        mounted() {

            let ul = this.$refs.ul

            let lis = ul.getElementsByTagName('li')

            let first_li = lis[0]

            let last_li = lis[lis.length - 1]

            first_li.style.marginLeft = document.body.clientWidth/2 + 'px'

            last_li.style.marginRight= document.body.clientWidth/2 + 'px'

            this.$nextTick(()=>{

                let bs = new BScroll('.wrapper', {

                    startX: 0,

                    scrollX: true,

                    probeType: 2,

                    useTransition: false,

                    bounce: true,

                    momentum: true

                })

                bs.on('scrollEnd', ({x, y}) => {

                    if (x > 0) {

                        x = 0

                    }

                    this.value = -Math.round(x/10)

                    bs.scrollTo(Math.round(x/10) * 10, 0)

                })

            })

        },

        computed: {

            ul_width() {

                return this.ruler_max_num * 10 * 10 + document.body.clientWidth 

            },

            ruler_max_num() {

                let split_num = Math.floor(this.max_val / this.split_val)

                let left_v = this.max_val % this.split_val

                if (left_v > 0) {

                    split_num = split_num + 1

                }

                return split_num

            }

        }

    }

    </script>

    基本上项目安装好better-scroll后就可以运行起来了,

    今天做了一个小小的优化,支持传入最大值和最小值,从而只显示这个值域段的刻度

    DOM

    样式添加:

    <style lang="stylus" rel="stylesheet/stylus" scoped>

    .box

        .arrow

            font-weight 500

            width 100%

            height 20px

            text-align center

            position relative

            top -20px

            &::after

                content ''

                position absolute

                left 50%

                top 110px

                transform translateX(-50%)

                border 8px solid black

                border-color black  transparent transparent transparent

        .ruler

            font-size 12px

            width 100%

            padding-top 100px

            >ul

                width 100%

                height 80px

                border 1px solid #ddd

                border-left none

                border-right none

                display flex

                justify-content space-between

                background #fff

                >li

                    height 18px

                    display flex

                    justify-content space-between

                    box-sizing border-box

                    position relative

                    &:first-child

                        position relative

                        &::before

                            position absolute

                            content ""

                            left -1px

                            top 0

                            height 11px

                            width 1px

                            background black

                            opacity 0.8

                    &::after

                        position absolute

                        content ""

                        right 0

                        top 0

                        height 15px

                        width 1px

                        background black

                    >label

                        position absolute

                        right -6px

                        bottom -16px

                        &.first

                            right 100%

                            bottom -14px

                            margin-right -6px

                    >span

                        width 10px

                        height 11px

                        box-sizing border-box

                        border-right 1px solid black

                        opacity 0.8

                        position relative

                        &::after

                            position absolute

                            content ""

                            left 50%

                            top 0

                            transform translateX(-50%)

                            height 8px

                            width 1px

                            background black

                            opacity 0.5

    </style>

    JS逻辑:

    export default {

        props: {

            max_val: {

                type: Number,

                default() {

                    return 888

                }

            },

            min_val: {

                type: Number,

                default() {

                    return 666

                }

            }

        },

        data() {

            return {

                split_val: 10,

                value: 0,

                initail_val: 0

            }

        },

        mounted() {

            let ul = this.$refs.ul

            let lis = ul.getElementsByTagName('li')

            let first_li = lis[0]

            let last_li = lis[lis.length - 1]

            first_li.style.marginLeft = document.body.clientWidth/2 + 'px'

            last_li.style.marginRight= document.body.clientWidth/2 + 'px'

            this.value = this.ruler_min_num * 10

            this.initail_val = this.ruler_min_num * 10

            this.$nextTick(()=>{

                let bs = new BScroll('.wrapper', {

                    startX: 0,

                    scrollX: true,

                    probeType: 2,

                    useTransition: false,

                    bounce: true,

                    momentum: true

                })

                bs.on('scrollEnd', ({x, y}) => {

                    if (x > 0) {

                        x = 0

                    }

                    this.value = -Math.round(x / 10) + this.ruler_min_num * 10

                    bs.scrollTo(Math.round(x / 10) * 10, 0)

                })

            })

        },

        computed: {

            ul_width() {

                return this.actual_num * 10 * 10 + document.body.clientWidth

            },

            ruler_max_num() {

                let split_num = Math.floor(this.max_val / this.split_val)

                let left_v = this.max_val % this.split_val

                if (left_v > 0) {

                    split_num = split_num + 1

                }

                return split_num

            },

            ruler_min_num() {

                let split_num = Math.floor(this.min_val / this.split_val)

                return split_num

            },

            actual_num() {

                return this.ruler_max_num - this.ruler_min_num

            }

        }

    }

    效果图:传入最大值88,传入最小值66,显示为60-90之前的尺段,提高尺子的滑动效率:

    相关文章

      网友评论

          本文标题:Vue定制尺子,支持各种自定义,使用简单方便

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