马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
- <template>
- <view class="slider-container" :style="containerStyle" @touchmove.prevent>
- <view ref="sliderHandle" class="slider-handle" :style="handleStyle" @touchstart="onTouchStart"
- @touchmove.stop="onTouchMove" @touchend="onTouchEnd"></view>
- </view>
- </template>
- <script>
- export default {
- name: 'SliderControl',
- props: {
- mode: {
- type: String,
- default: 'horizontal'
- },
- width: {
- type: [Number, String],
- default: 220
- },
- height: {
- type: [Number, String],
- default: 60
- }
- },
- data() {
- return {
- position: 70,
- isDragging: false,
- startTouch: null,
- startPosition: null,
- lastUpdate: 0,
- lastEmittedValue: 0,
- currentDelta: 0,
- animationTimer: null
- }
- },
- methods: {
- onTouchStart(e) {
- uni.vibrateShort({
- success: () => {
- console.log('短振动成功');
- },
- fail: (err) => {
- console.error('短振动失败:', err);
- }
- });
- e.stopPropagation()
- if (this.animationTimer) {
- clearTimeout(this.animationTimer)
- this.animationTimer = null
- }
- const touch = e.changedTouches[0]
- if (!touch) return
- this.isDragging = true
- this.startTouch = {
- x: touch.pageX,
- y: touch.pageY
- }
- this.startPosition = this.position
- this.lastUpdate = Date.now()
- this.currentDelta = 0
- },
- onTouchMove(e) {
- if (!this.isDragging || !this.startTouch) return
- e.stopPropagation()
- const now = Date.now()
- const timeDiff = now - this.lastUpdate
- if (timeDiff < 16) return
- this.lastUpdate = now
- const touch = e.changedTouches[0]
- if (!touch) return
- const delta = this.mode === 'horizontal' ?
- touch.pageX - this.startTouch.x :
- touch.pageY - this.startTouch.y
- this.currentDelta = this.currentDelta + (delta - this.currentDelta) * 0.9
- let targetPos = this.startPosition + this.currentDelta * 1
- targetPos = Math.max(0, Math.min(targetPos, 180))
- if (Math.abs(targetPos - this.position) > 0.05) {
- const smoothFactor = Math.min(0.08, timeDiff / 250)
- this.position = this.position + (targetPos - this.position) * smoothFactor
- }
- const value = this.mode === 'horizontal' ?
- (this.position - 70) / 70 :
- (70 - this.position) / 70
- const roundedValue = Math.round(value * 100) / 100
- if (Math.abs(roundedValue - this.lastEmittedValue) >= 0.01) {
- this.lastEmittedValue = roundedValue
- this.$emit('change', {
- value: Math.max(-1, Math.min(1, roundedValue))
- })
- }
- },
- onTouchEnd(e) {
- if (!this.isDragging) return
- e.stopPropagation()
- this.isDragging = false
- this.startTouch = null
- this.startPosition = null
- this.currentDelta = 0
- const startPos = this.position
- const startTime = Date.now()
- const duration = 500
- const easeOutQuart = t => 1 - Math.pow(1 - t, 4)
- const animate = () => {
- const elapsed = Date.now() - startTime
- if (elapsed >= duration) {
- this.position = 70
- this.$emit('change', {
- value: 0
- })
- this.animationTimer = null
- return
- }
- const progress = elapsed / duration
- const easeProgress = easeOutQuart(progress)
- this.position = startPos + (70 - startPos) * easeProgress
- this.animationTimer = setTimeout(animate, 16)
- }
- animate()
- }
- },
- beforeDestroy() {
- if (this.animationTimer) {
- clearTimeout(this.animationTimer)
- }
- },
- computed: {
- containerStyle() {
- return {
- width: typeof this.width === 'number' ? `${this.width}px` : this.width,
- height: typeof this.height === 'number' ? `${this.height}px` : this.height,
- backgroundColor: '#000000',
- borderRadius: '30px',
- position: 'relative'
- }
- },
- trackStyle() {
- if (this.mode === 'horizontal') {
- return {
- position: 'absolute',
- left: '20px',
- right: '20px',
- height: '2px',
- top: '30%',
- backgroundColor: 'rgba(255, 255, 255, 0.3)',
- transform: 'translateY(-1px)'
- }
- } else {
- return {
- position: 'absolute',
- top: '20px',
- bottom: '20px',
- width: '2px',
- left: '40%',
- backgroundColor: 'rgba(255, 255, 255, 0.3)',
- transform: 'translateX(-1px)'
- }
- }
- },
- handleStyle() {
- const baseStyle = {
- position: 'absolute',
- width: '50px',
- height: '50px',
- backgroundColor: '#FFFFFF',
- borderRadius: '30px'
- }
- if (this.mode === 'horizontal') {
- return {
- ...baseStyle,
- transform: `translateX(${this.position}px)`,
- top: '0px'
- }
- } else {
- return {
- ...baseStyle,
- transform: `translateY(${this.position}px)`,
- left: '0px'
- }
- }
- }
- }
- }
- </script>
- <style>
- .slider-container {
- flex: 1;
- position: relative;
- background-color: #000000;
- border-radius: 30px;
- }
- .slider-track {
- position: absolute;
- background-color: rgba(255, 255, 255, 0.3);
- }
- .slider-handle {
- position: absolute;
- background-color: #FFFFFF;
- }
- </style>
复制代码 为这个代码创建一个文件SlidePlugin.vue
然后再其他页面进行调用:
- <template>
- <view>
- <SlidePlugin
- mode="vertical"
- :width="50"
- :height="180"
- @change="sliderChange_ver"
- />
- </view>
- </template>
- <script>
- import SlidePlugin from '@/components/SlidePlugin.vue'
- export default {
- components: {
-
- SlidePlugin
- }
- }
- </script>
复制代码 官方提供的无法在一个页面同时滑动2个,所以自己做了一个,这个滑动后会自动返回中心位置,假如中心位置偏离,自己调整下
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |