React.js滑动条鼠标、触摸事件仅在移动端失效问题求助
iOS Safari宽度过渡失效是平台特有的渲染机制问题导致的,按以下步骤修改即可修复:
- 给涉及过渡的CSS类添加GPU加速触发属性,避免软件渲染导致过渡丢失:
.bar { /* 原有样式保留,新增以下属性 */ transform: translateZ(0); will-change: width; } .slide { /* 不要用transition: all,明确指定过渡属性,兼容性更好 */ transition: width 0.3s ease; }
- 修复交互逻辑中的样式更新触发逻辑,手动触发重绘让iOS识别到样式变更:
修改onMouseDown中的setState回调,在设置transition为none后强制重绘:
const onMouseDown = useCallback(e => { e.preventDefault() if (info.isSliding === true) return console.log('mouse down') const percent = getPercent(e.clientX || e.touches[0].clientX) setInfo({ isSliding: true, currentPercent: percent > MAX_PERCENT ? MAX_PERCENT : percent }, () => { barRef.current.style.transition = 'none' // 强制浏览器读取DOM尺寸,触发重绘,确保后续样式变更被识别 void barRef.current.offsetWidth }) }, [info.isSliding])
- 移除
touchend事件的不必要默认行为阻止,避免iOS阻塞动画渲染:
修改onMouseUp逻辑,仅在非触摸事件下执行preventDefault:
const onMouseUp = useCallback(e => { // 触摸事件下不阻止默认行为,避免iOS Safari阻塞后续动画渲染 if (!e.changedTouches) e.preventDefault() console.log('mouse up') const percent = getPercent(e.clientX || e.changedTouches[0].clientX) setInfo(state => ({ ...state, isSliding: false, currentPercent: (percent > MAX_PERCENT) ? MAX_PERCENT : INITIAL_PERCENT })) }, [])
- 给slide类添加的逻辑也补充重绘触发,确保类名变更生效:
useEffect(() => { if (info.isSliding === false) { barRef.current.classList.add('slide') void barRef.current.offsetWidth } else { barRef.current.classList.remove('slide') } }, [info.isSliding])
内容的提问来源于stack exchange,提问作者Evan Jin
相关产品推荐
相关产品推荐

