无缝滚动
第一步 定义 Dom结构
- 第一层
div
最外侧 负责 1️⃣鼠标 交互,2️⃣超出隐藏 - 第二层
div
负责整体动画,通过marginTop
属性实现动画效果1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<div
className="contetn"
ref="content" // react中 通过 this.refs.content 获取 Dom元素
onMouseEnter={this.removeAnimationInterval} // 鼠标移入 清除定时器
onMouseLeave={this.animationInterval} // 鼠标移出 设置定时器
style={{overflow: "hidden"}} // 超出隐藏 多余内容
// onWheel={} // 鼠标滚轴 事件
>
<div style={{ marginTop: scrollData + "px" }}> // 通过`marginTop`属性实现动画效果
{
dutyList.map((item, index) => {
return (
<div className="card" key={`${item.title}:${item.name}${index}`}>
内部元素 非 动画效果 关键,可自定义内容
</div>
)
})
}
</div>
</div>
第二步 获取数据 利用周期执行动画
在请求数据的回调函数 中 设置state, 利用回调 执行 动画方法1
2
3
4
5
6
7
8
9
10getOnDutyListData() {
axios({
method: 'GET',
url: `/OnDutyList`,
}).then(res => {
this.setState({
dutyList: res.data.result
}, () => this.animationInterval()) // 在这里,利用 回调 执行 动画方法。可以避免 在其他 周期里面获取不到 异步数据的情况
})
}
第三步 动画实现效果
1 | animationInterval() { |
操作重点
- 数组操作: 1️⃣
shift()
, 2️⃣push(dutyList[0])
- react:
setState
第四步 鼠标移入移出/ 组件卸载
清除定时器
1 | removeAnimationInterval() { |
附录 完整代码
CarouselList.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79export default class CarouselList extends Component {
constructor(props) {
super(props);
this.state = {
data: this.props.data,
scrollData: 0
};
}
componentDidMount = () => {
this.addHandleTimer();
};
componentWillUnmount = () => {
this.removeHandleTimer();
}
//timers
addHandleTimer = () => {
let { data, scrollData } = this.state;
if (!data || !data.length) return null;
// 定时器
this.timer = setInterval(() => {
if (scrollData > -27) {
scrollData--;
this.setState({
scrollData: scrollData
})
} else {
scrollData = 0;
let firstData = data[0];
data.shift();
data.push(firstData);
}
}, 70);
}
removeHandleTimer = () => {
this.timer && clearInterval(this.timer);
}
handleScroll = e => {
const ev = e || window.event;
e.preventDefault();
const conDom = this.refs["content"];
const speed = 5; // scroll speed
if (ev.deltaY > 0) {
conDom.scrollTop += speed;
} else {
conDom.scrollTop -= speed;
}
};
render() {
const { data, scrollData } = this.state;
return (
<div
ref="content"
onMouseEnter={this.removeHandleTimer}
onMouseLeave={this.addHandleTimer}
onWheel={this.handleScroll}
>
<ul style={{ marginTop: scrollData + "px" }}>
{
data.length > 0 && data.map((item, index) => {
return (
this.props.type === 'simple' ?
<li key={index}><p title={item.value}>{item.value}</p></li>
: <li key={index}><span>{item.id}</span><p title={item.intelligence}>{item.intelligence}</p></li>
)
// 默认:complex
{/*<li key={index}><span>{item.id}</span><p title={item.intelligence}>{item.intelligence}</p></li>*/ }
}
)
}
</ul>
</div>
);
}
}
CarouselList2.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95export default class CarouselList2 extends Component {
constructor(props) {
super(props);
console.log('是大法官',this.props.data)
this.state = {
data: this.props.data,
scrollData: 0
};
}
componentDidMount = () => {
this.addHandleTimer();
};
componentWillUnmount = () => {
this.removeHandleTimer();
};
//timers
addHandleTimer = () => {
let {data, scrollData} = this.state;
if (!data || !data.length) return null;
if(data.length < 5 ) return false;
this.timer = setInterval(() => {
if (scrollData > -52) {
scrollData--;
this.setState({
scrollData: scrollData
})
} else {
scrollData = 0;
let firstData = data[0];
data.shift();
data.push(firstData);
let firstData1 = data[0];
data.shift();
data.push(firstData1);
}
}, 70);
}
removeHandleTimer = () => {
this.timer && clearInterval(this.timer);
}
handleScroll = e => {
const ev = e || window.event;
e.preventDefault();
const conDom = this.refs["content"];
const speed = 6; // scroll speed
if (ev.deltaY > 0) {
conDom.scrollTop += speed;
} else {
conDom.scrollTop -= speed;
}
};
render() {
const {data, scrollData} = this.state;
return (
<div
ref="content"
onMouseEnter={this.removeHandleTimer}
onMouseLeave={this.addHandleTimer}
onWheel={this.handleScroll}
>
<ul style={{marginTop: scrollData + "px"}}>
{
data.length > 0 && data.map((item, index) => {
return (
this.props.type === 'superior' ?
<li key={item.id}>
<p title={item.name}>{item.name}</p>
<p title={item.card}>{item.card}</p>
<p title={item.show}>{item.show}</p>
<p title={item.feedback}>{item.feedback}</p>
<p title={item.state}>{item.state}</p>
</li>
: <li key={item.id}>
<p title={item.name}>{item.name}</p>
<p title={item.card}>{item.card}</p>
<p title={item.time}>{item.time}</p>
<p title={item.origin}>{item.origin}</p>
<p title={item.destination}>{item.destination}</p>
</li>
)
}
)
}
</ul>
</div>
);
}
}
InformationOnDuty.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128import "./InformationOnDuty.scss"
import { hidden } from "ansi-colors";
class InformationOnDuty extends Component {
constructor(props) {
super(props);
this.state = {
dutyList: [],
scrollData: 0,
inital: true
};
this.getOnDutyListData = this.getOnDutyListData.bind(this);
this.animationInterval = this.animationInterval.bind(this);
this.removeAnimationInterval = this.removeAnimationInterval.bind(this);
this.getOnDutyListData();
}
getOnDutyListData() {
axios({
method: 'GET',
url: `/OnDutyList`,
}).then(res => {
this.setState({
dutyList: res.data.result
}, () => this.animationInterval())
})
}
animationInterval() {
let { scrollData, dutyList } = this.state;
if (!dutyList.length) return;
this.state.animationInterval = setInterval(() => {
this.setState({
scrollData: scrollData--
});
let firstItem = dutyList[1];
if (scrollData < 0 && scrollData > -2) {
if (this.state.inital) {
dutyList.push(dutyList[0]);
this.setState({
inital: false
})
}
}
// dutyList.push(firstItem);
if (scrollData % 128 === 0) {
// debugger
dutyList.shift();
dutyList.push(firstItem);
scrollData = 0;
// debugger
}
// if (scrollData > -113) {
// let firstItem = dutyList[0];
// // dutyList.shift();
// // dutyList.push(firstItem);
// this.setState({
// scrollData: scrollData--
// })
// } else {
// scrollData = 0;
// let firstItem = dutyList[0];
// dutyList.shift();
// dutyList.push(firstItem);
// }
}, 60)
}
removeAnimationInterval() {
this.state.animationInterval && clearInterval(this.state.animationInterval);
}
componentDidMount() {
}
componentWillReceiveProps() {
debugger
}
componenWillUnmount() {
this.removeAnimationInterval();
}
render() {
let { dutyList, scrollData } = this.state;
return (
<div className="InformationOnDuty">
<div className="title">
<div className="tit1"><span>值班信息</span></div>
<div className="tit2"><span>查看值班表</span></div>
</div>
<div
className="contetn"
ref="content"
onMouseEnter={this.removeAnimationInterval}
onMouseLeave={this.animationInterval}
style={{overflow: "hidden"}}
// onWheel={}
>
<div style={{ marginTop: scrollData + "px" }}>
{
dutyList.map((item, index) => {
return (
<div className="card" key={`${item.title}:${item.name}${index}`}>
<div className="row1">
<span>{item.title} </span><b> | </b><span>{item.name}</span>
</div>
<div className="row2">
<span className={item.title.length > 3 ? 'nbsp4' : 'nbsp3'}>电话 </span><b> | </b><span>{item.phone}</span>
</div>
</div>
)
})
}
</div>
</div>
</div>
)
}
}
export default InformationOnDuty;