未验证 提交 9d22d453 编写于 作者: 拧巴的猫 提交者: GitHub

fix:修改drag组件 (#72)

* feat: 修改drag组件

* fix: drag组件修改同步修改fixednav组件&&elevator组件滑动修改
上级 a845ed48
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
}, },
"dependencies": { "dependencies": {
"@bem-react/classname": "^1.5.10", "@bem-react/classname": "^1.5.10",
"@react-spring/web": "^9.3.2",
"@use-gesture/react": "^10.2.4",
"classnames": "^2.3.1" "classnames": "^2.3.1"
}, },
"devDependencies": { "devDependencies": {
......
...@@ -4,9 +4,12 @@ import { AnimatingNumbers } from './animatingnumbers' ...@@ -4,9 +4,12 @@ import { AnimatingNumbers } from './animatingnumbers'
const AnimatingNumbersDemo = () => { const AnimatingNumbersDemo = () => {
const [endNumber, setEndNumer] = useState('1570.99') const [endNumber, setEndNumer] = useState('1570.99')
useEffect(() => { useEffect(() => {
setInterval(() => { let timer = setInterval(() => {
setEndNumer(`${Math.floor(Math.random() * 999999)}.${Math.floor(Math.random() * 89 + 10)}`) setEndNumer(`${Math.floor(Math.random() * 999999)}.${Math.floor(Math.random() * 89 + 10)}`)
}, 30000) }, 30000)
return () => {
clearInterval(timer)
}
}, []) }, [])
return ( return (
<> <>
......
.nut-drag { .nut-drag {
position: fixed; position: fixed;
display: inline-block; display: inline-flex;
z-index: 9997 !important; z-index: 9997 !important;
width: fit-content; width: fit-content;
height: fit-content; height: fit-content;
touch-action: none; touch-action: none;
user-select: none;
} }
import React, { FunctionComponent, useState, useEffect, useRef } from 'react' import React, { FunctionComponent, useState, useEffect, useRef } from 'react'
import './drag.scss' import './drag.scss'
import bem from '@/utils/bem' import bem from '@/utils/bem'
import { useDrag } from '@use-gesture/react'
import { useSpring, animated } from '@react-spring/web'
export interface DragProps { export interface DragProps {
attract: boolean attract: boolean
direction: string direction: undefined | string
boundary: { boundary: {
top: number top: number
left: number left: number
...@@ -16,7 +18,7 @@ export interface DragProps { ...@@ -16,7 +18,7 @@ export interface DragProps {
} }
const defaultProps = { const defaultProps = {
attract: false, attract: false,
direction: 'all', direction: undefined,
boundary: { boundary: {
top: 0, top: 0,
left: 0, left: 0,
...@@ -28,151 +30,87 @@ const defaultProps = { ...@@ -28,151 +30,87 @@ const defaultProps = {
export const Drag: FunctionComponent<Partial<DragProps> & React.HTMLAttributes<HTMLDivElement>> = ( export const Drag: FunctionComponent<Partial<DragProps> & React.HTMLAttributes<HTMLDivElement>> = (
props props
) => { ) => {
const { attract, direction, boundary, children, className, ...reset } = { const { attract, direction, boundary, children, className, style, ...reset } = {
...defaultProps, ...defaultProps,
...props, ...props,
} }
const b = bem('drag') const b = bem('drag')
const elWidth = useRef(0) const [boundaryState, setBoundaryState] = useState(boundary)
const elHeight = useRef(0) const myDrag = useRef<HTMLDivElement>(null)
const screenWidth = useRef(0) const [currstyle, api] = useSpring(() => ({
const screenHeight = useRef(0)
const startTop = useRef(0)
const startLeft = useRef(0)
const nx = useRef(0)
const ny = useRef(0)
const xPum = useRef(0)
const yPum = useRef(0)
const position = useRef({
x: 0, x: 0,
y: 0, y: 0,
}))
const screen = useRef({
clientWidth: 0,
clientHeight: 0,
}) })
const boundaryState = useRef({ const element = useRef({
top: 0, offsetWidth: 0,
left: 0, offsetHeight: 0,
right: 0,
bottom: 0,
}) })
const myDrag = useRef<HTMLDivElement>(null)
const getInfo = () => { const getInfo = () => {
const el = myDrag.current const el = myDrag.current
if (el) { if (el) {
const domElem = document.documentElement const { offsetWidth, offsetHeight, offsetTop, offsetLeft } = el
elWidth.current = el.offsetWidth const { clientWidth, clientHeight } = document.documentElement
elHeight.current = el.offsetHeight const { top, left, bottom, right } = boundary
screenWidth.current = domElem.clientWidth element.current = {
screenHeight.current = domElem.clientHeight offsetWidth: offsetWidth,
} offsetHeight: offsetHeight,
}
const goLeft = (target: HTMLElement) => {
if (boundary.left) {
if (+target.style.left.split('px')[0] > boundary.left) {
target.style.left = +target.style.left.split('px')[0] - 10 + 'px'
window.requestAnimationFrame(() => {
goLeft(target)
})
} else {
target.style.left = `${boundary.left}px`
} }
} else { screen.current = {
if (+target.style.left.split('px')[0] > 10) { clientWidth: clientWidth,
target.style.left = +target.style.left.split('px')[0] - 10 + 'px' clientHeight: clientHeight,
window.requestAnimationFrame(() => {
goLeft(target)
})
} else {
target.style.left = '0px'
} }
} setBoundaryState({
} top: -offsetTop + top,
const goRight = (target: HTMLElement, rightLocation: number) => { left: -offsetLeft + left,
if (rightLocation - parseInt(target.style.left.split('px')[0]) > 10) { bottom: clientHeight - offsetHeight - offsetTop - bottom,
target.style.left = parseInt(target.style.left.split('px')[0]) + 10 + 'px' right: clientWidth - offsetWidth - offsetLeft - right,
window.requestAnimationFrame(() => {
goRight(target, rightLocation)
}) })
} else {
target.style.left = rightLocation + 'px'
} }
} }
const touchMove = (e: TouchEvent) => {
e.preventDefault() const bind = useDrag(
const target = e.currentTarget as HTMLElement ({ down, last, offset: [x, y] }) => {
if (e.targetTouches.length === 1) { api.start({ x, y, immediate: down })
const touch = e.targetTouches[0] if (last) {
const x = touch.clientX - position.current.x if (props.direction != 'y' && props.attract) {
const y = touch.clientY - position.current.y if (x < (screen.current.clientWidth - element.current.offsetWidth) / 2) {
xPum.current = startLeft.current + x console.log(x)
yPum.current = startTop.current + y window.requestAnimationFrame(() => {
const rightLocation = screenWidth.current - elWidth.current - boundary.right api.start({ x: boundaryState.left, y, immediate: down })
if (Math.abs(xPum.current) > rightLocation) { })
xPum.current = rightLocation } else {
} else if (xPum.current <= boundary.left) { window.requestAnimationFrame(() => {
xPum.current = boundary.left api.start({
} x: screen.current.clientWidth - element.current.offsetWidth + boundaryState.left,
if (yPum.current < boundary.top) { y,
yPum.current = boundary.top immediate: down,
} else if (yPum.current > screenHeight.current - elHeight.current - boundary.bottom) { })
yPum.current = screenHeight.current - elHeight.current - boundary.bottom })
} }
if (props.direction != 'y') { }
target.style.left = `${xPum.current}px`
}
if (props.direction != 'x') {
target.style.top = `${yPum.current}px`
}
}
}
const touchEnd = (e: TouchEvent) => {
const target = e.currentTarget as HTMLElement
const touch = e.changedTouches[0]
let currX = touch.clientX
const rightLocation = screenWidth.current - elWidth.current - boundary.right
if (currX > rightLocation) {
currX = rightLocation
} else if (currX < boundary.left) {
currX = boundary.left
} else {
currX = currX < screenWidth.current / 2 ? boundary.left : rightLocation
}
if (props.direction != 'y' && props.attract) {
if (currX < screenWidth.current / 2) {
window.requestAnimationFrame(() => {
goLeft(target)
})
} else {
window.requestAnimationFrame(() => {
goRight(target, rightLocation)
})
} }
},
{
from: () => [currstyle.x.get(), currstyle.y.get()],
axis: direction,
bounds: boundaryState,
} }
} )
const touchStart = (e: React.TouchEvent<HTMLDivElement>) => {
const target = e.currentTarget as HTMLElement
const touches = e.touches[0]
startTop.current = target.offsetTop
startLeft.current = target.offsetLeft
position.current = { x: touches.clientX, y: touches.clientY }
target.removeEventListener('touchmove', touchMove, false)
target.removeEventListener('touchend', touchEnd, false)
target.addEventListener('touchmove', touchMove, false)
target.addEventListener('touchend', touchEnd, false)
}
useEffect(() => { useEffect(() => {
getInfo() getInfo()
}, []) }, [myDrag])
return ( return (
<div <div style={style} className={`${b()} ${className}`} {...reset} ref={myDrag}>
className={`${b()} ${className}`} <animated.div style={currstyle} {...bind()}>
{...reset} {children}
ref={myDrag} </animated.div>
onTouchStart={(event) => touchStart(event)}
>
{children}
</div> </div>
) )
} }
......
...@@ -111,12 +111,8 @@ export const Elevator: FunctionComponent< ...@@ -111,12 +111,8 @@ export const Elevator: FunctionComponent<
state.current.anchorIndex = +index state.current.anchorIndex = +index
setCurrentIndex((currentIndex) => currentIndex + index) setCurrentIndex((currentIndex) => currentIndex + index)
scrollTo(index) scrollTo(index)
const target = e.currentTarget as HTMLElement const target = e.currentTarget as HTMLElement
target.removeEventListener('touchmove', () => touchMove(e), false)
target.removeEventListener('touchend', touchEnd, false) target.removeEventListener('touchend', touchEnd, false)
target.addEventListener('touchmove', () => touchMove(e), false)
target.addEventListener('touchend', touchEnd, false) target.addEventListener('touchend', touchEnd, false)
} }
...@@ -176,7 +172,11 @@ export const Elevator: FunctionComponent< ...@@ -176,7 +172,11 @@ export const Elevator: FunctionComponent<
{indexList.length && scrollStart ? ( {indexList.length && scrollStart ? (
<div className={b('code', { current: true })}> {indexList[currentIndex][acceptKey]}</div> <div className={b('code', { current: true })}> {indexList[currentIndex][acceptKey]}</div>
) : null} ) : null}
<div className={b('bars')} onTouchStart={(event) => touchStart(event)}> <div
className={b('bars')}
onTouchStart={(event) => touchStart(event)}
onTouchMove={(event) => touchMove(event)}
>
<div className={b('bars__inner')}> <div className={b('bars__inner')}>
{indexList.map((item: any, index: number) => { {indexList.map((item: any, index: number) => {
return ( return (
......
...@@ -127,3 +127,6 @@ ...@@ -127,3 +127,6 @@
} }
} }
} }
.nut-drag .nut-fixednav {
position: inherit;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册