vue3组件篇 Slider

文章介绍了Slider组件的用途、特点和参数,展示了如何使用CSS改变HTML原生的slider组件样式,并提供了使用Vue3-dxui库的安装和组件代码示例。文章还提及了dxui组件库,这是一个针对PC网站交互模式的前端组件库。
摘要由CSDN通过智能技术生成

组件介绍

“Slider” 组件是一种常见的用户界面元素,通常用于允许用户在一个范围内选择一个数值或数值范围。用户可以通过拖动滑块来选择值,这种组件通常用于调整设置、选择价格范围、音量控制、时间选择等。以下是关于 “Slider” 组件的介绍和特点:

  1. 滑块:

    • “Slider” 组件通常包括一个或多个滑块,用户可以通过拖动滑块来选择数值。
  2. 数值范围:

    • “Slider” 允许用户在一个预定义的数值范围内选择值,通常包括最小值和最大值。
  3. 单一和范围选择:

    • “Slider” 组件可以是单一滑块,用于选择单个值,也可以是范围滑块,用于选择一个范围,例如选择一个起始值和结束值。
  4. 步长和刻度:

    • “Slider” 组件通常支持设置步长,也就是滑块每次拖动时数值的变化量。它们还可以包括刻度标记,以帮助用户更容易地选择数值。
  5. 标签和数值显示:

    • “Slider” 组件通常包括标签或数值显示区域,用于显示当前选择的值或范围。
  6. 自定义样式:

    • 开发人员通常可以自定义 “Slider” 组件的样式,包括滑块的外观、颜色、尺寸等。
  7. 事件处理:

    • “Slider” 组件通常支持事件处理,开发人员可以监听用户的滑动操作,并在数值变化时执行自定义操作。
  8. 垂直和水平方向:

    • “Slider” 组件可以水平或垂直方向展示,具体取决于设计需求。一些应用程序中可能需要垂直滑块,例如音量控制。
  9. 响应式设计:

    • “Slider” 组件通常支持响应式设计,以适应不同屏幕尺寸和设备类型。
  10. 可访问性:

    • 良好的 “Slider” 组件应该考虑到可访问性,以确保它对于使用辅助技术的用户也是可访问的。

“Slider” 组件对于用户交互和选择数值范围非常有用。它们通常用于网页应用程序、移动应用程序和桌面应用程序中,提供了一种用户友好的方式来选择值或范围,以满足不同的应用需求。许多前端框架和库提供了 “Slider” 组件的实现,或者你可以自行编写代码来创建适合你应用程序需求的滑块功能。

css改变html原生的slider组件

在前端开发中,Slider组件可以使用HTML、CSS和JavaScript实现。HTML中可以使用range input元素来创建Slider组件,CSS可以控制Slider组件的样式,而JavaScript可以增加Slider组件的交互功能,例如拖动滑块时更新滑块位置以及相应的值。

<input type="range" id="slider-input" min="0" max="100" />

// 修改滑条的轨道样式
input[type='range'] {
  -webkit-appearance: none;
  background: linear-gradient(75deg, #fff, #ff2d52);
  border-radius: 4px;
  width: 100%;
  height: 12px;
  outline: none;
  // box-shadow: 0 0 6px rgba();
}

// 修改滑条的按钮样式
input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  background: #f53b57;
  border-radius: 50%;
  transition: 0.3s;
  cursor: pointer;
}

// 修改滑条按钮激活时的样式
input[type='range']:active::-webkit-slider-thumb {
  background: #f53b57;
  box-shadow: 0 0 0 6px rgba(155, 73, 146, 0.4);
}

如果想要存手写一个slider组件,我们需要准备些什么

  1. slider组件需要确立一个数值范围,即最大最小值min或max
  2. 按钮的拖动时,触发事件监听,和数值变化
  3. step步长的限制
  4. 最难处理的是 进度与value与min和max之间及step的关联计算
  5. 按钮的拖动效果,以及拖动的边界限制
  6. 点击滑条上某个位置时,按钮和数值的变化
  7. 滑条的禁用

