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

fix:修改drag组件 (#72)

* feat: 修改drag组件

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