提交 2ef3852d 编写于 作者: D DCloud_LXH

feat(h5): swiper add navigation

上级 feaa4d1f
<script> <script>
import touchtrack from 'uni-mixins/touchtrack' import touchtrack from 'uni-mixins/touchtrack'
import { deepClone } from 'uni-shared' import { deepClone } from 'uni-shared'
...@@ -66,6 +65,18 @@ export default { ...@@ -66,6 +65,18 @@ export default {
disableTouch: { disableTouch: {
type: [Boolean, String], type: [Boolean, String],
default: false default: false
},
navigation: {
type: [Boolean, String],
default: false
},
navigationColor: {
type: String,
default: '#fff'
},
navigationActiveColor: {
type: String,
default: 'rgba(53, 53, 53, 0.6)'
} }
}, },
data () { data () {
...@@ -74,7 +85,12 @@ export default { ...@@ -74,7 +85,12 @@ export default {
currentItemIdSync: this.currentItemId || '', currentItemIdSync: this.currentItemId || '',
userTracking: false, userTracking: false,
currentChangeSource: '', currentChangeSource: '',
items: [] items: [],
isNavigationAuto: false,
hideNavigation: false,
prevDisabled: false,
nextDisabled: false
} }
}, },
computed: { computed: {
...@@ -114,8 +130,11 @@ export default { ...@@ -114,8 +130,11 @@ export default {
height: !this.vertical ? '100%' : value height: !this.vertical ? '100%' : value
} }
}, },
swiperEnabled () {
return this.items.length > this.displayMultipleItemsNumber
},
circularEnabled () { circularEnabled () {
return this.circular && this.items.length > this.displayMultipleItemsNumber return this.circular && this.swiperEnabled
} }
}, },
watch: { watch: {
...@@ -137,6 +156,7 @@ export default { ...@@ -137,6 +156,7 @@ export default {
currentSync (val, oldVal) { currentSync (val, oldVal) {
this._currentChanged(val, oldVal) this._currentChanged(val, oldVal)
this.$emit('update:current', val) this.$emit('update:current', val)
this._setNavigationState()
}, },
currentItemId (val) { currentItemId (val) {
this._currentCheck() this._currentCheck()
...@@ -146,6 +166,21 @@ export default { ...@@ -146,6 +166,21 @@ export default {
}, },
displayMultipleItemsNumber () { displayMultipleItemsNumber () {
this._resetLayout() this._resetLayout()
},
navigation (val) {
this.isNavigationAuto = val === 'auto'
this.hideNavigation = val !== true || this.isNavigationAuto
this._navigationSwiperAddMouseEvent()
},
items () {
this._setNavigationState()
},
swiperEnabled (val) {
if (!val) {
this.prevDisabled = true
this.nextDisabled = true
this.isNavigationAuto && (this.hideNavigation = true)
}
} }
}, },
created () { created () {
...@@ -168,6 +203,7 @@ export default { ...@@ -168,6 +203,7 @@ export default {
}, this._inintAutoplay) }, this._inintAutoplay)
this._inintAutoplay(this.autoplay && !this.userTracking) this._inintAutoplay(this.autoplay && !this.userTracking)
this.$watch('items.length', this._resetLayout) this.$watch('items.length', this._resetLayout)
this._navigationSwiperAddMouseEvent()
}, },
beforeDestroy () { beforeDestroy () {
this._cancelSchedule() this._cancelSchedule()
...@@ -464,6 +500,8 @@ export default { ...@@ -464,6 +500,8 @@ export default {
position += length position += length
} }
} }
} else if (source === 'click') {
current = current + this.displayMultipleItemsNumber - 1 < length ? current : 0
} }
this._animating = { this._animating = {
...@@ -586,6 +624,91 @@ export default { ...@@ -586,6 +624,91 @@ export default {
return false return false
} }
} }
},
/**
* navigation
*/
_onSwiperDotClick (index) {
this._animateViewport(
(this.currentSync = index),
(this.currentChangeSource = 'click'),
this.circularEnabled ? 1 : 0
)
},
_navigationClick (type) {
const swiperItemLength = this.items.length
let _current = this.currentSync
switch (type) {
case 'prev':
_current--
if (_current < 0 && this.circularEnabled) {
_current = swiperItemLength - 1
}
break
case 'next':
_current++
if (_current >= swiperItemLength && this.circularEnabled) {
_current = 0
}
break
}
this._onSwiperDotClick(_current)
},
_navigationMouseMove (e) {
const { clientX, clientY } = e
const {
left,
right,
top,
bottom,
width,
height
} = this.$refs.slidesWrapper.getBoundingClientRect()
if (this.vertical) {
this.hideNavigation = !(
clientY - top < height / 3 || bottom - clientY < height / 3
)
} else {
this.hideNavigation = !(
clientX - left < width / 3 || right - clientX < width / 3
)
}
},
_navigationMouseOut () {
this.hideNavigation = true
},
_navigationSwiperAddMouseEvent () {
if (__PLATFORM__ === 'h5') {
const rootRef = this.$refs.slidesWrapper
if (rootRef) {
rootRef.removeEventListener('mousemove', this._navigationMouseMove)
rootRef.removeEventListener('mouseout', this._navigationMouseOut)
if (this.isNavigationAuto) {
rootRef.addEventListener('mousemove', this._navigationMouseMove)
rootRef.addEventListener('mouseout', this._navigationMouseOut)
}
}
}
},
_navigationHover (event, type) {
const target = event.currentTarget
if (!target) return
target.style.backgroundColor =
type === 'over' ? this.navigationActiveColor : ''
},
_setNavigationState () {
const swiperItemLength = this.items.length
const notCircular = !this.circularEnabled
this.prevDisabled = this.currentSync === 0 && notCircular
this.nextDisabled =
(this.currentSync === swiperItemLength - 1 && notCircular) ||
(notCircular &&
this.currentSync + this.displayMultipleItemsNumber >= swiperItemLength)
} }
}, },
render (createElement) { render (createElement) {
...@@ -602,9 +725,7 @@ export default { ...@@ -602,9 +725,7 @@ export default {
const currentSync = this.currentSync const currentSync = this.currentSync
slidesDots.push(createElement('div', { slidesDots.push(createElement('div', {
on: { on: {
click: () => { click: () => this._onSwiperDotClick(index)
this._animateViewport(this.currentSync = index, this.currentChangeSource = 'click', this.circularEnabled ? 1 : 0)
}
}, },
class: { class: {
'uni-swiper-dot': true, 'uni-swiper-dot': true,
...@@ -634,6 +755,70 @@ export default { ...@@ -634,6 +755,70 @@ export default {
}, slidesDots)) }, slidesDots))
} }
if (__PLATFORM__ === 'h5') {
if (this.navigation) {
const navigationClass = {
'uni-swiper-navigation-hide': this.hideNavigation,
'uni-swiper-navigation-vertical': this.vertical
}
const iconElement = createElement(
'i',
{
domProps: {
innerHTML: '&#xe601;'
},
class: 'uni-btn-icon',
style: { color: this.navigationColor, fontSize: '26px' }
}
)
const navigationEvent = {
mouseover: event => this._navigationHover(event, 'over'),
mouseout: event => this._navigationHover(event, 'out')
}
slidesWrapperChild.push(
createElement(
'div',
{
on: {
click: () => this._navigationClick('prev'),
...navigationEvent
},
class: [
'uni-swiper-navigation',
'uni-swiper-navigation-prev',
{
'uni-swiper-navigation-disabled': this.prevDisabled,
...navigationClass
}
]
},
[iconElement]
),
createElement(
'div',
{
on: {
click: () => this._navigationClick('next'),
...navigationEvent
},
class: [
'uni-swiper-navigation',
'uni-swiper-navigation-next',
{
'uni-swiper-navigation-disabled': this.nextDisabled,
...navigationClass
}
]
},
[iconElement]
)
)
}
}
return createElement( return createElement(
'uni-swiper', { 'uni-swiper', {
on: this.$listeners on: this.$listeners
...@@ -734,4 +919,71 @@ uni-swiper .uni-swiper-dot { ...@@ -734,4 +919,71 @@ uni-swiper .uni-swiper-dot {
uni-swiper .uni-swiper-dot-active { uni-swiper .uni-swiper-dot-active {
background-color: #000000; background-color: #000000;
} }
uni-swiper .uni-swiper-navigation {
width: 26px;
height: 26px;
cursor: pointer;
position: absolute;
top: 50%;
margin-top: -13px;
display: flex;
align-items: center;
transition: all 0.2s;
border-radius: 50%;
opacity: 1;
}
uni-swiper .uni-swiper-navigation-disabled {
opacity: 0.35;
cursor: auto;
pointer-events: none;
}
uni-swiper .uni-swiper-navigation-hide {
opacity: 0;
cursor: auto;
pointer-events: none;
}
uni-swiper .uni-swiper-navigation-prev {
left: 10px;
}
uni-swiper .uni-swiper-navigation-prev i {
margin-left: -1px;
left: 10px;
}
uni-swiper .uni-swiper-navigation-prev.uni-swiper-navigation-vertical {
top: 18px;
left: 50%;
margin-left: -13px;
}
uni-swiper .uni-swiper-navigation-prev.uni-swiper-navigation-vertical i {
transform: rotate(90deg);
margin-left: auto;
margin-top: -2px;
}
uni-swiper .uni-swiper-navigation-next {
right: 10px;
}
uni-swiper .uni-swiper-navigation-next i {
transform: rotate(180deg);
}
uni-swiper .uni-swiper-navigation-next.uni-swiper-navigation-vertical {
top: auto;
bottom: 5px;
left: 50%;
margin-left: -13px;
}
uni-swiper .uni-swiper-navigation-next.uni-swiper-navigation-vertical i {
margin-top: 2px;
transform: rotate(270deg);
}
</style> </style>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册