JS
import React, { useState, useEffect, useRef } from 'react'
import styles from './style.less'
import { RestOutlined, RedditOutlined } from '@ant-design/icons'
import { DS } from './utils/index'
const data = [
{ event: '向女神表白被拒', location: '钱柜KTV', src: 'https://www.dataojocloud.com/dataeye/v1/data/image/get?imageid=61bc5c91fd73384a0bde157f', id: 1 },
{ event: '打架斗殴', location: '孙浩家里', src: 'https://www.dataojocloud.com/dataeye/v1/data/image/get?imageid=61bc5c9422a0c63075b01ec5', id: 2 },
{ event: '发酒疯导致被打', location: '郭帅家里', src: 'https://www.dataojocloud.com/dataeye/v1/data/image/get?imageid=617a55a011001e6b8ea0cce3', id: 3 },
{ event: '连续通宵', location: '鸣鹿网吧', src: 'https://www.dataojocloud.com/dataeye/v1/data/image/get?imageid=61bc5c982ee1bd7d90486745', id: 4 },
{ event: '挑衅路人', location: '鹿邑县城', src: 'https://www.dataojocloud.com/dataeye/v1/data/image/get?imageid=617a55a422a0c62f56684521', id: 5 },
{ event: '唱歌音质过差', location: '麦地', src: 'https://www.dataojocloud.com/dataeye/v1/data/image/get?imageid=617a5596fd73380b818dc300', id: 6 },
{ event: '爬树掉下去', location: '后陈西头', src: 'https://www.dataojocloud.com/dataeye/v1/data/image/get?imageid=617a559d2ee1bd5a04779569', id: 7 },
]
const Index = () =>
{
const scrollRef = useRef()
const scrollBar = useRef()
const [dsContainer, setDsContainer] = useState(null)
useEffect(() =>
{ // 发送数据请求 设置订阅/启动定时器 手动更改 DOM 等 ~
DS({ wrapper: scrollRef.current, scrollBar: scrollBar.current }, setDsContainer)
return () =>
{ // 组件卸载之前 做一些收尾工作 比如清楚定时器/取消订阅 等 ~
}
}, []) // 检测数组内变量 如果为空 则监控全局
const scrollDom = () =>
{
return (
<div id='wrapper' ref={scrollRef} className={styles.wrapper}>
<div className={styles.content}>
{data.map((data, index) => (
<div key={data.id} className={styles.coreItem}>
<div className={styles.detail}>
<div className={styles.detailItem}>
<div className={styles.round}></div>
<span className={styles.event}>事件</span>
<span className={styles.colon}>:</span>
<span className={styles.eventDetails}>{data.event}</span>
</div>
<div className={styles.detailItem}>
<div className={styles.round}></div>
<span className={styles.event}>地点</span>
<span className={styles.colon}>:</span>
<span className={styles.eventDetails}>{data.location}</span>
</div>
</div>
<div className={styles.coreItemImg}>
<img src={data.src} alt="" />
</div>
</div>
))}
</div>
<div ref={scrollBar} className={styles.horizontal_scrollbar}>
<div className={styles.horizontal_indicator}></div>
</div>
</div>
)
}
return (
<div className={styles.container}>
<div className={styles.overall}>
<div className={styles.head}>
<RedditOutlined className={styles.RedditOutlined} />
<span className={styles.headTitle}>羽神天下第一</span>
</div>
<div className={styles.core}>
<div className={styles.coreLeft}>
<div className={styles.leftBox}>
<RestOutlined className={styles.RestOutlined} />
<div className={styles.article}>
<span className={styles.articleQuantity}>223</span>
<span className={styles.unit}>件</span>
</div>
<span className={styles.abnormalOccurrence}>羽神异常事件</span>
</div>
</div>
<div className={styles.line}></div>
{scrollDom()}
</div>
</div>
</div >
)
}
export default Index
utils
import BScroll from '@better-scroll/core' // BScroll 核心
import MouseWheel from '@better-scroll/mouse-wheel' // 引入滚轮
import Scrollbar from '@better-scroll/scroll-bar'
BScroll.use(MouseWheel)
BScroll.use(Scrollbar)
export const DS = (container, setDsContainer = false, action = false) =>
{
const { wrapper, scrollBar } = container // wrapper 可以是 id scrollBar 必须是 Ref
const { payload } = action
if (wrapper)
{
if (typeof wrapper === 'string')
{
let wrapperRef = document.querySelector('#' + wrapper)
deployX(wrapper ? [wrapperRef, scrollBar] : null, setDsContainer ? setDsContainer : null, payload ? payload.callback : null)
} else
{
deployX(wrapper ? [wrapper, scrollBar] : null, setDsContainer ? setDsContainer : null, payload ? payload.callback : null)
}
}
}
// X轴配置
const deployX = (container, setDsContainer) => // horizontal 拿到自定义滚动条 ref
{
let [wrapper, horizontal] = container // 结构赋值
if (wrapper)
{
let ds = new BScroll(wrapper, {
probeType: 0, // 默认0 不侦测 0和1 都不侦测 2:在手指滚动的过程中侦测 手指离开后的惯性滚动过程中不侦测 3:只要是滚动 都进行侦测
click: true, // 可以点击 用法:要覆盖本机滚动,BetterScroll必须禁止某些默认浏览器行为,例如鼠标单击。如果您希望您的应用程序响应click事件,则必须将该选项显式设置为true。然后BetterScroll将向其_constructed调度事件添加一个私有属性,该属性的值为true。
mouseWheel: true, // 鼠标滚轮
scrollX: true,
scrollY: false,
scrollbar: {
customElements: [horizontal], // 自定义滚动条 [horizontal,vertical] 横竖 我只用了 horizontal 滚动条 DOM 传过来的 REF
fade: true, // 淡入淡出
interactive: true,
scrollbarTrackClickable: true
} // 滚动条
})
setDsContainer(ds) // 保存 ds
}
}
CSS
.container {
position: absolute;
width: 100%;
height: 100%;
background-color: rgb(207, 108, 108);
.overall {
margin: 200px auto;
position: relative;
width: 1000px;
height: 285px;
border-radius: 4px;
box-sizing: border-box;
background: linear-gradient(0deg, rgba(10, 15, 22, .7) 0%, rgba(21, 31, 45, .7) 100%);
line-height: 1.45;
}
img {
width: 100%;
height: 100%;
}
}
.head {
display: flex;
align-items: center;
width: 100%;
height: 60px;
background: linear-gradient(0deg, rgba(27, 71, 143, .9) 0%, rgba(21, 31, 45, .9) 100%);
border-radius: 4px;
.RedditOutlined {
margin-left: 22px;
font-size: 38px;
color: rgb(45, 198, 224);
}
.headTitle {
margin-left: 8px;
font-size: 30px;
font-weight: 600;
color: #FFFFFF;
background: linear-gradient(0deg, rgba(90, 203, 255, .9) 0%, rgba(26, 134, 255, .9) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.core {
display: flex;
.coreLeft {
width: 249px;
height: calc(~'100% - 60px');
overflow: hidden;
.leftBox {
padding: 20px 0 0 20px;
margin: 21px 30px 25px 20px;
width: 196px;
height: 179px;
background: linear-gradient(0deg, #16508D 0%, #041528 100%);
border: 1px solid rgba(24, 63, 113, 0.4);
border-radius: 4px;
.RestOutlined {
font-size: 42px;
color: cornflowerblue;
}
.article {
display: flex;
color: #FFFFFF;
.articleQuantity {
font-size: 38px;
font-weight: 500;
}
.unit {
margin-left: 10px;
padding-top: 20px;
font-size: 20px;
font-weight: 400;
}
}
.abnormalOccurrence {
display: flex;
font-size: 22px;
font-weight: 400;
color: #AFC6E4;
}
}
}
.line {
margin-top: 18px;
width: 1px;
height: 185px;
background: rgba(50, 93, 154, .6);
border-radius: 4px;
}
.wrapper {
position: relative;
white-space: nowrap;
width: 753px;
overflow: hidden;
.content {
display: inline-block;
.coreItem {
display: inline-block;
margin-left: 31px;
width: 216px;
height: 100%;
.detail {
padding-top: 18px;
height: 81px;
line-height: 1.45;
.detailItem {
display: flex;
align-items: center;
.round {
width: 8px;
height: 8px;
background: rgba(249, 81, 3, 1);
border-radius: 50%;
}
.event {
margin-left: 6px;
color: rgba(180, 217, 244, 1);
font-size: 20px;
}
.colon {
margin-left: 2px;
color: rgba(180, 217, 244, 1);
font-size: 20px;
}
.eventDetails {
margin-left: 10px;
font-size: 20px;
color: rgba(255, 255, 255, 1);
}
}
}
}
.coreItemImg {
width: 100%;
height: 119px;
border-radius: 4px;
}
}
}
// 自定义滚动条
.horizontal_scrollbar {
position: absolute;
left: 50%;
bottom: 10px;
width: 100px;
height: 7px;
border-radius: 5px;
transform: translateX(-50%) translateZ(0);
background: linear-gradient(to right, rgba(182, 54, 128) 0%, rgba(16, 202, 100, ) 100%);
.horizontal_indicator {
height: 100%;
width: 20px;
border-radius: 5px;
background-color: #db8090;
}
}
}