-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
57 changed files
with
6,333 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,136 @@ | ||
# vue-carousel | ||
一个简单、灵活的 Vue3 走马灯组件,非常轻量,只有 5kB。 | ||
# Vue DevUI Carousel | ||
|
||
一个简单、灵活的`Vue3`走马灯组件,非常轻量,只有`5kB`。 | ||
|
||
预览地址: | ||
[https://kagol.gitee.io/vue-carousel/](https://kagol.gitee.io/vue-carousel/) | ||
|
||
## 快速开始 | ||
|
||
创建一个vite工程: | ||
|
||
``` | ||
yarn create vite vite-demo --template vue-ts | ||
``` | ||
|
||
安装`Carousel`: | ||
``` | ||
yarn add vue-devui-carousel | ||
``` | ||
|
||
在`main.ts`中引入`Carousel`: | ||
``` | ||
import Carousel from 'vue-devui-carousel' | ||
import 'vue-devui-carousel/dist/style.css' | ||
createApp(App) | ||
.use(Carousel) | ||
.mount('#app') | ||
``` | ||
|
||
在`App.vue`中使用: | ||
|
||
``` | ||
<DCarousel> | ||
<div class="carousel-item">page 1</div> | ||
<div class="carousel-item">page 2</div> | ||
<div class="carousel-item">page 3</div> | ||
</DCarousel> | ||
``` | ||
|
||
## 效果动图 | ||
|
||
默认效果: | ||
|
||
![1-default.gif](https://pic.imgdb.cn/item/61f2b4932ab3f51d9107f30c.gif) | ||
|
||
掘金活动: | ||
|
||
![2-juejin.gif](https://pic.imgdb.cn/item/61f2b4932ab3f51d9107f315.gif) | ||
|
||
指示器位置: | ||
|
||
![3-indicator-position.gif](https://pic.imgdb.cn/item/61f2b4932ab3f51d9107f31c.gif) | ||
|
||
自定义指示器: | ||
|
||
![4-custom-indicator.gif](https://pic.imgdb.cn/item/61f2b4932ab3f51d9107f325.gif) | ||
|
||
分页器位置: | ||
|
||
![5-pagination-position.gif](https://pic.imgdb.cn/item/61f2b4932ab3f51d9107f32f.gif) | ||
|
||
自定义分页器: | ||
|
||
![6-custom-pagination.gif](https://pic.imgdb.cn/item/61f2b5282ab3f51d9108b5ef.gif) | ||
|
||
华为官网: | ||
|
||
![7-huawei.gif](https://pic.imgdb.cn/item/61f2b7bb2ab3f51d910d4651.gif) | ||
|
||
QQ音乐: | ||
|
||
![8-qqmusic.gif](https://pic.imgdb.cn/item/61f2bb5d2ab3f51d91146170.gif) | ||
|
||
B站: | ||
|
||
![9-bilibili.gif](https://pic.imgdb.cn/item/61f2b85e2ab3f51d910e65ab.gif) | ||
|
||
手风琴式折叠卡片: | ||
|
||
![10-collapse-card.gif](https://pic.imgdb.cn/item/61f2b6f42ab3f51d910bc018.gif) | ||
|
||
## API | ||
|
||
### DCarousel 组件 | ||
|
||
props | ||
|
||
| 属性 | 类型 | 默认 | 说明 | | ||
| ------- | ------ | ---- | -------------- | | ||
| v-model | Number | 1 | 可选,当前页码 | | ||
| autoplay | Boolean | true | 可选,是否自动播放 | | ||
| interval | Number | 3000 | 可选,自动播放的时间间隔,单位是毫秒 | | ||
|
||
插槽 | ||
|
||
| 属性 | 类型 | 默认 | 说明 | | ||
| ------- | ------ | ---- | -------------- | | ||
| default | -- | -- | 必选,默认插槽 | | ||
| indicator | -- | -- | 可选,指示器插槽 | | ||
| pagination | -- | -- | 可选,分页器插槽 | | ||
|
||
### DCarouselIndicator 组件 | ||
|
||
props | ||
|
||
| 属性 | 类型 | 默认 | 说明 | | ||
| ------- | ------ | ---- | -------------- | | ||
| v-model | Number | 1 | 可选,当前页码 | | ||
| count | Number | -- | 可选,指示器元素数量 | | ||
|
||
插槽 | ||
|
||
| 属性 | 类型 | 默认 | 说明 | | ||
| ------- | ------ | ---- | -------------- | | ||
| default | ({ pageIndex, setPageIndex }) => {} | -- | 可选,默认插槽 | | ||
|
||
### DCarouselPrev 组件 | ||
|
||
插槽 | ||
|
||
| 属性 | 类型 | 默认 | 说明 | | ||
| ------- | ------ | ---- | -------------- | | ||
| default | -- | -- | 可选,默认插槽 | | ||
|
||
### DCarouselNext 组件 | ||
|
||
插槽 | ||
|
||
| 属性 | 类型 | 默认 | 说明 | | ||
| ------- | ------ | ---- | -------------- | | ||
| default | -- | -- | 可选,默认插槽 | | ||
|
||
参考: | ||
|
||
[用积木理论设计的Carousel组件都有哪些有趣的玩法?](https://juejin.cn/post/7056193763810476063/) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { App } from 'vue' | ||
import DCarousel from './src/carousel' | ||
import DCarouselIndicator from './src/components/carousel-indicator' | ||
import DCarouselPrev from './src/components/carousel-prev' | ||
import DCarouselNext from './src/components/carousel-next' | ||
import usePage from './src/composables/use-page' | ||
|
||
export { DCarousel, DCarouselIndicator, DCarouselPrev, DCarouselNext, usePage } | ||
|
||
export default { | ||
install(app: App) { | ||
app.component(DCarousel.name, DCarousel) | ||
app.component(DCarouselIndicator.name, DCarouselIndicator) | ||
app.component(DCarouselPrev.name, DCarouselPrev) | ||
app.component(DCarouselNext.name, DCarouselNext) | ||
app.config.globalProperties.usePage = usePage | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
.devui-carousel { | ||
position: relative; | ||
overflow: hidden; | ||
|
||
.devui-carousel-indicator { | ||
position: absolute; | ||
} | ||
} | ||
|
||
.devui-carousel-item-container { | ||
display: flex; | ||
position: relative; | ||
transition: left 500ms ease 0s; // 内容切换时的动效 | ||
|
||
& > * { | ||
flex: 1; | ||
} | ||
} | ||
|
||
.devui-arrow { | ||
position: absolute; | ||
top: 50%; | ||
margin-top: -18px; | ||
cursor: pointer; | ||
width: 36px; | ||
height: 36px; | ||
border-radius: 18px; | ||
background: var(--devui-highlight-overlay, rgba(255, 255, 255, .8)); | ||
box-shadow: var(--devui-shadow-length-hover, 0 4px 16px 0) var(--devui-light-shadow, rgba(0, 0, 0, .1)); | ||
display: inline-flex; | ||
align-items: center; | ||
justify-content: center; | ||
transition: background-color var(--devui-animation-duration-slow, .3s) var(--devui-animation-ease-in-out-smooth, cubic-bezier(.645, .045, .355, 1)); | ||
|
||
&:hover { | ||
background: var(--devui-area, #f8f8f8); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { defineComponent, renderSlot, useSlots, watch, toRefs, ref } from 'vue' | ||
|
||
// Components | ||
import DCarouselIndicator from './components/carousel-indicator' | ||
import DCarouselPrev from './components/carousel-prev' | ||
import DCarouselNext from './components/carousel-next' | ||
|
||
// Composables | ||
import usePage from './composables/use-page' | ||
import useAutoplay from './composables/use-autoplay' | ||
|
||
// Util | ||
import { formatPageIndex } from './carousel.util' | ||
|
||
// Props/Types | ||
import { carouselProps, CarouselProps } from './carousel.type' | ||
|
||
// SCSS | ||
import './carousel.scss' | ||
|
||
export default defineComponent({ | ||
name: 'DCarousel', | ||
components: { | ||
DCarouselIndicator, | ||
DCarouselPrev, | ||
DCarouselNext, | ||
}, | ||
props: carouselProps, | ||
emits: ['update:modelValue'], | ||
setup(props: CarouselProps, { slots, emit }) { | ||
const { modelValue, autoplay, interval } = toRefs(props) | ||
|
||
const { pageIndex, prevPage, nextPage, setPageIndex } = usePage(modelValue.value) | ||
const { startPlay, stopPlay } = useAutoplay(nextPage, interval.value) | ||
|
||
const count = useSlots().default().filter(item => typeof item.type !== 'symbol').length | ||
const defaultFormattedPageIndex = formatPageIndex(pageIndex.value, count) | ||
const formattedPageIndex = ref(defaultFormattedPageIndex) | ||
|
||
const launchTimer = (autoplay) => { | ||
if (autoplay) { | ||
startPlay() | ||
} else { | ||
stopPlay() | ||
} | ||
} | ||
|
||
launchTimer(autoplay.value) | ||
|
||
watch(autoplay, (newVal) => { | ||
launchTimer(newVal) | ||
}) | ||
|
||
watch(modelValue, (newVal: number) => { | ||
pageIndex.value = newVal | ||
}) | ||
|
||
watch(pageIndex, (newVal: number) => { | ||
emit('update:modelValue', newVal) | ||
formattedPageIndex.value = formatPageIndex(pageIndex.value, count) | ||
}) | ||
|
||
watch(formattedPageIndex, (newVal: number) => { | ||
pageIndex.value = newVal | ||
}) | ||
|
||
return () => { | ||
return ( | ||
<div class="devui-carousel"> | ||
<div | ||
class="devui-carousel-item-container" | ||
style={{ | ||
width: count * 100 + '%', | ||
left: -(formattedPageIndex.value - 1) * 100 + '%', | ||
}} | ||
> | ||
{renderSlot(useSlots(), 'default')} | ||
</div> | ||
{ | ||
slots.pagination | ||
? renderSlot(useSlots(), 'pagination', { | ||
prevPage, nextPage | ||
}) : <> | ||
<DCarouselPrev onClick={() => { | ||
emit('update:modelValue', props.modelValue-1) | ||
prevPage() | ||
}} /> | ||
<DCarouselNext onClick={() => { | ||
emit('update:modelValue', props.modelValue+1) | ||
nextPage() | ||
}} /> | ||
</> | ||
} | ||
{slots.indicator ? ( | ||
slots.indicator({ | ||
count, | ||
pageIndex: formattedPageIndex.value, | ||
setPageIndex | ||
}) | ||
) : ( | ||
<DCarouselIndicator | ||
count={count} | ||
v-model={formattedPageIndex.value} | ||
></DCarouselIndicator> | ||
)} | ||
</div> | ||
) | ||
} | ||
}, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { extractPropTypes } from 'vue' | ||
|
||
export const carouselProps = { | ||
modelValue: { | ||
type: Number, | ||
}, | ||
autoplay: { | ||
type: Boolean, | ||
default: true, | ||
}, | ||
interval: { | ||
type: Number, | ||
default: 3000, | ||
} | ||
} | ||
|
||
export type CarouselProps = extractPropTypes<typeof carouselProps> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export const formatPageIndex = (current, count) => { | ||
if (current <= 0) { | ||
return current + count * (Math.floor(-current / count) + 1) | ||
} else { | ||
return current % count === 0 ? count : current % count | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
export default () => ( | ||
<svg | ||
_ngcontent-jai-c250="" | ||
width="18px" | ||
height="18px" | ||
viewBox="0 0 16 16" | ||
version="1.1" | ||
> | ||
<g | ||
_ngcontent-jai-c250="" | ||
stroke="none" | ||
stroke-width="1" | ||
fill="none" | ||
fill-rule="evenodd" | ||
> | ||
<polygon | ||
_ngcontent-jai-c250="" | ||
fill="#293040" | ||
fill-rule="nonzero" | ||
points="10.7071068 12.2928932 9.29289322 13.7071068 3.58578644 8 9.29289322 2.29289322 10.7071068 3.70710678 6.41421356 8" | ||
></polygon> | ||
</g> | ||
</svg> | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
export default () => ( | ||
<svg | ||
_ngcontent-jai-c250="" | ||
width="18px" | ||
height="18px" | ||
viewBox="0 0 16 16" | ||
version="1.1" | ||
> | ||
<g | ||
_ngcontent-jai-c250="" | ||
stroke="none" | ||
stroke-width="1" | ||
fill="none" | ||
fill-rule="evenodd" | ||
> | ||
<polygon | ||
_ngcontent-jai-c250="" | ||
fill="#293040" | ||
fill-rule="nonzero" | ||
transform="translate(8.146447, 8.000000) scale(-1, 1) translate(-8.146447, -8.000000) " | ||
points="11.7071068 12.2928932 10.2928932 13.7071068 4.58578644 8 10.2928932 2.29289322 11.7071068 3.70710678 7.41421356 8" | ||
></polygon> | ||
</g> | ||
</svg> | ||
) |
Oops, something went wrong.