因为需要做了一个相册的业务组件,我感觉还挺难看的,分享给大家看一下,能够本人提取,6点几了,上班先!
<template> <div class="img-wrapper"> <el-button icon="h-icon-angle_left" plain class="left to" :disabled="disabledPrev" @click="toRight" ></el-button> <div ref="imagesWrapper" class="images"> <div v-if="noData" class="empty-text"> <slot name="empty">暂无数据</slot> </div> <div v-show="!noData" class="items" :style="itemsStyle"> <div v-for="(item, index) in data" :key="index" class="item-img" :style="imgSize" :class="{ 'is-active': index === currentIndex }" @click="selected(index)" > <img :title="item[props.title]" :src="item[props.url]" /> <p v-if="item[props.title]" v-ellipsis class="item-date"> {{ item[props.title] }} </p> </div> </div> </div> <el-button icon="h-icon-angle_right" :disabled="disabledNext" plain class="right to" @click="Left" ></el-button> </div></template><script>export default { name: 'ImagesGroup', props: { imgSize: { type: Object, default: () => { return { width: '120px', height: '120px' }; } }, value: { type: Number, default: null }, data: { type: Array, default: () => [] } }, data() { return { props: { title: 'title', url: 'url', key: 'key', type: 'type' }, currentIndex: '', translateX: 0, pageSize: 0 // 一页展现的图片数 }; }, computed: { // 偏移度数 itemsStyle() { return { transform: `translateX(${-this.translateX}px)` }; }, // 每一项宽度 itemWidth() { return parseInt(this.imgSize.width.replace('px', '')) + 8; }, disabledPrev() { // 禁用前一页按钮 return this.translateX <= 0; }, disabledNext() { // 禁用后一页按钮 return ( this.translateX >= (this.data.length - this.pageSize) * this.itemWidth ); }, noData() { return this.data.length === 0; }, dataLength() { return this.data.length; } }, watch: { value: { immediate: true, handler(val) { this.currentIndex = val; } } }, mounted() { this.pageSize = this.wrapperWidth() / this.itemWidth; }, methods: { toRight() { if (this.translateX < this.pageSize * this.itemWidth) { this.translateX = 0; } else { this.translateX = this.translateX - this.pageSize * this.itemWidth; } }, Left() { this.translateX = this.translateX + this.pageSize * this.itemWidth; const maxTrans = this.itemWidth * (this.dataLength - this.pageSize); if (this.translateX > maxTrans) { this.translateX = maxTrans; } }, selected(index) { const center = this.pageSize >> 1; // 最初一页的两头地位 const lastCenter = this.dataLength - center; if (index > center && index < lastCenter) { // 与相册两头相差的图片数量 const step = index - center; // 将点击图片挪动到两头 this.translateX = this.itemWidth * step; } else { const maxTrans = this.itemWidth * (this.dataLength - this.pageSize); this.translateX = index <= center ? 0 : maxTrans; } if (this.currentIndex !== index) { this.currentIndex = index; this.$emit('input', index); } }, wrapperWidth() { if (this.$refs.imagesWrapper) { return this.$refs.imagesWrapper.offsetWidth; } return 0; } }};</script><style lang="less" scoped>.img-wrapper { display: flex; position: relative; margin: 20px; height: 120px; .to { width: 32px; height: 100%; padding: 0; } .images::before { position: absolute; z-index: 5; top: 0; height: 100%; width: 84px; content: ''; pointer-events: none; background: -webkit-gradient( linear, left top, right top, from(#fff), color-stop(50%, rgba(0, 0, 0, 0)) ); background: -o-linear-gradient(left, #fff, rgba(0, 0, 0, 0) 50%); background: linear-gradient(90deg, #fff, rgba(0, 0, 0, 0) 50%); } .images::after { position: absolute; z-index: 5; top: 0; height: 100%; right: 0; width: 84px; content: ''; pointer-events: none; background: -webkit-gradient( linear, right top, left top, from(#fff), color-stop(50%, rgba(0, 0, 0, 0)) ); background: -o-linear-gradient(right, #fff, rgba(0, 0, 0, 0) 50%); background: linear-gradient(270deg, #fff, rgba(0, 0, 0, 0) 50%); } .images { position: relative; overflow: hidden; width: 100%; height: 100%; margin: 0 2px; .empty-text { color: rgb(158, 158, 158); height: 100%; display: flex; align-items: center; justify-content: center; } .items { position: absolute; top: 0; left: 0; display: flex; // width: 6000px; height: 100%; align-items: center; transition: transform 0.25s ease; .item-img { display: inline-block; box-sizing: border-box; position: relative; margin-right: 8px; border: 2px solid rgba(0, 0, 0, 0); cursor: pointer; .item-date { bottom: 0px; position: absolute; width: 100%; height: 24px; background: rgba(0, 0, 0, 0.2); text-align: center; line-height: 24px; color: white; } img { width: 100%; height: 100%; } } .item-img:hover::after { // border-color: #409EFF; opacity: 0; } .item-img::after { position: absolute; top: 0; left: 0; width: 100%; height: 100%; content: ''; opacity: 0.2; pointer-events: none; -webkit-transition: opacity 0.3s ease; -o-transition: opacity 0.3s ease; transition: opacity 0.3s ease; background-color: #fff; } .is-active { border-color: #409eff; } .is-active:after { opacity: 0; } } }}</style>