未验证 提交 e9c482db 编写于 作者: L lkjh3214 提交者: GitHub

feat: Swiper组件能力补齐,新增demo,添加国际化文档 (#196)

上级 ccc6e7e9
import React from 'react'
import { render, waitFor } from '@testing-library/react'
import '@testing-library/jest-dom'
import { act } from 'react-dom/test-utils'
import { Swiper } from '../swiper'
import { SwiperItem } from '../../swiperitem/swiperitem'
import { triggerDrag } from '@/utils/test/event'
function sleep(delay = 0): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, delay)
})
}
test('should render width and height', () => {
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg',
]
const state: any = {
height: 150,
initPage: 0,
width: 375,
}
const { height, initPage, width } = state
const onChange = (e: number) => {}
const { container } = render(
<Swiper
height={height}
width={width}
autoPlay="2000"
initPage={initPage}
onChange={onChange}
paginationVisible
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
)
const swiper = container.querySelectorAll('.nut-swiper__inner')[0]
const item = container.querySelectorAll('.nut-swiper-item')[0]
expect(swiper).toHaveStyle({
height: '150px',
})
expect(item).toHaveStyle({
width: '375px',
})
})
test('should render initpage', () => {
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg',
]
const state: any = {
height: 150,
initPage: 1,
width: 375,
}
const { height, initPage, width } = state
const onChange = (e: number) => {}
const { container } = render(
<Swiper
height={height}
width={width}
initPage={initPage}
onChange={onChange}
paginationVisible
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
)
const swiper = container.querySelectorAll('.nut-swiper__inner')[0]
expect(swiper).toHaveStyle({
transform: 'translate3D(-375px,0,0)',
})
})
test('should render direction', () => {
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg',
]
const state: any = {
height: 150,
initPage: 1,
width: 375,
direction: 'vertical',
}
const { height, initPage, width, direction } = state
const onChange = (e: number) => {}
const { container } = render(
<Swiper
height={height}
width={width}
direction={direction}
initPage={initPage}
onChange={onChange}
paginationVisible
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
)
const swiper = container.querySelectorAll('.nut-swiper__inner')[0]
expect(swiper).toHaveStyle({
transform: 'translate3D(0,-150px,0)',
})
})
test('should render pagination', () => {
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg',
]
const state: any = {
height: 150,
initPage: 1,
width: 375,
paginationColor: 'red',
}
const { height, initPage, width, paginationColor } = state
const onChange = (e: number) => {}
const { container } = render(
<Swiper
height={height}
width={width}
initPage={initPage}
onChange={onChange}
paginationVisible
paginationColor={paginationColor}
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
)
const paginationItem = container.querySelectorAll(
'.nut-swiper__pagination-item'
)
expect(paginationItem).toHaveLength(4)
expect(paginationItem[1]).toHaveStyle({
backgroundColor: 'red',
})
})
test('should render loop and auto-play', async () => {
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg',
]
const state: any = {
height: 150,
initPage: 0,
width: 375,
direction: 'vertical',
}
const { height, initPage, width, direction } = state
const onChange = (e: number) => {}
const { container } = render(
<Swiper
height={height}
width={width}
initPage={initPage}
onChange={onChange}
autoPlay="100"
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
)
const swiper = container.querySelectorAll('.nut-swiper__inner')[0]
await waitFor(() => {
expect(swiper).toHaveStyle({
transform: 'translate3D(-375px,0,0)',
})
})
})
test('should not allow to drag when touchable is false', () => {
const onChange = jest.fn()
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg',
]
const state: any = {
height: 150,
initPage: 0,
width: 375,
direction: 'vertical',
}
const { height, initPage, width, direction } = state
const { container } = render(
<Swiper
height={height}
width={width}
initPage={initPage}
onChange={onChange}
touchable={false}
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
)
const swiper = container.querySelectorAll('.nut-swiper__inner')[0]
triggerDrag(swiper, 220, 0)
expect(swiper).toHaveStyle({
transform: 'translate3D(0px,0,0)',
})
})
test('should not allow to drag when loop is false', async () => {
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg',
]
const state: any = {
height: 150,
initPage: 3,
width: 375,
direction: 'vertical',
}
const { height, initPage, width, direction } = state
let _container: any
act(() => {
const { container } = render(
<Swiper
height={height}
width={width}
initPage={initPage}
loop={false}
autoPlay="100"
data-testid="swiper_container"
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
)
_container = container
})
await waitFor(
async () => {
await sleep(2000)
const swiper = _container.querySelectorAll('.nut-swiper__inner')[0]
expect(swiper).toHaveStyle({
transform: 'translate3D(-1125px,0,0)',
})
},
{
timeout: 3000,
}
)
})
.demo-box {
position: relative;
.nut-swiper {
height: 150px;
img {
......@@ -18,4 +19,42 @@
color: #fff;
font-size: 14px;
}
.nut-swiper-btns {
width: 100%;
position: absolute;
top: 50%;
transform: translateY(-15px);
z-index: 1;
display: flex;
justify-content: space-between;
height: 0px;
span {
display: flex;
align-items: center;
justify-content: center;
width: 20px;
height: 30px;
background-color: rgba(0, 0, 0, 0.2);
}
}
}
.vertical-center {
.nut-swiper__pagination-vertical {
i {
width: 6px;
height: 6px;
border-radius: 50%;
&.active {
height: 18px;
border-radius: 5px;
}
}
}
.nut-swiper-item {
height: 300px;
img {
width: 100%;
height: 100%;
}
}
}
import React, { useState } from 'react'
import React, { useState, useEffect } from 'react'
import SwiperItem from '@/packages/swiperitem'
import Swiper from '@/packages/swiper'
import '@/packages/swiper/demo.scss'
import Icon from '@/packages/icon'
import { useTranslate } from '../../sites/assets/locale'
interface T {
basic: string
asyc: string
dynamicDel: string
size: string
indicator: string
btns: string
vertical: string
horizontalCenter: string
verticalCenter: string
}
const SwiperDemo = () => {
const [translated] = useTranslate<T>({
'zh-CN': {
basic: '基本用法',
asyc: '异步加载(3s)',
dynamicDel: '动态加载',
size: '自定义大小',
indicator: '自定义指示器',
btns: '手动切换',
vertical: '垂直方向',
horizontalCenter: '水平居中展示',
verticalCenter: '垂直居中展示',
},
'en-US': {
basic: 'Basic Usage',
asyc: 'Asynchronous loading(3s)',
dynamicDel: 'Dynamic loading',
size: 'Custom size',
indicator: 'Custom indicator',
btns: 'Manual switching',
vertical: 'Vertical direction',
horizontalCenter: 'Horizontal center display',
verticalCenter: 'Vertical center display',
},
})
const swiperRef = React.useRef<any>(null)
const [height, setHeight] = useState<any>(150)
const [paginationColor, setPaginationColor] = useState<string>('#426543')
......@@ -11,7 +48,20 @@ const SwiperDemo = () => {
const [initPage2, setInitPage2] = useState<any>(0)
const [initPage3, setInitPage3] = useState<any>(0)
const [initPage4, setInitPage4] = useState<any>(0)
const [initPage5, setInitPage5] = useState<any>(0)
const [initPage6, setInitPage6] = useState<any>(0)
const [initPage7, setInitPage7] = useState<any>(0)
const [initPage8, setInitPage8] = useState<any>(0)
const [initPage9, setInitPage9] = useState<any>(0)
const [current, setCurrent] = useState(1)
const [current2, setCurrent2] = useState(1)
const [list1, setList1] = useState<string[]>([])
const [list2, setList2] = useState<string[]>([
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg',
])
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
......@@ -20,12 +70,27 @@ const SwiperDemo = () => {
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg',
]
const onChange = (e: number) => {}
const handlePrev = () => {
swiperRef.current.prev()
}
const handleNext = () => {
swiperRef.current.next()
}
useEffect(() => {
setTimeout(() => {
const arr: any = list.slice()
setList1(arr)
const arr2 = list2.slice()
arr2.splice(1, 1)
setList2(arr2)
}, 3000)
}, [])
return (
<div className="demo padding">
<h2>基本用法</h2>
<h2>{translated.basic}</h2>
<div className="demo-box" style={{ height: 150 }}>
<Swiper
ref={swiperRef}
height={height}
paginationColor={paginationColor}
autoPlay="2000"
......@@ -42,9 +107,48 @@ const SwiperDemo = () => {
})}
</Swiper>
</div>
<h2>自定义大小</h2>
<h2>{translated.asyc}</h2>
<div className="demo-box" style={{ height: 150 }}>
<Swiper
height={height}
paginationColor={paginationColor}
autoPlay="2000"
initPage={initPage2}
onChange={onChange}
paginationVisible
>
{list1.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
</div>
<h2>{translated.dynamicDel}</h2>
<div className="demo-box" style={{ height: 150 }}>
<Swiper
height={height}
paginationColor={paginationColor}
autoPlay="2000"
initPage={initPage3}
onChange={onChange}
paginationVisible
>
{list2.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
</div>
<h2>{translated.size}</h2>
<div className="demo-box" style={{ height: 150 }}>
<Swiper initPage={initPage2} width="300" loop={false}>
<Swiper initPage={initPage4} width="300" loop={false}>
{list.map((item) => {
return (
<SwiperItem key={item}>
......@@ -54,11 +158,11 @@ const SwiperDemo = () => {
})}
</Swiper>
</div>
<h2>自定义指示器</h2>
<h2>{translated.indicator}</h2>
<div className="demo-box" style={{ height: 150 }}>
<Swiper
loop
initPage={initPage3}
initPage={initPage5}
onChange={(e) => setCurrent(e + 1)}
pageContent={<div className="page"> {current}/4 </div>}
>
......@@ -71,11 +175,37 @@ const SwiperDemo = () => {
})}
</Swiper>
</div>
<h2>垂直方向</h2>
<h2>{translated.btns}</h2>
<div className="demo-box" style={{ height: 150 }}>
<Swiper
ref={swiperRef}
loop
initPage={initPage6}
onChange={(e) => setCurrent2(e + 1)}
pageContent={<div className="page"> {current2}/4 </div>}
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
<div className="nut-swiper-btns">
<span className="nut-swiper-btns__left" onClick={(e) => handlePrev()}>
<Icon name="left" />
</span>
<span className="nut-swiper-btns__left" onClick={(e) => handleNext()}>
<Icon name="right" />
</span>
</div>
</div>
<h2>{translated.vertical}</h2>
<div className="demo-box vertical-center" style={{ height: 150 }}>
<Swiper
loop
initPage={initPage4}
initPage={initPage7}
direction="vertical"
autoPlay="3000"
height="150"
......@@ -90,6 +220,47 @@ const SwiperDemo = () => {
})}
</Swiper>
</div>
<h2>{translated.horizontalCenter}</h2>
<div className="demo-box " style={{ height: 150 }}>
<Swiper
loop={false}
initPage={initPage8}
autoPlay="0"
height="150"
paginationVisible
width="280"
isCenter
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
</div>
<h2>{translated.verticalCenter}</h2>
<div className="demo-box vertical-center">
<Swiper
loop={false}
initPage={initPage9}
direction="vertical"
autoPlay="0"
height="220"
paginationVisible
isCenter
style={{ height: '280px' }}
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
</div>
</div>
)
}
......
# Swiper 轮播
# Swiper
### 介绍
### Intro
常用于一组图片或卡片轮播,当内容空间不足时,可以用走马灯的形式进行收纳,进行轮播展现。
Often used in a group of pictures or card rotation.
### 安装
### Install
```javascript
import { Swiper,SwiperItem } from '@nutui/nutui-react';
```
## 代码演示
### 基础用法
### Basic Usage
`autoPlay` 自动轮播的时长
`initPage` 初始索引值
`paginationVisible` 是否显示分页指示器
`paginationColor` 指示器颜色自定义
`onChange` 当卡片发生变化
`autoPlay` Duration of automatic rotation
`initPage` Initial index value
`paginationVisible` Show paging indicator
`paginationColor` Indicator color customization
`onChange` When the card changes
:::demo
``` tsx
......@@ -32,35 +31,132 @@ const App = () => {
// do something
}
return (
<Swiper
height={height}
paginationColor="#426543"
autoPlay="3000"
initPage={initPage1}
paginationVisible
onChange={onChange}
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
<div className="demo-box" style={{ height: 150 }}>
<Swiper
height={height}
paginationColor="#426543"
autoPlay="3000"
initPage={initPage1}
paginationVisible
onChange={onChange}
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
</div>
)
}
export default App;
```
:::
### 自定义大小
### Asynchronous loading
:::demo
``` tsx
import React, { useState, useEffect } from 'react'
import { Swiper,SwiperItem } from '@nutui/nutui-react';
const App = () => {
const [initPage1, setInitPage1] = useState(0)
const [height, setHeight] = useState<any>(150)
const [list, setList] = useState<string[]>([])
useEffect(() => {
setTimeout(() => {
const arr: string[] = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg'
]
setList(arr)
}, 3000)
}, [])
return (
<div className="demo-box" style={{ height: 150 }}>
<Swiper
height={height}
paginationColor="#426543"
autoPlay="3000"
initPage={initPage1}
paginationVisible
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
</div>
)
}
export default App;
```
:::
### Dynamic loading
Support dynamic addition / deletion of pictures
:::demo
``` tsx
import React, { useState, useEffect } from 'react'
import { Swiper,SwiperItem } from '@nutui/nutui-react';
const App = () => {
const [initPage1, setInitPage1] = useState(0)
const [height, setHeight] = useState<any>(150)
const [list, setList] = useState<string[]>([
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg',
])
useEffect(() => {
setTimeout(() => {
const arr = list.slice()
arr.splice(1, 1)
setList(arr)
}, 3000)
}, [])
return (
<div className="demo-box" style={{ height: 150 }}>
<Swiper
height={height}
paginationColor="#426543"
autoPlay="3000"
initPage={initPage1}
paginationVisible
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
</div>
)
}
export default App;
```
:::
### Custom size
`width` Custom rotation size
`width` 自定义轮播大小
:::demo
``` tsx
import React, { useState } from 'react'
......@@ -69,33 +165,36 @@ import { Swiper,SwiperItem } from '@nutui/nutui-react';
const App = () => {
const [initPage2, setInitPage2] = useState(0)
return (
<Swiper
width={300}
initPage={initPage2}
loop={false}
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
<div className="demo-box" style={{ height: 150 }}>
<Swiper
width={300}
initPage={initPage2}
loop={false}
height={150}
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
</div>
)
}
export default App;
```
:::
### 自定义分页指示器
### Custom paging indicator
`pageContent` 表示自定义指示器
`pageContent` Custom indicator
:::demo
``` tsx
......@@ -109,34 +208,129 @@ const App = () => {
setCurrent(e + 1)
}
return (
<Swiper
initPage={initPage3}
loop
onChange={onChange3}
pageContent={<div className="page"> {current}/4 </div>}
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
<div className="demo-box" style={{ height: 150 }}>
<Swiper
initPage={initPage3}
loop
height={150}
onChange={onChange3}
pageContent={<div className="page"> {current}/4 </div>}
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
</div>
)
}
export default App;
```
:::
### Manual switching
You can manually switch through `api` (`prev`, `next`)
:::demo
``` tsx
import React, { useState, useRef } from 'react'
import { Swiper, SwiperItem, Icon } from '@nutui/nutui-react';
const App = () => {
const swiperRef = React.useRef<any>(null)
const [initPage6, setInitPage6] = useState(0)
const [current2, setCurrent2] = useState(1)
const onChange3 = (e) => {
setCurrent(e + 1)
}
const handlePrev = () => {
swiperRef.current.prev()
}
const handleNext = () => {
swiperRef.current.next()
}
const pageStyle = {
position: 'absolute',
bottom: 0,
right: 0,
width: '46px',
height: '22px',
background: 'rgba(0, 0, 0, 0.33)',
borderRadius: '22px',
textAlign: 'center',
color: '#fff',
fontSize: '14px',
}
const btnsStyle = {
width: '100%',
position: 'absolute',
top: '50%',
transform: 'translateY(-15px)',
zIndex: 1,
display: 'flex',
justifyContent: 'space-between',
height: '0px',
}
const spanStyle = {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '20px',
height: '30px',
backgroundColor: 'rgba(0, 0, 0, 0.2)',
}
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg'
]
return (
<div className="demo-box" style={{ height: '150px', position: 'relative' }}>
<Swiper
height={150}
ref={swiperRef}
loop
initPage={initPage6}
onChange={(e) => setCurrent2(e + 1)}
pageContent={<div style={ pageStyle } > {current2}/4 </div>}
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
<div style={btnsStyle}>
<span style={spanStyle} onClick={(e) => handlePrev()}>
<Icon name="left" />
</span>
<span style={spanStyle} onClick={(e) => handleNext()}>
<Icon name="right" />
</span>
</div>
</div>
)
}
export default App;
```
:::
### 垂直方向
### Vertical direction
`direction` 自定义轮播方向
`direction` Custom rotation direction
:::demo
``` tsx
......@@ -150,27 +344,116 @@ const App = () => {
setCurrent(e + 1)
}
return (
<Swiper
loop
initPage={initPage4}
direction="vertical"
autoPlay="3000"
height="150"
paginationVisible
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
<div className="demo-box vertical-center" style={{ height: '150px' }}>
<Swiper
loop
initPage={initPage4}
direction="vertical"
autoPlay="3000"
height="150"
paginationVisible
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
</div>
)
}
export default App;
```
:::
### Horizontal center display
`isCenter` means it can be centered, and `width` must be passed at the same time
:::demo
``` tsx
import React, { useState } from 'react'
import { Swiper,SwiperItem } from '@nutui/nutui-react';
const App = () => {
const [initPage8, setInitPage8] = useState(0)
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg'
]
return (
<div className="demo-box " style={{ height: '150px' }}>
<Swiper
loop={false}
initPage={initPage8}
autoPlay="0"
height="150"
paginationVisible
width="280"
isCenter
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
</div>
)
}
export default App;
```
:::
### Vertically centered display
`isCenter` means that it can be centered, and `height` must be passed
:::demo
``` tsx
import React, { useState } from 'react'
import { Swiper,SwiperItem } from '@nutui/nutui-react';
const App = () => {
const [initPage9, setInitPage9] = useState(0)
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg'
]
return (
<div className="demo-box vertical-center" style={{ height: '150px' }}>
<Swiper
loop={false}
initPage={initPage9}
direction="vertical"
autoPlay="0"
height="220"
paginationVisible
isCenter
style={{ height: '280px' }}
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
</div>
)
}
export default App;
......@@ -181,36 +464,37 @@ export default App;
### Props
| 参数 | 说明 | 类型 | 默认值 |
| Attribute | Description | Type | Default |
| ----------------- | -------------------------------------- | ------------------------- | ----------------- |
| width | 轮播卡片的宽度 | Number \| String | window.innerWidth |
| height | 轮播卡片的高度 | String \| Number | 0 |
| direction | 轮播方向,可选值`horizontal`,`vertical` | String | 'horizontal' |
| paginationVisible | 分页指示器是否展示 | Boolean | false |
| paginationColor | 分页指示器选中的颜色 | String | '#fff' |
| loop | 是否循环轮播 | Boolean | true |
| duration | 动画时长(单位是ms) | Number \| String | 500 |
| autoPlay | 自动轮播时长,0表示不会自动轮播 | Number \| String | 0 |
| initPage | 初始化索引值 | Number \| String | 0 |
| touchable | 是否可触摸滑动 | Boolean | true |
| pageContent | 自定义指示器 | String \| React.ReactNode | - |
| isPreventDefault | 滑动过程中是否禁用默认事件 | Boolean | true |
| isStopPropagation | 滑动过程中是否禁止冒泡 | Boolean | true |
| width | Width of rotation car | Number \| String | window.innerWidth |
| height | Height of rotation card | String \| Number | 0 |
| direction | Rotation direction, optional value:`horizontal`,`vertical` | String | 'horizontal' |
| paginationVisible | Whether the pagination indicator is displayed | Boolean | false |
| paginationColor | Pagination indicator selected color | String | '#fff' |
| loop | Whether to rotate | Boolean | true |
| duration | Animation duration(Unit ms | Number \| String | 500 |
| autoPlay | Automatic rotation duration, 0 means no automatic | Number \| String | 0 |
| initPage | Initialize index value | Number \| String | 0 |
| touchable | Is it possible to touch swipe | Boolean | true |
| pageContent | Custom indicator | String \| React.ReactNode | - |
| isPreventDefault | Whether to disable default events during swipe | Boolean | true |
| isStopPropagation | Whether to prohibit bubbling during sliding | Boolean | true |
| isCenter | Whether to display in the center, the corresponding `width` and `height` must be passed | Boolean | false |
### Events
| 事件名 | 说明 | 回调参数 |
| Event | Description | Arguments |
| -------- | ---------------- | --------------- |
| onChange | 卡片切换后的回调 | 当前索引值index |
| onChange | Callback after card switching | Current index value |
### API
| 事件名 | 说明 | 参数 |
| Event | Description | Arguments |
| ------ | -------------- | ------------ |
| prev | 切换到上一页 | - |
| next | 切换到下一页 | - |
| to | 切换到指定轮播 | index:number |
\ No newline at end of file
| prev | Switch to previous page | - |
| next | Switch to next page | - |
| to | Switch to the specified rotation | index:number |
\ No newline at end of file
......@@ -32,32 +32,129 @@ const App = () => {
// do something
}
return (
<Swiper
height={height}
paginationColor="#426543"
autoPlay="3000"
initPage={initPage1}
paginationVisible
onChange={onChange}
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
<div className="demo-box" style={{ height: 150 }}>
<Swiper
height={height}
paginationColor="#426543"
autoPlay="3000"
initPage={initPage1}
paginationVisible
onChange={onChange}
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
</div>
)
}
export default App;
```
:::
### 异步加载
:::demo
``` tsx
import React, { useState, useEffect } from 'react'
import { Swiper,SwiperItem } from '@nutui/nutui-react';
const App = () => {
const [initPage1, setInitPage1] = useState(0)
const [height, setHeight] = useState<any>(150)
const [list, setList] = useState<string[]>([])
useEffect(() => {
setTimeout(() => {
const arr: string[] = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg'
]
setList(arr)
}, 3000)
}, [])
return (
<div className="demo-box" style={{ height: 150 }}>
<Swiper
height={height}
paginationColor="#426543"
autoPlay="3000"
initPage={initPage1}
paginationVisible
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
</div>
)
}
export default App;
```
:::
### 动态加载
支持动态增加/删除图片
:::demo
``` tsx
import React, { useState, useEffect } from 'react'
import { Swiper,SwiperItem } from '@nutui/nutui-react';
const App = () => {
const [initPage1, setInitPage1] = useState(0)
const [height, setHeight] = useState<any>(150)
const [list, setList] = useState<string[]>([
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg',
])
useEffect(() => {
setTimeout(() => {
const arr = list.slice()
arr.splice(1, 1)
setList(arr)
}, 3000)
}, [])
return (
<div className="demo-box" style={{ height: 150 }}>
<Swiper
height={height}
paginationColor="#426543"
autoPlay="3000"
initPage={initPage1}
paginationVisible
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
</div>
)
}
export default App;
```
:::
### 自定义大小
`width` 自定义轮播大小
......@@ -69,24 +166,27 @@ import { Swiper,SwiperItem } from '@nutui/nutui-react';
const App = () => {
const [initPage2, setInitPage2] = useState(0)
return (
<Swiper
width={300}
initPage={initPage2}
loop={false}
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
<div className="demo-box" style={{ height: 150 }}>
<Swiper
width={300}
initPage={initPage2}
loop={false}
height={150}
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
</div>
)
}
export default App;
......@@ -109,25 +209,120 @@ const App = () => {
setCurrent(e + 1)
}
return (
<Swiper
initPage={initPage3}
loop
onChange={onChange3}
pageContent={<div className="page"> {current}/4 </div>}
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
<div className="demo-box" style={{ height: 150 }}>
<Swiper
initPage={initPage3}
loop
height={150}
onChange={onChange3}
pageContent={<div className="page"> {current}/4 </div>}
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
</div>
)
}
export default App;
```
:::
### 手动切换
可通过 `API`(`prev`,`next`)进行手动切换
:::demo
``` tsx
import React, { useState, useRef } from 'react'
import { Swiper, SwiperItem, Icon } from '@nutui/nutui-react';
const App = () => {
const swiperRef = React.useRef<any>(null)
const [initPage6, setInitPage6] = useState(0)
const [current2, setCurrent2] = useState(1)
const onChange3 = (e) => {
setCurrent(e + 1)
}
const handlePrev = () => {
swiperRef.current.prev()
}
const handleNext = () => {
swiperRef.current.next()
}
const pageStyle = {
position: 'absolute',
bottom: 0,
right: 0,
width: '46px',
height: '22px',
background: 'rgba(0, 0, 0, 0.33)',
borderRadius: '22px',
textAlign: 'center',
color: '#fff',
fontSize: '14px',
}
const btnsStyle = {
width: '100%',
position: 'absolute',
top: '50%',
transform: 'translateY(-15px)',
zIndex: 1,
display: 'flex',
justifyContent: 'space-between',
height: '0px',
}
const spanStyle = {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '20px',
height: '30px',
backgroundColor: 'rgba(0, 0, 0, 0.2)',
}
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg'
]
return (
<div className="demo-box" style={{ height: '150px', position: 'relative' }}>
<Swiper
height={150}
ref={swiperRef}
loop
initPage={initPage6}
onChange={(e) => setCurrent2(e + 1)}
pageContent={<div style={ pageStyle } > {current2}/4 </div>}
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
<div style={btnsStyle}>
<span style={spanStyle} onClick={(e) => handlePrev()}>
<Icon name="left" />
</span>
<span style={spanStyle} onClick={(e) => handleNext()}>
<Icon name="right" />
</span>
</div>
</div>
)
}
export default App;
......@@ -150,27 +345,116 @@ const App = () => {
setCurrent(e + 1)
}
return (
<Swiper
loop
initPage={initPage4}
direction="vertical"
autoPlay="3000"
height="150"
paginationVisible
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
<div className="demo-box vertical-center" style={{ height: '150px' }}>
<Swiper
loop
initPage={initPage4}
direction="vertical"
autoPlay="3000"
height="150"
paginationVisible
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/welcomenutui.jpg" alt="" />
</SwiperItem>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/fristfabu.jpg" alt="" />
</SwiperItem>
</Swiper>
</div>
)
}
export default App;
```
:::
### 水平居中展示
`isCenter` 代表可居中,同时必须传 `width`
:::demo
``` tsx
import React, { useState } from 'react'
import { Swiper,SwiperItem } from '@nutui/nutui-react';
const App = () => {
const [initPage8, setInitPage8] = useState(0)
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg'
]
return (
<div className="demo-box " style={{ height: '150px' }}>
<Swiper
loop={false}
initPage={initPage8}
autoPlay="0"
height="150"
paginationVisible
width="280"
isCenter
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
</div>
)
}
export default App;
```
:::
### 垂直居中展示
`isCenter` 代表可居中,同时必须传 `height`
:::demo
``` tsx
import React, { useState } from 'react'
import { Swiper,SwiperItem } from '@nutui/nutui-react';
const App = () => {
const [initPage9, setInitPage9] = useState(0)
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg'
]
return (
<div className="demo-box vertical-center" style={{ height: '150px' }}>
<Swiper
loop={false}
initPage={initPage9}
direction="vertical"
autoPlay="0"
height="220"
paginationVisible
isCenter
style={{ height: '280px' }}
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
</div>
)
}
export default App;
......@@ -196,6 +480,7 @@ export default App;
| pageContent | 自定义指示器 | String \| React.ReactNode | - |
| isPreventDefault | 滑动过程中是否禁用默认事件 | Boolean | true |
| isStopPropagation | 滑动过程中是否禁止冒泡 | Boolean | true |
| isCenter | 是否居中展示,必须传对应的`width``height` | Boolean | false |
......
......@@ -58,6 +58,97 @@ const App = () => {
export default App;
```
:::
### 异步加载
:::demo
``` tsx
import React, { useState, useEffect } from 'react'
import { Swiper,SwiperItem } from '@nutui/nutui-react';
const App = () => {
const [initPage1, setInitPage1] = useState(0)
const [height, setHeight] = useState<any>(150)
const [list, setList] = useState<string[]>([])
useEffect(() => {
setTimeout(() => {
const arr: string[] = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg'
]
setList(arr)
}, 3000)
}, [])
return (
<Swiper
height={height}
paginationColor="#426543"
autoPlay="3000"
initPage={initPage1}
paginationVisible
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
)
}
export default App;
```
:::
### 动态加载
支持动态增加/删除图片
:::demo
``` tsx
import React, { useState, useEffect } from 'react'
import { Swiper,SwiperItem } from '@nutui/nutui-react';
const App = () => {
const [initPage1, setInitPage1] = useState(0)
const [height, setHeight] = useState<any>(150)
const [list, setList] = useState<string[]>([
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg',
])
useEffect(() => {
setTimeout(() => {
const arr = list.slice()
arr.splice(1, 1)
setList(arr)
}, 3000)
}, [])
return (
<Swiper
height={height}
paginationColor="#426543"
autoPlay="3000"
initPage={initPage1}
paginationVisible
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
)
}
export default App;
```
:::
### 自定义大小
`width` 自定义轮播大小
......@@ -73,6 +164,7 @@ const App = () => {
width={300}
initPage={initPage2}
loop={false}
height={150}
>
<SwiperItem >
<img src="https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg" alt="" />
......@@ -112,6 +204,7 @@ const App = () => {
<Swiper
initPage={initPage3}
loop
height={150}
onChange={onChange3}
pageContent={<div className="page"> {current}/4 </div>}
>
......@@ -134,6 +227,98 @@ export default App;
```
:::
### 手动切换
可通过 `API`(`prev`,`next`)进行手动切换
:::demo
``` tsx
import React, { useState, useRef } from 'react'
import { Swiper, SwiperItem, Icon } from '@nutui/nutui-react';
const App = () => {
const swiperRef = React.useRef<any>(null)
const [initPage6, setInitPage6] = useState(0)
const [current2, setCurrent2] = useState(1)
const onChange3 = (e) => {
setCurrent(e + 1)
}
const handlePrev = () => {
swiperRef.current.prev()
}
const handleNext = () => {
swiperRef.current.next()
}
const pageStyle = {
position: 'absolute',
bottom: 0,
right: 0,
width: '46px',
height: '22px',
background: 'rgba(0, 0, 0, 0.33)',
borderRadius: '22px',
textAlign: 'center',
color: '#fff',
fontSize: '14px',
}
const btnsStyle = {
width: '100%',
position: 'absolute',
top: '50%',
transform: 'translateY(-15px)',
zIndex: 1,
display: 'flex',
justifyContent: 'space-between',
height: '0px',
}
const spanStyle = {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '20px',
height: '30px',
backgroundColor: 'rgba(0, 0, 0, 0.2)',
}
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg'
]
return (
<div className="demo-box" style={{ height: '150px', position: 'relative' }}>
<Swiper
height={150}
ref={swiperRef}
loop
initPage={initPage6}
onChange={(e) => setCurrent2(e + 1)}
pageContent={<div style={ pageStyle } > {current2}/4 </div>}
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
<div style={btnsStyle}>
<span style={spanStyle} onClick={(e) => handlePrev()}>
<Icon name="left" />
</span>
<span style={spanStyle} onClick={(e) => handleNext()}>
<Icon name="right" />
</span>
</div>
</div>
)
}
export default App;
```
:::
### 垂直方向
`direction` 自定义轮播方向
......@@ -177,6 +362,93 @@ export default App;
```
:::
### 水平居中展示
`isCenter` 代表可居中,同时必须传 `width`
:::demo
``` tsx
import React, { useState } from 'react'
import { Swiper,SwiperItem } from '@nutui/nutui-react';
const App = () => {
const [initPage8, setInitPage8] = useState(0)
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg'
]
return (
<div className="demo-box " style={{ height: '150px' }}>
<Swiper
loop={false}
initPage={initPage8}
autoPlay="0"
height="150"
paginationVisible
width="280"
isCenter
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
</div>
)
}
export default App;
```
:::
### 垂直居中展示
`isCenter` 代表可居中,同时必须传 `height`
:::demo
``` tsx
import React, { useState } from 'react'
import { Swiper,SwiperItem } from '@nutui/nutui-react';
const App = () => {
const [initPage9, setInitPage9] = useState(0)
const list = [
'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg',
'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg',
'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg',
'https://storage.360buyimg.com/jdc-article/fristfabu.jpg'
]
return (
<div className="demo-box " style={{ height: '150px' }}>
<Swiper
loop={false}
initPage={initPage9}
direction="vertical"
autoPlay="0"
height="220"
paginationVisible
isCenter
style={{ height: '280px' }}
>
{list.map((item) => {
return (
<SwiperItem key={item}>
<img src={item} alt="" />
</SwiperItem>
)
})}
</Swiper>
</div>
)
}
export default App;
```
:::
## API
### Props
......@@ -196,6 +468,7 @@ export default App;
| pageContent | 自定义指示器 | String \| React.ReactNode | - |
| isPreventDefault | 滑动过程中是否禁用默认事件 | Boolean | true |
| isStopPropagation | 滑动过程中是否禁止冒泡 | Boolean | true |
| isCenter | 是否居中展示,必须传对应的`width``height` | Boolean | false |
......
......@@ -30,6 +30,9 @@
}
}
}
&__pagination-item {
background-color: $swiper-pagination-item-background-color;
}
&__pagination-vertical {
top: 50%;
left: 12px;
......
......@@ -26,6 +26,7 @@ interface SwiperProps {
touchable: boolean
isPreventDefault: boolean
isStopPropagation: boolean
isCenter: boolean
className?: string
style?: React.CSSProperties
pageContent?: React.ReactNode
......@@ -45,6 +46,7 @@ const defaultProps = {
touchable: true,
isPreventDefault: true,
isStopPropagation: true,
isCenter: false,
className: '',
} as SwiperProps
......@@ -72,6 +74,7 @@ export const Swiper = React.forwardRef<
isPreventDefault,
isStopPropagation,
autoPlay,
isCenter,
...rest
} = propSwiper
const container = useRef<any>(null)
......@@ -87,6 +90,7 @@ export const Swiper = React.forwardRef<
const isVertical = direction === 'vertical'
const [rect, setRect] = useState(null as DOMRect | null)
// eslint-disable-next-line prefer-const
let [active, setActive] = useState(0)
const [width, setWidth] = useState(0)
const [height, setHeight] = useState(0)
......@@ -190,7 +194,6 @@ export const Swiper = React.forwardRef<
const to = (index: number) => {
resettPosition()
touchReset()
requestFrame(() => {
requestFrame(() => {
_swiper.current.moving = false
......@@ -243,10 +246,8 @@ export const Swiper = React.forwardRef<
props.onChange && props.onChange((targetActive + childCount) % childCount)
}
active = targetActive
offset = targetOffset
setActive(targetActive)
setOffset(targetOffset)
getStyle(targetOffset)
}
// 确定当前active 元素
......@@ -325,8 +326,22 @@ export const Swiper = React.forwardRef<
})
const getStyle = (moveOffset = offset) => {
const target = innerRef.current
let _offset = 0
if (!isCenter) {
_offset = moveOffset
} else {
const _size = isVertical ? height : width
const val = isVertical
? (rect as DOMRect).height - _size
: (rect as DOMRect).width - _size
_offset =
moveOffset +
(active === childCount - 1 && !props.loop ? -val / 2 : val / 2)
}
target.style.transform = `translate3D${
!isVertical ? `(${moveOffset}px,0,0)` : `(0,${moveOffset}px,0)`
!isVertical ? `(${_offset}px,0,0)` : `(0,${_offset}px,0)`
}`
target.style.transitionDuration = `${
_swiper.current.moving ? 0 : props.duration
......@@ -369,7 +384,11 @@ export const Swiper = React.forwardRef<
if (isShouldMove && touch.stateDirection === props.direction) {
const offset = isVertical ? touch.offsetY : touch.offsetX
if (props.loop) {
pace = offset > 0 ? (touch.delta > 0 ? -1 : 1) : 0
if (offset > 0) {
pace = touch.delta > 0 ? -1 : 1
} else {
pace = 0
}
} else {
pace = -Math[touch.delta > 0 ? 'ceil' : 'floor'](touch.delta / size)
}
......@@ -426,9 +445,11 @@ export const Swiper = React.forwardRef<
stopAutoPlay()
autoplay()
}, [children])
useEffect(() => {
init()
}, [propSwiper.initPage])
useEffect(() => {
const target = container.current
target.addEventListener('touchstart', onTouchStart, false)
......@@ -440,7 +461,12 @@ export const Swiper = React.forwardRef<
target.removeEventListener('touchend', onTouchEnd, false)
}
})
const style = (index: any) => {
useEffect(() => {
return () => {
stopAutoPlay()
}
}, [])
const itemStyle = (index: any) => {
const style: IStyle = {}
const _direction = propSwiper.direction || direction
const _size = size
......@@ -468,7 +494,7 @@ export const Swiper = React.forwardRef<
return (
<div
className={b('item-wrapper')}
style={style(index)}
style={itemStyle(index)}
key={index}
>
{child}
......@@ -486,12 +512,17 @@ export const Swiper = React.forwardRef<
{React.Children.map(childs, (item: any, index: number) => {
return (
<i
style={{
backgroundColor:
(active + childCount) % childCount === index
? propSwiper.paginationColor
: '#ddd',
}}
style={
(active + childCount) % childCount === index
? {
backgroundColor: propSwiper.paginationColor,
}
: undefined
}
className={classNames({
[`${b('pagination-item')}`]: true,
active: (active + childCount) % childCount === index,
})}
key={index}
/>
)
......
import React, { useState, useContext, useImperativeHandle } from 'react'
import React, { useContext } from 'react'
import classNames from 'classnames'
import { DataContext } from '@/packages/swiper/UserContext'
import bem from '@/utils/bem'
......@@ -25,15 +25,9 @@ export const SwiperItem = React.forwardRef<
const _props = { ...defaultProps, ...props }
const { children, direction, size } = _props
const parent: any = useContext(DataContext)
const [offset, setOffset] = useState(0)
const b = bem('swiper-item')
const classes = classNames(b(''))
useImperativeHandle<HTMLDivElement, any>(ref, () => ({
changeOffset: (num: number) => {
setOffset(num)
},
}))
const style = () => {
const style: IStyle = {}
const _direction = parent?.propSwiper.direction || direction
......
......@@ -69,7 +69,7 @@ $button-primary-background-color: linear-gradient(
$primary-color-end 100%
);
$button-info-color: $white;
$button-info-border-color: rgba(73, 106, 242, 1);
$button-info-border-color: #496af2;
$button-info-background-color: linear-gradient(
315deg,
rgba(73, 143, 242, 1) 0%,
......@@ -495,6 +495,10 @@ $divider-vertical-top: 2px !default;
$divider-vertical-border-left: rgba(0, 0, 0, 0.06) !default;
$divider-vertical-margin: 0 8px !default;
// swiper
$swiper-pagination-item-background-color: #ddd !default;
// Table
$table-border-color: #ececec !default;
$table-cols-padding: 10px !default;
......@@ -524,6 +528,7 @@ $numberkeyboard-key-finish-font-size: 16px !default;
$numberkeyboard-key-finish-font-size-color: #fff !default;
$numberkeyboard-key-finish-background-color: #1989fa !default;
$numberkeyboard-key-activeFinsh-background-color: #0570db !default;
// elevator
$elevator-list-item-highcolor: $primary-color !default;
$elevator-list-item-font-size: 12px !default;
......@@ -591,7 +596,6 @@ $row-content-height: 50px !default;
$row-content-line-height: 40px !default;
$col-default-margin-bottom: 15px !default;
// searchbar
$searchbar-background: $white !default;
$searchbar-right-out-color: $black !default;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册