Vue定制尺子,支持各種自定義,使用簡(jiǎn)單方便

看到網(wǎng)上很多關(guān)于Vue的尺子組件,有一些上傳到npm官網(wǎng)的,但是使用并不方便,支持的定制化也不夠用,抽空寫(xiě)了一個(gè),總體來(lái)說(shuō)主要是樣式寫(xiě)好,效果是基于better-scroll實(shí)現(xiàn)的,支持bounce效果,自動(dòng)識(shí)別最近的刻度,只需要傳入自己的最大值和最小值,就會(huì)幫你算出一個(gè)包含最大值的最大刻度,整體效果不錯(cuò),由于是demo,沒(méi)有基于任何UI效果,要達(dá)到自己設(shè)計(jì)師要求的UI效果,可以將這份代碼拷貝過(guò)去自己改造定義一個(gè)尺子的Vue組件來(lái)使用,效果圖:

有點(diǎn)大了

頁(yè)面DOM結(jié)構(gòu)如下,樣式采用的stylus預(yù)處理語(yǔ)法,個(gè)人覺(jué)得stylus就是為css而生的,相比less,sass好用很多,請(qǐng)現(xiàn)在webpack.config.js里面配上處理stylus的規(guī)則,

<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>

基本上項(xiàng)目安裝好better-scroll后就可以運(yùn)行起來(lái)了,

今天做了一個(gè)小小的優(yōu)化,支持傳入最大值和最小值,從而只顯示這個(gè)值域段的刻度


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之前的尺段,提高尺子的滑動(dòng)效率:


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容