我在React中创建了一个自定义的照片旋转组件(因为外部库太难操作,或者没有完成我希望它做的事情),您可以在移动上滑动到下一张/上一张照片。Android上一切都很好,但这只是IOS Safari。
问题
我有一页画了几个传送带的地图。地图上的第一个旋转木马工作得很好。随后的传送带将在第一张幻灯片后正确地滑动,但是一旦它过渡到第二张幻灯片,触控事件就停止了,并且它不会滑动。我想要的是像第一个旋转木马一样的旋转木马。也没有看到错误消息。请参阅视频
代码
以下是自定义组件:
import { useState, useEffect } from 'react'
const Carousel = ({ children }) => {
const IMG_WIDTH = 400
const [currentIndex, setCurrentIndex] = useState(0)
const [lastTouch, setLastTouch] = useState(0)
const [movement, setMovement] = useState(0)
const [transitionDuration, setTransitionDuration] = useState('')
const [transitionTimeout, setTransitionTimeout] = useState(null)
const maxLength = children.length - 1,
maxMovement = maxLength * IMG_WIDTH
useEffect(() => {
return () => {
clearTimeout(transitionTimeout)
}
}, [])
const transitionTo = (index, duration) => {
setCurrentIndex(index)
setMovement(index * IMG_WIDTH)
setTransitionDuration(`${duration}s`)
setTransitionTimeout(
setTimeout(() => {
setTransitionDuration('0s')
}, duration * 100))
}
const handleMovementEnd = () => {
const endPosition = movement / IMG_WIDTH
const endPartial = endPosition % 1
const endingIndex = endPosition - endPartial
const deltaInteger = endingIndex - currentIndex
let nextIndex = endingIndex
if (deltaInteger >= 0) {
if (endPartial >= 0.1) {
nextIndex++
}
} else if (deltaInteger < 0) {
nextIndex = currentIndex - Math.abs(deltaInteger)
if (endPartial > 0.9) {
nextIndex++
}
}
transitionTo(nextIndex, Math.min(0.5, 1 - Math.abs(endPartial)))
}
const handleMovement = delta => {
clearTimeout(transitionTimeout)
const maxLength = children.length - 1
let nextMovement = movement + delta
if (nextMovement < 0) {
nextMovement = 0
}
if (nextMovement > maxLength * IMG_WIDTH) {
nextMovement = maxLength * IMG_WIDTH
}
setMovement(nextMovement)
setTransitionDuration('0s')
}
const handleTouchStart = event => {
setLastTouch(event.nativeEvent.touches[0].clientX)
}
const handleTouchMove = event => {
const delta = lastTouch - event.nativeEvent.touches[0].clientX
setLastTouch(event.nativeEvent.touches[0].clientX)
handleMovement(delta)
}
const handleTouchEnd = () => {
handleMovementEnd()
setLastTouch(0)
}
return (
<div
className="main"
style={{ width: IMG_WIDTH }}
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
onTouchEnd={handleTouchEnd}>
<div
className="swiper"
style={{
transform: `translateX(${movement * -1}px)`,
transitionDuration: transitionDuration
}}>
{children} // This is just <img /> tags
</div>
<div className="bullets">
{[...Array(children.length)].map((bullet, index) => (
<div key={`bullet-${index}`} className={`dot ${currentIndex === index && 'red-dot'}`} />
))}
</div>
</div>
)
}
export default Carousel下面是我使用自定义组件的代码的一部分:
return (
<>
<Announcement />
<Header />
<section className="tiles-section">
<Title />
{Component} // This is just a component that simply maps out the Carousel, nothing special and no extra styling
</section>
...
</>
)和CSS:
.main {
overflow: hidden;
position: relative;
touch-action: pan-y;
}
.swiper {
display: flex;
overflow-x: visible;
transition-property: transform;
will-change: transform;
}我所知道的/尝试过的
更新#1
我将触摸事件处理程序放入包装{child}的新div中。第二张幻灯片现在可以滑动,但是第三张幻灯片仍然是个泡影。
参考文献
这是我为定制旋转木马组件创建更多上下文的链接教程。
发布于 2021-04-03 06:29:02
经过几天和几个小时后,解决办法有点奇怪。我猜您需要正确地将目标设置为元素的div id。我把这个放在useEffect中,结果如下:
useEffect(() => {
document.getElementById(id).addEventListener('touchstart', () => false, { passive: false })
return () => {
clearTimeout(transitionTimeout)
}
}, [])请注意,id必须是唯一的,特别是如果创建了与我一样的组件的映射。否则,一个旋转木马将滑动所有的旋转木马。
https://stackoverflow.com/questions/66858417
复制相似问题