- react框架
css的样式代码如下
.carousel{
color: #fff;
margin-top: 80px;
text-align: center;
position: relative;
width: 100%;
height: 350px;
}
.carousel-item{
width: 160px;
font-size: 14px;
height: 150px;
position: absolute;
left: 0;
top: 0;
animation-name: xAni,yAni,scaleAni;
animation-iteration-count: infinite;
animation-duration: 10s,10s,20s;
animation-timing-function: cubic-bezier(0.36, 0, 0.64, 1);
animation-direction: alternate;
}
.carousel-item p{
padding: 0;
margin: 0;
}
/* 定义动画 */
@keyframes xAni {
0% {
left: -50px;
}
100% {
left: calc(100% - 110px);
}
}
@keyframes yAni {
0% {
top: 0;
}
100% {
top: 100%;
}
}
@keyframes scaleAni {
0% {
transform: scale(0.5);
}
50% {
transform: scale(1);
}
100% {
transform: scale(0.5);
}
}
主页面的代码
// 导入样式
import "./carousel.css"
// 导入图片
import dingwei from '../../../assets/images/dingwei_nor.png'
import dingwei_hov from '../../../assets/images/dingwei_hov.png'
import fenxi from '../../../assets/images/fenxi_nor.png'
import fenxi_hov from '../../../assets/images/fenxi_hov.png'
import huaxiang from '../../../assets/images/huaxiang_nor.png'
import huaxiang_hov from '../../../assets/images/huaxiang_hov.png'
import jiankong from '../../../assets/images/jiankong_nor.png'
import jiankong_hov from '../../../assets/images/jiankong_hov.png'
import tingche from '../../../assets/images/tingche_nor.png'
import tingche_hov from '../../../assets/images/tingche_hov.png'
import toukui from '../../../assets/images/toukui_nor.png'
import toukui_hov from '../../../assets/images/toukui_hov.png'
// 导入hooks
import {useRef, useEffect, useState} from 'react'
const Carousel = () => {
// 定义数据用于渲染旋转木马
const [data, setData] = useState([
{
id: 1,
url: dingwei,
hov_url: dingwei_hov,
text: '车辆定位系统',
active: false
},
{
id: 2,
url: fenxi,
hov_url: fenxi_hov,
text: '可视化作战平台',
active: false
},
{
id: 3,
url: huaxiang,
hov_url: huaxiang_hov,
text: '交通安全画像系统',
active: false
},
{
id: 4,
url: jiankong,
hov_url: jiankong_hov,
text: '交通态势监控系统',
active: false
},
{
id: 5,
url: tingche,
hov_url: tingche_hov,
text: '自动停车系统',
active: false
},
{
id: 6,
url: toukui,
hov_url: toukui_hov,
text: '未带头盔识别系统',
active: false
}
])
// 定义变量用于获取标签
const carouselBox = useRef(null)
// 模拟生命周期中获取标签
useEffect(() => {
// console.log(111, carouselBox.current.children);
// 遍历所有子标签设置延迟动画的时间
for (let a = 0; a < carouselBox.current.children.length; a++) {
carouselBox.current.children[a].style['animation-delay'] = `${-5 - a * 3.3}s,-${a * 3.3}s,-${a * 3.3}s`
}
}, [])
// 事件函数
const onmouseenter = (id) => {
// 让动画停止
for (let a = 0; a < carouselBox.current.children.length; a++) {
carouselBox.current.children[a].style['animation-play-state'] = `paused`
}
// 让当前这个变 hov 图片 ==> 知道这是哪一个要变
// console.log(222, id);
// 根据id找到对应的这个数据
let carouselData = data.find(item => item.id === id)
// 修改这个数据的active
carouselData.active = !carouselData.active
// 重新设置data数据
// setData(data) // 新data和旧data内存地址没有变化,其中的深层次数据变化了,但是监听不到,页面不会重新渲染
setData([...data])
// console.log(333, data);
}
const onmouseleave = (id) => {
// 让动画停止
for (let a = 0; a < carouselBox.current.children.length; a++) {
carouselBox.current.children[a].style['animation-play-state'] = `running`
}
// 让当前这个变 hov 图片 ==> 知道这是哪一个要变
// console.log(222, id);
// 根据id找到对应的这个数据
let carouselData = data.find(item => item.id === id)
// 修改这个数据的active
carouselData.active = !carouselData.active
// 重新设置data数据
setData([...data])
// console.log(333, data);
}
const onclick = (id) => {
let carouselData = data.find(item => item.id === id)
alert(carouselData.text)
}
return (
<div className="carousel" ref={carouselBox}>
{/* 循环渲染:数组的map方法 */}
{data.map(item => {
return (
<div className="carousel-item" key={item.id} onMouseEnter={(e) => onmouseenter(item.id)} onMouseLeave={(e) => onmouseleave(item.id)} onClick={() => onclick(item.id)}>
{/* {item.active ? <img src={item.hov_url} /> : <img src={item.url} />} */}
<img src={item.active ? item.hov_url : item.url} />
<p>{item.text}</p>
</div>
)
})}
</div>
)
}
export default Carousel
上面的代码通过帧动画的形式进行走向和时间间隔多少秒走一个形成一个转盘的形式走动,并且实现了鼠标移入暂停,图片高亮。鼠标移出继续走动消除高亮(高亮的实现其实就是切换了一个图片)。以及点击每项的时候显示弹窗弹出该图片下的文本