React
-用swiper
实现多行交错、同速、跑马灯效果的弹幕式轮播(总)数据轮播(三行交错、同速、跑马灯效果),动图如下:
swiper
react
-swiper8
swiper8
npm i swiper@8
或者
yarn add swiper@8
app.jsx
全局引入app.jsx
// swiper【Autoplay:自动播放 ,Pagination:分页 ,Navigation:标记页数】
import SwiperCore, { Autoplay, Pagination, Navigation } from 'swiper';
SwiperCore.use([Autoplay, Pagination, Navigation])
swiper
写的弹幕item
组件 —— swiperComponent
⭐️swiperComponent.jsx
【关键点】 实现跑马灯效果的关键点用【关键】标注出来了~
/**
* swiper写的弹幕item组件
*/
'use strict';
import React from 'react';
import { observer } from 'mobx-react';
import { Swiper, SwiperSlide } from "swiper/react"; // 引入swiper,实现轮播
import 'style-loader!css-loader!swiper/swiper-bundle.css'; // 引入swiper的css
import './swiperComponent.less';
@observer
class SwiperComponent extends React.Component {
constructor(props) {
super(props);
}
// 【非常重要】fixed: 多行swiper情况下,第一次进入页面时,某一行 出现 先快后慢、滑动一轮后才和其余几行达成一致 的步调
componentDidMount() {
this.carouselSwiper?.autoplay.stop(); // 关闭自动切换
// 加个延时
setTimeout(() => {
this.carouselSwiper?.autoplay.start(); // 开启自动切换
},500)
}
// TODO: 根据自己需求对下方两个数据进行调整(可以把autoplay关闭后慢慢调)
firstContainerSlidesPerView = 1.25; // 第一个swiper-container的slidesPerView
SecondSlidePaddingLeft = 0.8; // 第二个swiper-slide的paddingLeft值(第一个的值为0)
render() {
const {
// 索引值
index,
// 当前轮播信息
carouselInfo,
} = this.props;
return (
<div className="barrageInner">
{
carouselInfo?.length > 0 &&
<Swiper
className="barrage"
// 设置slider容器能够同时显示的slides数量(carousel模式)
slidesPerView={this.firstContainerSlidesPerView - index * 0.15}
//【关键】匀速时间
speed={3000}
//【关键】设置为true则变为free模式
freeMode={true}
// 设置为true 则开启loop(无限循环)模式
loop={true}
// 自动播放
autoplay={{
delay: 0, //【关键】自动切换的时间间隔,单位ms
}}
onSwiper={swiper => { this.carouselSwiper = swiper; }}
style={{ paddingLeft: `${index * this.SecondSlidePaddingLeft}rem` }}
>
{
carouselInfo?.map((item, index) => {
return (
<SwiperSlide className="barrageItem" key={index}>
{/* slide背景图 */}
<div className="barrageItemBg"></div>
{/* slide内容 */}
<div className="barrageText text-hidden-ellipsis">{item}</div>
</SwiperSlide>
)
})
}
</Swiper>
}
</div>);
}
}
export default SwiperComponent;
swiperComponent.less
【关键点】 给
.swiper-wrapper
增加样式transition-timing-function: linear;
实现swiper
匀速轮播~
.barrageInner {
width: 100%;
height: 100%;
/** 相当于swiper-container */
.barrage {
width: 100%;
height: 100%;
box-sizing: border-box;
/**【关键】swiper实现匀速轮播 */
&>.swiper-wrapper {
-webkit-transition-timing-function: linear; /*之前是ease-out*/
-moz-transition-timing-function: linear;
-ms-transition-timing-function: linear;
-o-transition-timing-function: linear;
transition-timing-function: linear;
}
/** 相当于swiper-slide */
.barrageItem {
position: relative;
/** 不需要写宽度,用swiper-slide的默认宽度 */
height: 62px;
.barrageItemBg, .barrageText {
/** slide背景图和slide内容的宽度 */
width: 467px;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
/** slide背景 */
.barrageItemBg {
opacity: .4;
background: url("../../assets/startPage/danmuBg.png") no-repeat center/cover;
}
/** slide内容 */
.barrageText {
padding: 0 10px;
box-sizing: border-box;
font-size: 26px;
color: #4478a0;
text-align: center;
line-height: 62px;
}
/** 文字展示固定宽度,超出省略号展示 */
.text-hidden-ellipsis {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
/** 设置文字方向:从左往右 */
direction: ltr;
}
}
}
}
homePage.jsx
【注意】
多行
交错、同速、跑马灯效果的弹幕式轮播 里的行数
修改方法如下哦:小萝卜儿们,想实现好多行,就将如下代码里
state
的devideNum
修改成对应理想行数即可哦~
/**
* 活动首页
*/
'use strict';
import React from 'react';
import { observer } from 'mobx-react';
import SwiperComponent from "@src/components/swiperComponent/swiperComponent"; // 引入弹幕item组件
import './homePage.less';
@observer
class HomePage extends React.Component {
constructor(props) {
super(props);
this.state = {
/** 弹幕信息 */
fakeCarouselData: [],
/** 需划分的swiper份数 */
devideNum: 3,
}
}
// 测试数据
carouselInfo = ['嘻嘻嘻1', '啦啦啦啦1', '嘻嘻嘻2', '哈哈哈2', '嘻嘻嘻3'];
componentDidMount() {
const result = this.cut(this.state.devideNum, this.carouselInfo);
console.log('result', result); // [['嘻嘻嘻1', '啦啦啦啦1'],['嘻嘻嘻2', '哈哈哈2'],['嘻嘻嘻3']]
this.setState({
fakeCarouselData: result,
})
}
/*
将一个含未知个数内容的数组,划分成num份
* num {Int} 需划分的份数
* arr {Array} 数据源
*/
cut = (num, arr) => {
if (num < 2) {
console.error("参数不合法");
}
const length = arr.length;
if (length == 0) {
return [];
}
const step = Math.ceil(length / num);
const list = [];
for (let i = 0; i < num; i++) {
const start = i * step;
const end = length - i * step > step ? (i + 1) * step : length;
const part = arr.slice(start, end);
list.push(part);
}
return list;
}
// 在组件卸载及销毁之前 清空掉swiper里的数据【数据为动态数据时,一定要加这步哦:https://blog.csdn.net/weixin_48850734/article/details/127509051?spm=1001.2014.3001.5501】
componentWillUnmount() {
this.carouselInfo = [];
}
render() {
const { fakeCarouselData } = this.state;
return (
<div className="homePage">
{/* 弹幕区域【swiper-no-swiping: 禁止手动滑动】*/}
<div className="barrageContent swiper-no-swiping">
{/* 遍历fakeCarouselData数组 */}
{
fakeCarouselData.map((item, index) => {
return (
<div className="barrageOuter" key={index}>
<SwiperComponent index={index} carouselInfo={item} />
</div>
)
})
}
</div>
</div>
);
}
}
export default HomePage;
homePage.less
.homePage {
width: 750px;
height: 100%;
position: absolute;
/** swiper实现的弹幕区域 */
.barrageContent {
width: 750px;
height: 264px;
position: absolute;
left: 0;
top: 1106px;
/** 轮播的swiper */
.barrageOuter {
width: 100%;
height: 62px;
&:not(:last-child) {
margin-bottom: 39px;
}
}
}
}
JS
-将一个含未知个数内容的数组,划分成num
份/*
将一个含未知个数内容的数组,划分成num份
* @param {Int} num 需划分的份数
* @param {Array} arr 数据源
* @return {Array}
*/
function cut(num, arr) {
if (num < 2) {
console.error("参数不合法");
}
const length = arr.length;
if (length == 0) {
return [];
}
const step = Math.ceil(length / num);
const list = [];
for (let i = 0; i < num; i++) {
const start = i * step;
const end = length - i * step > step ? (i + 1) * step : length;
const part = arr.slice(start, end);
list.push(part);
}
return list;
}
cut(3,['嘻嘻嘻1', '啦啦啦啦1', '嘻嘻嘻2', '哈哈哈2', '嘻嘻嘻3']); // [['嘻嘻嘻1', '啦啦啦啦1'], ['嘻嘻嘻2', '哈哈哈2'], ['嘻嘻嘻3']]