mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat(Barrage): add new Barrage component (#11760)
* fix(Swipe): props changed but component didn't * fix(Swipe): target watch windowWidth * Update packages/vant/src/swipe/Swipe.tsx * feat(Barrage): add new Barrage component * feat(Barrage): add will-change * feat: only use transform move * refactor: only use transform * refactor: only use transform * fix(Barrage): many problems * fix(Barrage): many problems * fix(Barrage): many problems * fix(Barrage): many problems * fix(Barrage): many problems * fix(Barrage): many problems --------- Co-authored-by: zhousg <345313727@qq.com> Co-authored-by: neverland <jait.chen@foxmail.com>
This commit is contained in:
parent
5a859ff019
commit
cb0f859a83
166
packages/vant/src/barrage/Barrage.tsx
Normal file
166
packages/vant/src/barrage/Barrage.tsx
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
import {
|
||||||
|
defineComponent,
|
||||||
|
onMounted,
|
||||||
|
ref,
|
||||||
|
type ExtractPropTypes,
|
||||||
|
nextTick,
|
||||||
|
watch,
|
||||||
|
} from 'vue';
|
||||||
|
import { useExpose } from '../composables/use-expose';
|
||||||
|
import {
|
||||||
|
createNamespace,
|
||||||
|
makeArrayProp,
|
||||||
|
makeNumberProp,
|
||||||
|
makeNumericProp,
|
||||||
|
truthProp,
|
||||||
|
} from '../utils';
|
||||||
|
import { BarrageExpose } from './types';
|
||||||
|
|
||||||
|
export interface BarrageItem {
|
||||||
|
id: string | number;
|
||||||
|
text: string | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const barrageProps = {
|
||||||
|
top: makeNumericProp(10),
|
||||||
|
rows: makeNumericProp(4),
|
||||||
|
speed: makeNumericProp(4000),
|
||||||
|
autoPlay: truthProp,
|
||||||
|
delay: makeNumberProp(300),
|
||||||
|
modelValue: makeArrayProp<BarrageItem>(),
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BarrageProps = ExtractPropTypes<typeof barrageProps>;
|
||||||
|
|
||||||
|
const [name, bem] = createNamespace('barrage');
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name,
|
||||||
|
|
||||||
|
props: barrageProps,
|
||||||
|
|
||||||
|
emits: ['update:modelValue'],
|
||||||
|
|
||||||
|
setup(props, { emit, slots }) {
|
||||||
|
const barrageWrapper = ref<HTMLDivElement>();
|
||||||
|
const className = bem('item') as string;
|
||||||
|
const total = ref(0);
|
||||||
|
const barrageItems: HTMLSpanElement[] = [];
|
||||||
|
|
||||||
|
const createBarrageItem = (
|
||||||
|
text: string | number,
|
||||||
|
delay: number = props.delay
|
||||||
|
) => {
|
||||||
|
const item = document.createElement('span');
|
||||||
|
item.className = className;
|
||||||
|
item.innerText = String(text);
|
||||||
|
|
||||||
|
item.style.animationDuration = `${props.speed}ms`;
|
||||||
|
item.style.animationDelay = `${delay}ms`;
|
||||||
|
item.style.animationName = 'van-barrage';
|
||||||
|
item.style.animationTimingFunction = 'linear';
|
||||||
|
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isInitBarrage = ref(true);
|
||||||
|
const isPlay = ref(props.autoPlay);
|
||||||
|
|
||||||
|
const appendBarrageItem = ({ id, text }: BarrageItem, i: number) => {
|
||||||
|
const item = createBarrageItem(
|
||||||
|
text,
|
||||||
|
isInitBarrage.value ? i * props.delay : undefined
|
||||||
|
);
|
||||||
|
if (!props.autoPlay && isPlay.value === false) {
|
||||||
|
item.style.animationPlayState = 'paused';
|
||||||
|
}
|
||||||
|
barrageWrapper.value?.append(item);
|
||||||
|
total.value++;
|
||||||
|
|
||||||
|
const top =
|
||||||
|
((total.value - 1) % +props.rows) * item.offsetHeight + +props.top;
|
||||||
|
item.style.top = `${top}px`;
|
||||||
|
item.dataset.id = String(id);
|
||||||
|
barrageItems.push(item);
|
||||||
|
|
||||||
|
item.addEventListener('animationend', () => {
|
||||||
|
emit(
|
||||||
|
'update:modelValue',
|
||||||
|
[...props.modelValue].filter((v) => String(v.id) !== item.dataset.id)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateBarrages = (
|
||||||
|
newValue: BarrageItem[],
|
||||||
|
oldValue: BarrageItem[]
|
||||||
|
) => {
|
||||||
|
const map = new Map(oldValue.map((item) => [item.id, item]));
|
||||||
|
|
||||||
|
newValue.forEach((item, i) => {
|
||||||
|
if (map.has(item.id)) {
|
||||||
|
map.delete(item.id);
|
||||||
|
} else {
|
||||||
|
// add
|
||||||
|
appendBarrageItem(item, i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
map.forEach((item) => {
|
||||||
|
// remove
|
||||||
|
const index = barrageItems.findIndex(
|
||||||
|
(span) => span.dataset.id === String(item.id)
|
||||||
|
);
|
||||||
|
if (index > -1) {
|
||||||
|
barrageItems[index].remove();
|
||||||
|
barrageItems.splice(index, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
isInitBarrage.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.modelValue.slice(),
|
||||||
|
(newValue, oldValue) => updateBarrages(newValue ?? [], oldValue ?? []),
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const rootStyle = ref<{
|
||||||
|
'--move-distance'?: string;
|
||||||
|
}>({});
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
rootStyle.value[
|
||||||
|
'--move-distance'
|
||||||
|
] = `-${barrageWrapper.value?.offsetWidth}px`;
|
||||||
|
await nextTick();
|
||||||
|
updateBarrages(props.modelValue, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
const play = () => {
|
||||||
|
isPlay.value = true;
|
||||||
|
barrageItems.forEach((item) => {
|
||||||
|
item.style.animationPlayState = 'running';
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const pause = () => {
|
||||||
|
isPlay.value = false;
|
||||||
|
barrageItems.forEach((item) => {
|
||||||
|
item.style.animationPlayState = 'paused';
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useExpose<BarrageExpose>({
|
||||||
|
play,
|
||||||
|
pause,
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => (
|
||||||
|
<div class={bem()} ref={barrageWrapper} style={rootStyle.value}>
|
||||||
|
{slots.default?.()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
148
packages/vant/src/barrage/README.md
Normal file
148
packages/vant/src/barrage/README.md
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
# Barrage
|
||||||
|
|
||||||
|
### Intro
|
||||||
|
|
||||||
|
To realize the critical subtitle function when watching the video.
|
||||||
|
|
||||||
|
### Install
|
||||||
|
|
||||||
|
Register component globally via `app.use`, refer to [Component Registration](#/en-US/advanced-usage#zu-jian-zhu-ce) for more registration ways.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createApp } from 'vue';
|
||||||
|
import { Barrage } from 'vant';
|
||||||
|
|
||||||
|
const app = createApp();
|
||||||
|
app.use(Barrage);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Basic Usage
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-barrage v-model="list">
|
||||||
|
<div class="video" style="width: 100%; height: 150px"></div>
|
||||||
|
</van-barrage>
|
||||||
|
<van-space style="margin-top: 10px">
|
||||||
|
<van-button @click="add" type="primary" size="small"> barrage </van-button>
|
||||||
|
</van-space>
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const defaultList = [
|
||||||
|
{ id: 100, text: 'Lightweight' },
|
||||||
|
{ id: 101, text: 'Customizable' },
|
||||||
|
{ id: 102, text: 'Mobile' },
|
||||||
|
{ id: 103, text: 'Vue' },
|
||||||
|
{ id: 104, text: 'Library' },
|
||||||
|
{ id: 105, text: 'VantUI' },
|
||||||
|
{ id: 106, text: '666' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const list = ref([...defaultList]);
|
||||||
|
const add = () => {
|
||||||
|
list.value.push({ id: Math.random(), text: 'Barrage' });
|
||||||
|
};
|
||||||
|
return { list, add };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Imitate video barrage
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-barrage v-model="list" ref="barrage" :auto-play="false">
|
||||||
|
<div class="video" style="width: 100%; height: 150px"></div>
|
||||||
|
</van-barrage>
|
||||||
|
<van-space style="margin-top: 10px">
|
||||||
|
<van-button @click="add" type="primary" size="small" :disabled="!isPlay">
|
||||||
|
barrage
|
||||||
|
</van-button>
|
||||||
|
<van-button @click="toggle()" size="small">
|
||||||
|
{{ isPlay ? 'pause' : 'play' }}
|
||||||
|
</van-button>
|
||||||
|
</van-space>
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const defaultList = [
|
||||||
|
{ id: 100, text: 'Lightweight' },
|
||||||
|
{ id: 101, text: 'Customizable' },
|
||||||
|
{ id: 102, text: 'Mobile' },
|
||||||
|
{ id: 103, text: 'Vue' },
|
||||||
|
{ id: 104, text: 'Library' },
|
||||||
|
{ id: 105, text: 'VantUI' },
|
||||||
|
{ id: 106, text: '666' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const list = ref([...defaultList]);
|
||||||
|
const barrage = ref<BarrageInstance>();
|
||||||
|
const add = () => {
|
||||||
|
list.value.push({ id: Math.random(), text: 'Barrage' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const [isPlay, toggle] = useToggle(false);
|
||||||
|
|
||||||
|
watch(isPlay, () => {
|
||||||
|
if (isPlay.value) barrage.value?.play();
|
||||||
|
else barrage.value?.pause();
|
||||||
|
});
|
||||||
|
|
||||||
|
return { list, barrage, isPlay, toggle, add };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
| Attribute | Description | Type | Default |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| v-model | Barrage data | _BarrageItem[]_ | - |
|
||||||
|
| auto-play | Whether to play the bullet screen automatically | _boolean_ | `true` |
|
||||||
|
| rows | The number of lines of text | _number \| string_ | `4` |
|
||||||
|
| top | Spacing between the top of the barrage area, unit `px` | _number \| string_ | `10` |
|
||||||
|
| speed | Speed of passing, unit `ms` | _number \| string_ | `4000` |
|
||||||
|
| delay | Barrage animation delay, unit `ms` | _number_ | `300` |
|
||||||
|
|
||||||
|
### Methods
|
||||||
|
|
||||||
|
Use [ref](https://v3.vuejs.org/guide/component-template-refs.html) to get Barrage instance and call instance methods.
|
||||||
|
|
||||||
|
| Name | Description | Attribute | Return value |
|
||||||
|
| ----- | ------------- | --------- | ------------ |
|
||||||
|
| play | Play barrage | - | - |
|
||||||
|
| pause | Pause barrage | - | - |
|
||||||
|
|
||||||
|
### Slots
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
| ------- | ------------ |
|
||||||
|
| default | Default slot |
|
||||||
|
|
||||||
|
### Types
|
||||||
|
|
||||||
|
The component exports the following type definitions:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { BarrageProps, BarrageItem, BarrageInstance } from 'vant';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Theming
|
||||||
|
|
||||||
|
### CSS Variables
|
||||||
|
|
||||||
|
The component provides the following CSS variables, which can be used to customize styles. Please refer to [ConfigProvider component](#/en-US/config-provider).
|
||||||
|
|
||||||
|
| Name | Default Value | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| --van-barrage-font-size | _16px_ | - |
|
||||||
|
| --van-barrage-space | _10px_ | - |
|
||||||
|
| --van-barrage-color | _var(--van-white)_ | - |
|
||||||
|
| --van-barrage-font | _-apple-system-font, Helvetica Neue, Arial, sans-serif_ | - |
|
153
packages/vant/src/barrage/README.zh-CN.md
Normal file
153
packages/vant/src/barrage/README.zh-CN.md
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
# Barrage 弹幕
|
||||||
|
|
||||||
|
### 介绍
|
||||||
|
|
||||||
|
实现观看视频时弹出的评论性字幕功能。
|
||||||
|
|
||||||
|
### 引入
|
||||||
|
|
||||||
|
通过以下方式来全局注册组件,更多注册方式请参考[组件注册](#/zh-CN/advanced-usage#zu-jian-zhu-ce)。
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createApp } from 'vue';
|
||||||
|
import { Barrage } from 'vant';
|
||||||
|
|
||||||
|
const app = createApp();
|
||||||
|
app.use(Barrage);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 代码演示
|
||||||
|
|
||||||
|
### 基础用法
|
||||||
|
|
||||||
|
可以通过 `v-model` 双向绑定弹幕数据,`Barrage` 会在组件区域内播放文字弹幕,使用数组数据 `push()` 可以发送弹幕文字。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-barrage v-model="list">
|
||||||
|
<div class="video" style="width: 100%; height: 150px"></div>
|
||||||
|
</van-barrage>
|
||||||
|
<van-space style="margin-top: 10px">
|
||||||
|
<van-button @click="add" type="primary" size="small"> 弹幕 </van-button>
|
||||||
|
</van-space>
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const defaultList = [
|
||||||
|
{ id: 100, text: '轻量' },
|
||||||
|
{ id: 101, text: '可定制的' },
|
||||||
|
{ id: 102, text: '移动端' },
|
||||||
|
{ id: 103, text: 'Vue' },
|
||||||
|
{ id: 104, text: '组件库' },
|
||||||
|
{ id: 105, text: 'VantUI' },
|
||||||
|
{ id: 106, text: '666' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const list = ref([...defaultList]);
|
||||||
|
const add = () => {
|
||||||
|
list.value.push({ id: Math.random(), text: 'Barrage' });
|
||||||
|
};
|
||||||
|
|
||||||
|
return { list, add };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 模拟视频弹幕
|
||||||
|
|
||||||
|
设置 `auto-play` 为 `false` 属性后,需要使用 `play()` 进行弹幕播放,暂停可以使用 `pause()` 实现。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-barrage v-model="list" ref="barrage" :auto-play="false">
|
||||||
|
<div class="video" style="width: 100%; height: 150px"></div>
|
||||||
|
</van-barrage>
|
||||||
|
<van-space style="margin-top: 10px">
|
||||||
|
<van-button @click="add" type="primary" size="small" :disabled="!isPlay">
|
||||||
|
弹幕
|
||||||
|
</van-button>
|
||||||
|
<van-button @click="toggle()" size="small">
|
||||||
|
{{ isPlay ? '暂停' : '开始' }}
|
||||||
|
</van-button>
|
||||||
|
</van-space>
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const defaultList = [
|
||||||
|
{ id: 100, text: '轻量' },
|
||||||
|
{ id: 101, text: '可定制的' },
|
||||||
|
{ id: 102, text: '移动端' },
|
||||||
|
{ id: 103, text: 'Vue' },
|
||||||
|
{ id: 104, text: '组件库' },
|
||||||
|
{ id: 105, text: 'VantUI' },
|
||||||
|
{ id: 106, text: '666' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const list = ref([...defaultList]);
|
||||||
|
const barrage = ref<BarrageInstance>();
|
||||||
|
const add = () => {
|
||||||
|
list.value.push({ id: Math.random(), text: 'Barrage' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const [isPlay, toggle] = useToggle(false);
|
||||||
|
|
||||||
|
watch(isPlay, () => {
|
||||||
|
if (isPlay.value) barrage.value?.play();
|
||||||
|
else barrage.value?.pause();
|
||||||
|
});
|
||||||
|
|
||||||
|
return { list, barrage, isPlay, toggle, add };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 |
|
||||||
|
| --------- | ------------------------------- | ------------------ | ------ |
|
||||||
|
| v-model | 弹幕数据 | _BarrageItem[]_ | - |
|
||||||
|
| auto-play | 是否自动播放弹幕 | _boolean_ | `true` |
|
||||||
|
| rows | 弹幕文字行数 | _number \| string_ | `4` |
|
||||||
|
| top | 弹幕文字区域顶部间距,单位 `px` | _number \| string_ | `10` |
|
||||||
|
| speed | 文字滑过容器的时间,单位 `ms` | _number \| string_ | `4000` |
|
||||||
|
| delay | 弹幕动画延时,单位 `ms` | _number_ | `300` |
|
||||||
|
|
||||||
|
### 方法
|
||||||
|
|
||||||
|
通过 ref 可以获取到 Barrage 实例并调用实例方法,详见[组件实例方法](#/zh-CN/advanced-usage#zu-jian-shi-li-fang-fa)。
|
||||||
|
|
||||||
|
| 方法名 | 说明 | 参数 | 返回值 |
|
||||||
|
| ------ | -------- | ---- | ------ |
|
||||||
|
| play | 播放弹幕 | - | - |
|
||||||
|
| pause | 暂停弹幕 | - | - |
|
||||||
|
|
||||||
|
### Slots
|
||||||
|
|
||||||
|
| 名称 | 说明 |
|
||||||
|
| ------- | -------------- |
|
||||||
|
| default | 弹幕组件子元素 |
|
||||||
|
|
||||||
|
### 类型定义
|
||||||
|
|
||||||
|
组件导出以下类型定义:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { BarrageProps, BarrageItem, BarrageInstance } from 'vant';
|
||||||
|
```
|
||||||
|
|
||||||
|
## 主题定制
|
||||||
|
|
||||||
|
### 样式变量
|
||||||
|
|
||||||
|
组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 [ConfigProvider 组件](#/zh-CN/config-provider)。
|
||||||
|
|
||||||
|
| 名称 | 默认值 | 描述 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| --van-barrage-font-size | _16px_ | - |
|
||||||
|
| --van-barrage-space | _10px_ | - |
|
||||||
|
| --van-barrage-color | _var(--van-white)_ | - |
|
||||||
|
| --van-barrage-font | _-apple-system-font, Helvetica Neue, Arial, sans-serif_ | - |
|
103
packages/vant/src/barrage/demo/index.vue
Normal file
103
packages/vant/src/barrage/demo/index.vue
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import VanBarrage, { BarrageInstance } from '..';
|
||||||
|
import VanButton from '../../button';
|
||||||
|
import VanSpace from '../../space';
|
||||||
|
import { useTranslate } from '../../../docs/site';
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import { useToggle } from '@vant/use';
|
||||||
|
|
||||||
|
const t = useTranslate({
|
||||||
|
'zh-CN': {
|
||||||
|
barrage: '弹幕',
|
||||||
|
play: '开始',
|
||||||
|
pause: '暂停',
|
||||||
|
videoBarrage: '模仿视频弹幕',
|
||||||
|
lightweight: '轻量',
|
||||||
|
customizable: '可定制的',
|
||||||
|
mobile: '移动端',
|
||||||
|
library: '组件库',
|
||||||
|
},
|
||||||
|
'en-US': {
|
||||||
|
barrage: 'barrage',
|
||||||
|
play: 'play',
|
||||||
|
pause: 'pause',
|
||||||
|
videoBarrage: 'Imitate video barrage',
|
||||||
|
lightweight: 'Lightweight',
|
||||||
|
customizable: 'Customizable',
|
||||||
|
mobile: 'Mobile',
|
||||||
|
library: 'Library',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const defaultList = [
|
||||||
|
{ id: 100, text: t('lightweight') },
|
||||||
|
{ id: 101, text: t('customizable') },
|
||||||
|
{ id: 102, text: t('mobile') },
|
||||||
|
{ id: 103, text: 'Vue' },
|
||||||
|
{ id: 104, text: t('library') },
|
||||||
|
{ id: 105, text: 'VantUI' },
|
||||||
|
{ id: 106, text: '666' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const list = ref([...defaultList]);
|
||||||
|
const add = () => {
|
||||||
|
list.value.push({ id: Math.random(), text: 'Barrage' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const videoList = ref([...defaultList]);
|
||||||
|
const videoBarrage = ref<BarrageInstance>();
|
||||||
|
const videoAdd = () => {
|
||||||
|
videoList.value.push({ id: Math.random(), text: 'Barrage' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const [isPlay, toggle] = useToggle(false);
|
||||||
|
|
||||||
|
watch(isPlay, () => {
|
||||||
|
if (isPlay.value) videoBarrage.value?.play();
|
||||||
|
else videoBarrage.value?.pause();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<demo-block :title="t('basicUsage')">
|
||||||
|
<van-barrage v-model="list">
|
||||||
|
<div class="video"></div>
|
||||||
|
</van-barrage>
|
||||||
|
<van-space style="margin-top: 10px">
|
||||||
|
<van-button @click="add" type="primary" size="small">
|
||||||
|
{{ t('barrage') }}
|
||||||
|
</van-button>
|
||||||
|
</van-space>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('videoBarrage')">
|
||||||
|
<van-barrage v-model="videoList" ref="videoBarrage" :auto-play="false">
|
||||||
|
<div class="video"></div>
|
||||||
|
</van-barrage>
|
||||||
|
<van-space style="margin-top: 10px">
|
||||||
|
<van-button
|
||||||
|
@click="videoAdd"
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
:disabled="!isPlay"
|
||||||
|
>
|
||||||
|
{{ t('barrage') }}
|
||||||
|
</van-button>
|
||||||
|
<van-button @click="toggle()" size="small">
|
||||||
|
{{ isPlay ? t('pause') : t('play') }}
|
||||||
|
</van-button>
|
||||||
|
</van-space>
|
||||||
|
</demo-block>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.demo-barrage {
|
||||||
|
padding: var(--van-padding-sm);
|
||||||
|
background-color: var(--van-background-2);
|
||||||
|
.video {
|
||||||
|
background-color: var(--van-gray-2);
|
||||||
|
width: 100%;
|
||||||
|
height: 150px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
39
packages/vant/src/barrage/index.less
Normal file
39
packages/vant/src/barrage/index.less
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
:root {
|
||||||
|
--van-barrage-font-size: 16px;
|
||||||
|
--van-barrage-space: 10px;
|
||||||
|
--van-barrage-font: -apple-system-font, helvetica neue, arial, sans-serif;
|
||||||
|
--van-barrage-color: var(--van-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
.van-barrage {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
&__item {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 99;
|
||||||
|
padding-bottom: var(--van-barrage-space);
|
||||||
|
opacity: 0.75;
|
||||||
|
line-height: 1;
|
||||||
|
font-size: var(--van-barrage-font-size);
|
||||||
|
font-family: var(--van-barrage-font);
|
||||||
|
font-weight: bold;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: var(--van-barrage-color);
|
||||||
|
text-shadow: 1px 0 1px #000000, 0 1px 1px #000000, 0 -1px 1px #000000,
|
||||||
|
-1px 0 1px #000000;
|
||||||
|
user-select: none;
|
||||||
|
will-change: transform;
|
||||||
|
transform: translateX(110%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes van-barrage {
|
||||||
|
from {
|
||||||
|
transform: translateX(110%);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateX(var(--move-distance));
|
||||||
|
}
|
||||||
|
}
|
15
packages/vant/src/barrage/index.ts
Normal file
15
packages/vant/src/barrage/index.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { withInstall } from '../utils';
|
||||||
|
import _Barrage from './Barrage';
|
||||||
|
|
||||||
|
export const Barrage = withInstall(_Barrage);
|
||||||
|
export default Barrage;
|
||||||
|
|
||||||
|
export { barrageProps } from './Barrage';
|
||||||
|
export type { BarrageProps, BarrageItem } from './Barrage';
|
||||||
|
export type { BarrageInstance } from './types';
|
||||||
|
|
||||||
|
declare module 'vue' {
|
||||||
|
export interface GlobalComponents {
|
||||||
|
VanBarrage: typeof Barrage;
|
||||||
|
}
|
||||||
|
}
|
134
packages/vant/src/barrage/test/__snapshots__/demo.spec.ts.snap
Normal file
134
packages/vant/src/barrage/test/__snapshots__/demo.spec.ts.snap
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`should render demo and match snapshot 1`] = `
|
||||||
|
<div>
|
||||||
|
<div class="van-barrage"
|
||||||
|
style="--move-distance: -100px;"
|
||||||
|
>
|
||||||
|
<div class="video">
|
||||||
|
</div>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 0ms; animation-name: van-barrage; animation-timing-function: linear; top: 10px;"
|
||||||
|
data-id="100"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 300ms; animation-name: van-barrage; animation-timing-function: linear; top: 110px;"
|
||||||
|
data-id="101"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 600ms; animation-name: van-barrage; animation-timing-function: linear; top: 210px;"
|
||||||
|
data-id="102"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 900ms; animation-name: van-barrage; animation-timing-function: linear; top: 310px;"
|
||||||
|
data-id="103"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1200ms; animation-name: van-barrage; animation-timing-function: linear; top: 10px;"
|
||||||
|
data-id="104"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1500ms; animation-name: van-barrage; animation-timing-function: linear; top: 110px;"
|
||||||
|
data-id="105"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1800ms; animation-name: van-barrage; animation-timing-function: linear; top: 210px;"
|
||||||
|
data-id="106"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="van-space van-space--horizontal van-space--align-center"
|
||||||
|
style="margin-top: 10px;"
|
||||||
|
>
|
||||||
|
<div class="van-space-item">
|
||||||
|
<button type="button"
|
||||||
|
class="van-button van-button--primary van-button--small"
|
||||||
|
>
|
||||||
|
<div class="van-button__content">
|
||||||
|
<span class="van-button__text">
|
||||||
|
barrage
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-barrage"
|
||||||
|
style="--move-distance: -100px;"
|
||||||
|
>
|
||||||
|
<div class="video">
|
||||||
|
</div>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 0ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 10px;"
|
||||||
|
data-id="100"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 300ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 110px;"
|
||||||
|
data-id="101"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 600ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 210px;"
|
||||||
|
data-id="102"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 900ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 310px;"
|
||||||
|
data-id="103"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1200ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 10px;"
|
||||||
|
data-id="104"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1500ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 110px;"
|
||||||
|
data-id="105"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1800ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 210px;"
|
||||||
|
data-id="106"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="van-space van-space--horizontal van-space--align-center"
|
||||||
|
style="margin-top: 10px;"
|
||||||
|
>
|
||||||
|
<div class="van-space-item"
|
||||||
|
style="margin-right: 8px;"
|
||||||
|
>
|
||||||
|
<button type="button"
|
||||||
|
class="van-button van-button--primary van-button--small van-button--disabled"
|
||||||
|
disabled
|
||||||
|
>
|
||||||
|
<div class="van-button__content">
|
||||||
|
<span class="van-button__text">
|
||||||
|
barrage
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="van-space-item">
|
||||||
|
<button type="button"
|
||||||
|
class="van-button van-button--default van-button--small"
|
||||||
|
>
|
||||||
|
<div class="van-button__content">
|
||||||
|
<span class="van-button__text">
|
||||||
|
play
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
139
packages/vant/src/barrage/test/__snapshots__/index.spec.tsx.snap
Normal file
139
packages/vant/src/barrage/test/__snapshots__/index.spec.tsx.snap
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`should auto play when only list props 1`] = `
|
||||||
|
<div class="van-barrage"
|
||||||
|
style="--move-distance: -100px;"
|
||||||
|
>
|
||||||
|
<div class="video"
|
||||||
|
style="width: 100%; height: 150px;"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 0ms; animation-name: van-barrage; animation-timing-function: linear; top: 10px;"
|
||||||
|
data-id="100"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 300ms; animation-name: van-barrage; animation-timing-function: linear; top: 110px;"
|
||||||
|
data-id="101"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 600ms; animation-name: van-barrage; animation-timing-function: linear; top: 210px;"
|
||||||
|
data-id="102"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 900ms; animation-name: van-barrage; animation-timing-function: linear; top: 310px;"
|
||||||
|
data-id="103"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1200ms; animation-name: van-barrage; animation-timing-function: linear; top: 10px;"
|
||||||
|
data-id="104"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1500ms; animation-name: van-barrage; animation-timing-function: linear; top: 110px;"
|
||||||
|
data-id="105"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1800ms; animation-name: van-barrage; animation-timing-function: linear; top: 210px;"
|
||||||
|
data-id="106"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`should emit "update:modelValue" when animationend 1`] = `
|
||||||
|
<div class="van-barrage"
|
||||||
|
style="--move-distance: -100px;"
|
||||||
|
>
|
||||||
|
<div class="video"
|
||||||
|
style="width: 100%; height: 150px;"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 0ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 10px;"
|
||||||
|
data-id="100"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 300ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 110px;"
|
||||||
|
data-id="101"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 600ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 210px;"
|
||||||
|
data-id="102"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 900ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 310px;"
|
||||||
|
data-id="103"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1200ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 10px;"
|
||||||
|
data-id="104"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1500ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 110px;"
|
||||||
|
data-id="105"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1800ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 210px;"
|
||||||
|
data-id="106"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`should not auto play use play function when use play function 1`] = `
|
||||||
|
<div class="van-barrage"
|
||||||
|
style="--move-distance: -100px;"
|
||||||
|
>
|
||||||
|
<div class="video"
|
||||||
|
style="width: 100%; height: 150px;"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 0ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 10px;"
|
||||||
|
data-id="100"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 300ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 110px;"
|
||||||
|
data-id="101"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 600ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 210px;"
|
||||||
|
data-id="102"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 900ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 310px;"
|
||||||
|
data-id="103"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1200ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 10px;"
|
||||||
|
data-id="104"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1500ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 110px;"
|
||||||
|
data-id="105"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<span class="van-barrage__item"
|
||||||
|
style="animation-duration: 4000ms; animation-delay: 1800ms; animation-name: van-barrage; animation-timing-function: linear; animation-play-state: paused; top: 210px;"
|
||||||
|
data-id="106"
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
`;
|
4
packages/vant/src/barrage/test/demo.spec.ts
Normal file
4
packages/vant/src/barrage/test/demo.spec.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import Demo from '../demo/index.vue';
|
||||||
|
import { snapshotDemo } from '../../../test/demo';
|
||||||
|
|
||||||
|
snapshotDemo(Demo);
|
145
packages/vant/src/barrage/test/index.spec.tsx
Normal file
145
packages/vant/src/barrage/test/index.spec.tsx
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
import { ref } from 'vue';
|
||||||
|
import { Barrage, BarrageInstance } from '..';
|
||||||
|
import { mount, trigger } from '../../../test';
|
||||||
|
import { flushPromises } from '@vue/test-utils';
|
||||||
|
|
||||||
|
test('should auto play when only list props', async () => {
|
||||||
|
const wrapper = mount({
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Barrage
|
||||||
|
modelValue={[
|
||||||
|
{ id: 100, text: '轻量' },
|
||||||
|
{ id: 101, text: '可定制的' },
|
||||||
|
{ id: 102, text: '移动端' },
|
||||||
|
{ id: 103, text: 'Vue' },
|
||||||
|
{ id: 104, text: '组件库' },
|
||||||
|
{ id: 105, text: 'VantUI' },
|
||||||
|
{ id: 106, text: '666' },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<div class="video" style="width: 100%; height: 150px"></div>
|
||||||
|
</Barrage>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await flushPromises();
|
||||||
|
expect(wrapper.html()).toMatchSnapshot();
|
||||||
|
expect(wrapper.findAll('.van-barrage__item')).toHaveLength(7);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not auto play use play function when use play function', async () => {
|
||||||
|
const barrage = ref<BarrageInstance>();
|
||||||
|
const wrapper = mount({
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Barrage
|
||||||
|
ref={barrage}
|
||||||
|
autoPlay={false}
|
||||||
|
modelValue={[
|
||||||
|
{ id: 100, text: '轻量' },
|
||||||
|
{ id: 101, text: '可定制的' },
|
||||||
|
{ id: 102, text: '移动端' },
|
||||||
|
{ id: 103, text: 'Vue' },
|
||||||
|
{ id: 104, text: '组件库' },
|
||||||
|
{ id: 105, text: 'VantUI' },
|
||||||
|
{ id: 106, text: '666' },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<div class="video" style="width: 100%; height: 150px"></div>
|
||||||
|
</Barrage>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await flushPromises();
|
||||||
|
expect(wrapper.html()).toMatchSnapshot();
|
||||||
|
expect(wrapper.findAll('.van-barrage__item')).toHaveLength(7);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
(wrapper.find('.van-barrage__item') as HTMLSpanElement).style
|
||||||
|
.animationPlayState
|
||||||
|
).toBe('paused');
|
||||||
|
|
||||||
|
barrage.value?.play();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
(wrapper.find('.van-barrage__item') as HTMLSpanElement).style
|
||||||
|
.animationPlayState
|
||||||
|
).toBe('running');
|
||||||
|
|
||||||
|
barrage.value?.pause();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
(wrapper.find('.van-barrage__item') as HTMLSpanElement).style
|
||||||
|
.animationPlayState
|
||||||
|
).toBe('paused');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should emit "update:modelValue" when animationend', async () => {
|
||||||
|
const barrage = ref<BarrageInstance>();
|
||||||
|
const wrapper = mount({
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Barrage
|
||||||
|
ref={barrage}
|
||||||
|
autoPlay={false}
|
||||||
|
modelValue={[
|
||||||
|
{ id: 100, text: '轻量' },
|
||||||
|
{ id: 101, text: '可定制的' },
|
||||||
|
{ id: 102, text: '移动端' },
|
||||||
|
{ id: 103, text: 'Vue' },
|
||||||
|
{ id: 104, text: '组件库' },
|
||||||
|
{ id: 105, text: 'VantUI' },
|
||||||
|
{ id: 106, text: '666' },
|
||||||
|
]}
|
||||||
|
onUpdate:modelValue={(value) => this.$emit('change', value)}
|
||||||
|
>
|
||||||
|
<div class="video" style="width: 100%; height: 150px"></div>
|
||||||
|
</Barrage>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await flushPromises();
|
||||||
|
expect(wrapper.html()).toMatchSnapshot();
|
||||||
|
expect(wrapper.findAll('.van-barrage__item')).toHaveLength(7);
|
||||||
|
|
||||||
|
barrage.value?.play();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
(wrapper.find('.van-barrage__item') as HTMLSpanElement).style
|
||||||
|
.animationPlayState
|
||||||
|
).toBe('running');
|
||||||
|
|
||||||
|
await wrapper.setProps({
|
||||||
|
modelValue: [
|
||||||
|
{ id: 100, text: '轻量' },
|
||||||
|
{ id: 101, text: '可定制的' },
|
||||||
|
{ id: 102, text: '移动端' },
|
||||||
|
{ id: 103, text: 'Vue' },
|
||||||
|
{ id: 104, text: '组件库' },
|
||||||
|
{ id: 105, text: 'VantUI' },
|
||||||
|
{ id: 106, text: '666' },
|
||||||
|
{ id: 107, text: 'Barrage' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.findAll('.van-barrage__item')).toHaveLength(8);
|
||||||
|
|
||||||
|
await trigger(
|
||||||
|
wrapper.find('.van-barrage__item') as HTMLSpanElement,
|
||||||
|
'animationend'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(wrapper.emitted('change')?.[0][0]).toEqual([
|
||||||
|
{ id: 101, text: '可定制的' },
|
||||||
|
{ id: 102, text: '移动端' },
|
||||||
|
{ id: 103, text: 'Vue' },
|
||||||
|
{ id: 104, text: '组件库' },
|
||||||
|
{ id: 105, text: 'VantUI' },
|
||||||
|
{ id: 106, text: '666' },
|
||||||
|
{ id: 107, text: 'Barrage' },
|
||||||
|
]);
|
||||||
|
});
|
12
packages/vant/src/barrage/types.ts
Normal file
12
packages/vant/src/barrage/types.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { ComponentPublicInstance } from 'vue';
|
||||||
|
import { BarrageProps } from './Barrage';
|
||||||
|
|
||||||
|
export type BarrageExpose = {
|
||||||
|
play(): void;
|
||||||
|
pause(): void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BarrageInstance = ComponentPublicInstance<
|
||||||
|
BarrageProps,
|
||||||
|
BarrageExpose
|
||||||
|
>;
|
@ -239,6 +239,10 @@ location.href = location.href.replace('youzan.github.io', 'vant-ui.github.io');
|
|||||||
path: 'action-sheet',
|
path: 'action-sheet',
|
||||||
title: 'ActionSheet 动作面板',
|
title: 'ActionSheet 动作面板',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'barrage',
|
||||||
|
title: 'Barrage 弹幕',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'dialog',
|
path: 'dialog',
|
||||||
title: 'Dialog 弹出框',
|
title: 'Dialog 弹出框',
|
||||||
@ -687,6 +691,10 @@ location.href = location.href.replace('youzan.github.io', 'vant-ui.github.io');
|
|||||||
path: 'action-sheet',
|
path: 'action-sheet',
|
||||||
title: 'ActionSheet',
|
title: 'ActionSheet',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'barrage',
|
||||||
|
title: 'Barrage',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'dialog',
|
path: 'dialog',
|
||||||
title: 'Dialog',
|
title: 'Dialog',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user