发布页开发
This commit is contained in:
133
src/components/NTRPSlider/NTRPSlider.tsx
Normal file
133
src/components/NTRPSlider/NTRPSlider.tsx
Normal file
@@ -0,0 +1,133 @@
|
||||
import React, { useState, useCallback } from 'react'
|
||||
import { View, Text } from '@tarojs/components'
|
||||
import Taro from '@tarojs/taro'
|
||||
import './NTRPSlider.scss'
|
||||
|
||||
export interface NTRPRange {
|
||||
min: number
|
||||
max: number
|
||||
}
|
||||
|
||||
// 获取NTRP显示文本的工具函数
|
||||
export const getNTRPRangeText = (range: NTRPRange): string => {
|
||||
if (range.min === 2.0 && range.max === 4.0) {
|
||||
return '不限'
|
||||
}
|
||||
return `${range.min} - ${range.max}`
|
||||
}
|
||||
|
||||
interface NTRPSliderProps {
|
||||
value: NTRPRange
|
||||
onChange: (range: NTRPRange) => void
|
||||
title?: string
|
||||
showTitle?: boolean
|
||||
}
|
||||
|
||||
const NTRPSlider: React.FC<NTRPSliderProps> = ({
|
||||
value = {
|
||||
min: 1.0,
|
||||
max: 5.0
|
||||
},
|
||||
onChange,
|
||||
title = 'NTRP水平要求',
|
||||
showTitle = false
|
||||
}) => {
|
||||
const [activeThumb, setActiveThumb] = useState<'min' | 'max' | null>(null)
|
||||
|
||||
// 计算滑动条位置百分比
|
||||
const getSliderPercentage = useCallback((level: number) => {
|
||||
return ((level - 2.0) / 2.0) * 100
|
||||
}, [])
|
||||
|
||||
// 获取当前NTRP显示文本
|
||||
const currentRangeText = getNTRPRangeText(value)
|
||||
|
||||
const handleSliderTouchStart = useCallback((thumb: 'min' | 'max') => {
|
||||
setActiveThumb(thumb)
|
||||
}, [])
|
||||
|
||||
const handleSliderTouchMove = useCallback((e: any) => {
|
||||
if (!activeThumb) return
|
||||
|
||||
e.preventDefault()
|
||||
const query = Taro.createSelectorQuery()
|
||||
query.select('.ntrp-slider-track').boundingClientRect((rect: any) => {
|
||||
if (rect && !Array.isArray(rect)) {
|
||||
const touch = e.touches[0]
|
||||
const relativeX = touch.clientX - rect.left
|
||||
const percentage = Math.max(0, Math.min(1, relativeX / rect.width))
|
||||
const level = Number((2.0 + percentage * 2.0).toFixed(1))
|
||||
|
||||
if (activeThumb === 'min') {
|
||||
const newMin = Math.min(level, value.max - 0.1)
|
||||
onChange({ min: newMin, max: value.max })
|
||||
} else {
|
||||
const newMax = Math.max(level, value.min + 0.1)
|
||||
onChange({ min: value.min, max: newMax })
|
||||
}
|
||||
}
|
||||
}).exec()
|
||||
}, [activeThumb, value, onChange])
|
||||
|
||||
const handleSliderTouchEnd = useCallback(() => {
|
||||
setActiveThumb(null)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<View className='ntrp-slider'>
|
||||
{showTitle && (
|
||||
<View className='section-title-wrapper'>
|
||||
<Text className='section-title'>{title}</Text>
|
||||
<Text className='section-summary'>{currentRangeText}</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View className='ntrp-control-section'>
|
||||
<View className='ntrp-slider-container'>
|
||||
<View className='ntrp-labels'>
|
||||
<Text className='ntrp-label'>2.0及以下</Text>
|
||||
<Text className='ntrp-label'>4.0及以上</Text>
|
||||
</View>
|
||||
|
||||
<View
|
||||
className='ntrp-slider-track'
|
||||
onTouchMove={handleSliderTouchMove}
|
||||
onTouchEnd={handleSliderTouchEnd}
|
||||
>
|
||||
{/* 背景轨道 */}
|
||||
<View className='slider-bg'></View>
|
||||
|
||||
{/* 选中区间 */}
|
||||
<View
|
||||
className='slider-range'
|
||||
style={{
|
||||
left: `${getSliderPercentage(value.min)}%`,
|
||||
width: `${getSliderPercentage(value.max) - getSliderPercentage(value.min)}%`
|
||||
}}
|
||||
></View>
|
||||
|
||||
{/* 最小值滑块 */}
|
||||
<View
|
||||
className={`slider-thumb ${activeThumb === 'min' ? 'active' : ''}`}
|
||||
style={{ left: `${getSliderPercentage(value.min)}%` }}
|
||||
onTouchStart={() => handleSliderTouchStart('min')}
|
||||
>
|
||||
<View className='thumb-value'>{value.min}</View>
|
||||
</View>
|
||||
|
||||
{/* 最大值滑块 */}
|
||||
<View
|
||||
className={`slider-thumb ${activeThumb === 'max' ? 'active' : ''}`}
|
||||
style={{ left: `${getSliderPercentage(value.max)}%` }}
|
||||
onTouchStart={() => handleSliderTouchStart('max')}
|
||||
>
|
||||
<View className='thumb-value'>{value.max}</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default NTRPSlider
|
||||
Reference in New Issue
Block a user