组件安装与使用

需要先安装vue3-dxui

yarn add vue3-dxui

或者

npm install vue3-dxui

全局main.ts中引入css

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import 'vue3-dxui/dxui/dxui.css'

createApp(App).use(store).use(router).mount('#app')

按需引入

<script>
import { Slider } from 'vue3-dxui'

export default {
  components: {
  	Slider
  }
}
</script>

组件代码

<template>
  <div class="dx-slider-warpper">
    <div class="dx-slider-content" :draggable="false">
      <div class="dx-slider-track" ref="sliderTrack" :draggable="false" @click="handleClickTrack">
        <div class="dx-slider-fill" :style="{ width: sliderFillPercent + '%' }"></div>
      </div>
      <div
        class="dx-slider-thumb"
        :class="sliderThumbStatusClass"
        ref="sliderThumb"
        :style="{ left: thumbX }"
        @mousedown="thumbDown"
        :draggable="false"
      ></div>
    </div>
    <div class="dx-slider-other">
      <div class="dx-slider-min">{{ min }}</div>
      <div class="dx-slider-value">{{ sliderValue }}</div>

      <div class="dx-slider-max">{{ max }}</div>
    </div>
  </div>
</template>

<script lang="ts">
import { onMounted, ref, watch, SetupContext } from 'vue'
import { Data } from './types/index'
export default {
  props: {
    // 滑动条最小值
    min: {
      require: false,
      default: 0,
      type: Number
    },
    // 滑动条最大值
    max: {
      require: false,
      default: 100,
      type: Number
    },
    // 滑动条每一次滑动的最小值1 必须为整数
    step: {
      require: false,
      default: 1,
      type: Number
    },
    value: {
      require: false,
      default: 0,
      type: Number
    },
    disabled: {
      require: false,
      default: false,
      type: Boolean
    }
  },
  setup(props: Data, context: SetupContext) {
    let maxX = 0
    let thumbWidth = 6

    const sliderTrack = ref<any>()
    const sliderThumb = ref<any>()

    // sliderThumb被激活时的样式名称
    const sliderThumbStatusClass = ref('')

    // 当前的值
    const sliderValue = ref<number>(props.value as number)
    // 进度条填充百分比
    const sliderFillPercent = ref<number>(0)
    // 数值之间的间距
    const distance = Number(props.max) - Number(props.min)

    // value的值必须大于等于min,小于等于max
    if (sliderValue.value < Number(props.min)) {
      sliderValue.value = Number(props.min) || 0
    } else if (sliderValue.value > Number(props.max)) {
      sliderValue.value = Number(props.max) || 100
    }

    const thumbX = ref('0px')
    const thumbTop = ref('-7px')

    onMounted(() => {
      thumbWidth = (sliderThumb.value?.offsetWidth || 0) / 2
      thumbTop.value = -((sliderThumb.value?.offsetHeight || 0) / 2) + 'px'
      maxX = (sliderTrack.value?.offsetWidth || 0) - thumbWidth

      // 初始化,根据sliderValue.value的值,分别计算百分比和thumbX
      sliderFillPercent.value = ((sliderValue.value - Number(props.min)) / distance) * 100
      thumbX.value =
        ((sliderValue.value - Number(props.min)) / distance) * (maxX + thumbWidth) -
        thumbWidth +
        'px'
      if (props.disabled) {
        sliderThumbStatusClass.value = 'dx-slider-thumb-disabled'
      }
    })

    // 点击轨道,thumb跳跃至点击的位置,offsetX是个好东西
    const handleClickTrack = (e: any) => {
      const targetX = e?.offsetX
      if (props.disabled) {
        return
      }
      thumbX.value = targetX - thumbWidth + 'px'
    }

    const thumbDown = (e: any) => {
      if (props.disabled) {
        return
      }

      sliderThumbStatusClass.value = 'dx-slider-thumb-active'

      const startX = e?.clientX
      const initX = parseFloat(thumbX.value)

      const handler = (event: any) => {
        const nowX = event.clientX
        const disX = nowX - startX

        thumbX.value = initX + disX + 'px'
        // 限制可拖拽的范围
        if (initX + disX <= -thumbWidth) {
          thumbX.value = `-${thumbWidth}px`
        }

        if (initX + disX > maxX) {
          thumbX.value = `${maxX}px`
        }
      }

      document.addEventListener('mousemove', handler, false)
      document.addEventListener(
        'mouseup',
        () => {
          sliderThumbStatusClass.value = ''
          document.removeEventListener('mousemove', handler)
        },
        false
      )
    }

    watch(thumbX, () => {
      // 计算百分比,显示fill的进度条
      sliderFillPercent.value =
        ((parseFloat(thumbX.value) + thumbWidth) / (maxX + thumbWidth)) * 100

      // 计算对应的value的值
      const b =
        ((parseFloat(thumbX.value) + thumbWidth) / (maxX + thumbWidth)) * distance +
        Number(props.min)

      // 求余并去除余数
      const a = b % Number(props.step)
      sliderValue.value = b - a
      context.emit('sliderChange', sliderValue.value)
    })

    return {
      thumbDown,
      thumbX,
      thumbTop,
      handleClickTrack,
      sliderTrack,
      sliderThumb,
      sliderFillPercent,
      sliderThumbStatusClass,
      sliderValue
    }
  }
}
</script>

<style lang="scss" scoped>
@import '@/scss/layout.scss';

.dx-slider-warpper {
  // .dx-slider-min,
  // .dx-slider-max {
  //   display: inline-block;
  // }
  .dx-slider-other {
    // overflow: hidden;
    margin: 6px 0;
    position: relative;
    // &::after {
    //   content: '';
    //   clear: both;
    //   display: block;
    // }
    .dx-slider-min {
      position: absolute;
      transform: translateX(-50%);
    }

    .dx-slider-max {
      position: absolute;
      right: 0;
      top: 0;
      transform: translateX(50%);
    }
  }

  .dx-slider-value {
    display: inline-block;
    margin-left: 50%;
    transform: translateX(-50%);
  }

  .dx-slider-content {
    position: relative;
    cursor: pointer;
    -webkit-user-drag: none;
    user-select: none;
    width: calc(100%);
  }

  .dx-slider-track {
    width: 100%;
    height: 6px;
    border-radius: 3px;
    background-color: $background-color;
    overflow: hidden;
    .dx-slider-fill {
      background-color: $blue-middle-color;
      height: 100%;
      width: 20%;
    }
  }

  .dx-slider-track:hover {
    background: #e1e1e1;
  }

  .dx-slider-thumb {
    height: 14px;
    width: 14px;
    border-radius: 50%;
    border: 2px solid $blue-color;
    background: $white-color;
    cursor: pointer;
    position: absolute;
    z-index: 100;
    top: 50%;
    transform: translateY(-50%);
  }

  .dx-slider-thumb-active {
    height: 20px;
    width: 20px;
  }

  .dx-slider-thumb-disabled {
    cursor: not-allowed;
    border: 2px solid $background-color;
    background: $white-color;
  }
}
</style>

参数说明

参数说明
max最大值 number 默认值 0
min最小值 number 默认值 0
step步长 number 必须为整数 最小为1 默认值 1
value滑条当前的值
disabled是否禁用滑条

事件

事件名称说明
sliderChange通过@sliderChange 监听滑条的变化和最新的值

关于dxui组件库

dxui组件库是我个人搭建的vue3 前端交互组件库,倾向于pc网站的交互模式。

  1. 如果你有任何问题,请在博客下方评论留言,我尽可能24小时内回复。
  2. dxui新上线的官网域名变更 http://dxui.cn
  3. npm 官方链接 https://www.npmjs.com/package/vue3-dxui
  4. 如果你想看完整源码 https://github.com/757363985/dxui

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可缺不可滥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值