修改关于海威
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 455 KiB |
|
After Width: | Height: | Size: 1.9 MiB |
@ -0,0 +1,5 @@
|
|||||||
|
const files = require.context('./', false, /\.(png|jpe?g|gif|webp|svg)$/)
|
||||||
|
|
||||||
|
const logos = files.keys().map(key => files(key))
|
||||||
|
|
||||||
|
export default logos
|
||||||
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 13 KiB |
@ -0,0 +1,248 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="viewport" class="infinite-image-scroller">
|
||||||
|
<div
|
||||||
|
ref="track"
|
||||||
|
class="infinite-image-scroller__track"
|
||||||
|
:style="trackStyle"
|
||||||
|
@mouseenter="handleMouseEnter"
|
||||||
|
@mouseleave="handleMouseLeave"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="groupIndex in repeatCount"
|
||||||
|
:key="groupIndex"
|
||||||
|
class="infinite-image-scroller__group"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(image, index) in images"
|
||||||
|
:key="groupIndex + '-' + index"
|
||||||
|
class="infinite-image-scroller__item"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
class="infinite-image-scroller__image"
|
||||||
|
:src="getImageSrc(image)"
|
||||||
|
:alt="getImageAlt(image, index)"
|
||||||
|
draggable="false"
|
||||||
|
@load="updateSize"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'InfiniteImageScroller',
|
||||||
|
|
||||||
|
props: {
|
||||||
|
images: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
initialOffset: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
direction: {
|
||||||
|
type: String,
|
||||||
|
default: 'rtl',
|
||||||
|
validator: function (value) {
|
||||||
|
return [
|
||||||
|
'ltr',
|
||||||
|
'rtl'
|
||||||
|
].indexOf(value) !== -1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
speed: {
|
||||||
|
type: Number,
|
||||||
|
default: 40
|
||||||
|
},
|
||||||
|
gap: {
|
||||||
|
type: [
|
||||||
|
Number,
|
||||||
|
String
|
||||||
|
],
|
||||||
|
default: '1vw'
|
||||||
|
},
|
||||||
|
imageWidth: {
|
||||||
|
type: Number,
|
||||||
|
default: 160
|
||||||
|
},
|
||||||
|
imageHeight: {
|
||||||
|
type: Number,
|
||||||
|
default: 100
|
||||||
|
},
|
||||||
|
pauseOnHover: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
distance: 0,
|
||||||
|
groupWidth: 0,
|
||||||
|
viewportWidth: 0,
|
||||||
|
animationFrameId: null,
|
||||||
|
lastTime: 0,
|
||||||
|
isPaused: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
repeatCount: function () {
|
||||||
|
if (!this.groupWidth || !this.viewportWidth) {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.max(3, Math.ceil(this.viewportWidth / this.groupWidth) + 2)
|
||||||
|
},
|
||||||
|
trackStyle: function () {
|
||||||
|
return {
|
||||||
|
transform: 'translate3d(' + this.translateX + 'px, 0, 0)',
|
||||||
|
'--scroller-gap': this.formatSize(this.gap),
|
||||||
|
'--scroller-image-width': this.imageWidth,
|
||||||
|
'--scroller-image-height': this.imageHeight
|
||||||
|
}
|
||||||
|
},
|
||||||
|
translateX: function () {
|
||||||
|
if (!this.groupWidth) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var phase = this.getPositiveModulo(this.initialOffset + this.distance, this.groupWidth)
|
||||||
|
|
||||||
|
return this.direction === 'ltr' ? phase - this.groupWidth : -phase
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
images: function () {
|
||||||
|
this.$nextTick(this.updateSize)
|
||||||
|
},
|
||||||
|
gap: function () {
|
||||||
|
this.$nextTick(this.updateSize)
|
||||||
|
},
|
||||||
|
imageWidth: function () {
|
||||||
|
this.$nextTick(this.updateSize)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted: function () {
|
||||||
|
this.$nextTick(function () {
|
||||||
|
this.updateSize()
|
||||||
|
this.startAnimation()
|
||||||
|
})
|
||||||
|
window.addEventListener('resize', this.updateSize)
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy: function () {
|
||||||
|
this.stopAnimation()
|
||||||
|
window.removeEventListener('resize', this.updateSize)
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
getImageSrc: function (image) {
|
||||||
|
return typeof image === 'string' ? image : image.src
|
||||||
|
},
|
||||||
|
getImageAlt: function (image, index) {
|
||||||
|
if (typeof image === 'string') {
|
||||||
|
return 'image-' + (index + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return image.alt || 'image-' + (index + 1)
|
||||||
|
},
|
||||||
|
getPositiveModulo: function (value, base) {
|
||||||
|
return ((value % base) + base) % base
|
||||||
|
},
|
||||||
|
formatSize: function (value) {
|
||||||
|
return typeof value === 'number' ? value + 'px' : value
|
||||||
|
},
|
||||||
|
updateSize: function () {
|
||||||
|
var viewport = this.$refs.viewport
|
||||||
|
var track = this.$refs.track
|
||||||
|
|
||||||
|
this.viewportWidth = viewport ? viewport.offsetWidth : 0
|
||||||
|
|
||||||
|
if (!track || !track.children.length) {
|
||||||
|
this.groupWidth = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.groupWidth = track.children[0].offsetWidth
|
||||||
|
},
|
||||||
|
startAnimation: function () {
|
||||||
|
this.stopAnimation()
|
||||||
|
this.lastTime = performance.now()
|
||||||
|
this.animationFrameId = requestAnimationFrame(this.animate)
|
||||||
|
},
|
||||||
|
stopAnimation: function () {
|
||||||
|
if (this.animationFrameId) {
|
||||||
|
cancelAnimationFrame(this.animationFrameId)
|
||||||
|
this.animationFrameId = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
animate: function (time) {
|
||||||
|
var delta = time - this.lastTime
|
||||||
|
|
||||||
|
this.lastTime = time
|
||||||
|
|
||||||
|
if (!this.isPaused && this.groupWidth) {
|
||||||
|
this.distance += this.speed * delta / 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
this.animationFrameId = requestAnimationFrame(this.animate)
|
||||||
|
},
|
||||||
|
handleMouseEnter: function () {
|
||||||
|
if (this.pauseOnHover) {
|
||||||
|
this.isPaused = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleMouseLeave: function () {
|
||||||
|
this.isPaused = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.infinite-image-scroller {
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 14px 0;
|
||||||
|
|
||||||
|
&__track {
|
||||||
|
display: flex;
|
||||||
|
width: max-content;
|
||||||
|
will-change: transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__group {
|
||||||
|
display: flex;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
gap: var(--scroller-gap);
|
||||||
|
padding-right: var(--scroller-gap);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: calc(var(--scroller-image-width) - 2px);
|
||||||
|
height: calc(var(--scroller-image-height) - 2px);
|
||||||
|
flex: 0 0 auto;
|
||||||
|
box-shadow: 0 0 0 1px #e5e5e5, 0 2px 2px rgba(0, 0, 0, 0);
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__image {
|
||||||
|
display: block;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||