JS
import React, { useState, useEffect } from 'react'
import styles from './style.less'
import { Slider } from 'antd';
import { PlusOutlined, MinusOutlined } from '@ant-design/icons';
const end = 1440 // 总长度
const stepCount = 60 // 步长
const contentStyle = { // 是背景渐变 而不是给文字添加颜色 所需要的属性
cursor: 'pointer',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
// background: 'linear-gradient(to right, rgba(182, 54, 128) 0%, rgba(16, 202, 100, ) 100%)' // 不知道为何不生效 我单独 在 className 写入了
};
const index = () =>
{
const [currentTime, setCurrentTime] = useState('18:00')
useEffect(() =>
{ // 发送数据请求 设置订阅/启动定时器 手动更改 DOM 等 ~
setCurrentTime(ThisTime())
return () =>
{ // 组件卸载之前 做一些收尾工作 比如清楚定时器/取消订阅 等 ~
}
}, []) // 检测数组内变量 如果为空 则监控全局
// 获取实时小时
const ThisTime = () =>
{
let newThisTime = new Date().getHours().toString().padStart(2, '0').padEnd(5, ':00')
return newThisTime
}
// 当数据改变时 得到的是步长数 转换为加工过的时间
const handleChange = async value =>
{
try
{
let newValue = parseFloat(tipFormatter(value)) // 当前小时 08:00 => 8
let newThisTime = parseFloat(ThisTime()) // 实时小时
if (newValue <= newThisTime)
{
setCurrentTime(tipFormatter(value))
}
} catch (err)
{
console.log(err);
}
}
// 时间包装
const tipFormatter = value =>
{
let newValue = (value / 60).toString().padStart(2, '0').padEnd(5, ':00')
return newValue
}
// 时间转为步长
const TimeToStep = currentTimeStr =>
{
let currentTime = currentTimeStr.split(':');
if (currentTime.length === 2)
{
// 最新的步长数
let newStep = currentTime[0] * 60 + currentTime[1] * 1
return newStep
} else
{
return 0;
}
}
// 时间减1
const reduceClick = () =>
{
let CurrentStep = TimeToStep(currentTime) // 当前时间
let CurrentTimeStep = TimeToStep(ThisTime()) // 实时时间
if (CurrentStep <= CurrentTimeStep && CurrentStep > 0)
{
setCurrentTime(tipFormatter((CurrentStep -= 60)));
} else
{
setCurrentTime('00:00');
}
}
// 时间加1
const subjoinClick = () =>
{
let CurrentStep = TimeToStep(currentTime) // 当前时间
let CurrentTimeStep = TimeToStep(ThisTime()) // 实时时间
if (CurrentStep < CurrentTimeStep && CurrentStep >= 0)
{
setCurrentTime(tipFormatter(Number((CurrentStep += 60))));
} else
{
// 如果当前时间 大于等于时间轴 则显示这个时间
setCurrentTime(ThisTime());
}
}
const SliderDom = () =>
{
const marks = new Array
let newValue = parseFloat(currentTime) // 当前小时 08:00 => 8
let newThisTime = parseFloat(ThisTime()) // 实时小时
console.log(newValue, newThisTime);
for (let index = 0; index <= end / stepCount; index++)
{
let ladder = (end / (end / stepCount)) * Number(index) // 总长度 / 60 = 24小时
console.log(index, 'index');
marks[ladder] = ({
style: {
color: 'red', // 因为设置过背景颜色颜色了 所以这里不会生效 而且仿佛还只有 color 会生效
// textAlign: 'right' // 没生效 ~
},
// index 也对应着 所处的每个小时 所以 要拿 index 判断 而不是 newValue !
label: (<strong style={contentStyle} className={index <= newThisTime ? styles.active : index % 2 === 0 ? styles.marksEven : styles.marksOdd} >
{tipFormatter((end / 24) * index)
}</strong>),
})
}
return (
<Slider
className={styles.Slider}
marks={marks}
max={end}
step={stepCount}
value={TimeToStep(currentTime)} // 时间转换后的步长
onChange={handleChange}
tipFormatter={tipFormatter}
disabled={false} // 禁止点击 否
/>
)
}
return (
<div className={styles.container}>
<div className={styles.reduce} onClick={reduceClick}>
<MinusOutlined width={100} />
</div>
{SliderDom()}
<div className={styles.subjoin} onClick={subjoinClick}>
<PlusOutlined className={styles.subjoin} />
</div>
</div>
)
}
export default index
CSS
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
.active {
background: linear-gradient(to right, rgb(126, 228, 9) 0%, rgb(211, 19, 77) 100%);
}
.marksEven {
// 偶数
background: linear-gradient(to right, rgba(182, 54, 128) 0%, rgba(16, 202, 100, ) 100%);
}
.marksOdd {
// 奇数
display: none;
// background: linear-gradient(to right, rgb(231, 120, 157, .3) 0%, rgb(254, 225, 64, .1) 100%);
}
// .active,
// .marksEven,
// .marksOdd {
// cursor: pointer;
// -webkit-background-clip: text;
// -webkit-text-fill-color: transparent;
// }
.Slider {
background: #262626;
margin: 0px 5px 0px 5px;
height: 40px;
width: 80%;
}
.reduce,
.subjoin {
width: 40px;
height: 40px;
line-height: 40px;
background: #262626;
text-align: center;
cursor: pointer;
border-radius: 8px 8px 8px 8px;
}
// antd 样式
:global {
.ant-slider-rail {
height: 1px !important;
background: #fff !important;
top: 7px !important;
}
// 显示的距离
.ant-slider-track {
height: 1px !important;
background: transparent !important;
}
// 字体颜色
// .ant-slider-mark-text {
// color: #fff !important;
// }
.ant-slider-handle:focus {
outline: none !important;
box-shadow: none !important;
}
.ant-slider:hover .ant-slider-handle:not(.ant-tooltip-open) {
border: none;
}
.ant-slider-dot {
width: 1px !important;
height: 8px !important;
border: 0px solid rgb(85, 62, 62) !important;
margin-left: 0px !important;
}
// .ant-slider-handle {
// width: 1px !important;
// height: 30px !important;
// border: none;
// background: rgb(202, 12, 25);
// margin-top: -10px !important;
// transform: none !important;
// }
// .ant-slider-mark {
// top: 20px !important;
// }
// .ant-slider-mark {
// position: absolute;
// top: 14px;
// left: 0;
// width: 100%;
// font-size: 28px;
// }
}
}