| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- import { MovableArea, MovableView, View, ScrollView, Text, Image } from '@tarojs/components'
- import './MoveOrderList.scss'
- import { useEffect, useRef, useState } from 'react';
- import { ColorType } from '@/context/themes/color';
- import Taro from '@tarojs/taro';
- import { IconDrag } from '@/components/basic/Icons';
- export default function Component(props: { array: any, itemHeight: number, color?: string,update:Function }) {
- const [list, setList] = useState(props.array)
- const [movaleViewY, setMovaleViewY] = useState(0)
- const [dragElement, setDragElement] = useState(null)
- const [lastTarget, setLastTarget] = useState(null)
- const [startOffsetY, setStartOffsetY] = useState(0)
- const [startPageY, setStartPageY] = useState(0)
- const [dragIndex, setDragIndex] = useState(-1)
- const [scrollThreshold, setScrollThreshold] = useState(0.5)
- const upperThreshold = 100
- const lowThreshold = 100
- const [duration, setDuration] = useState(1000)
- const [canScroll, setCanScroll] = useState(true)
- const [changedIndex, setChangedIndex] = useState(-1)
- const [hiddenContent, setHiddenContent] = useState(false)
- const [scrollTop, setScrollTop] = useState(0)
- const [contentY, setContentY] = useState(0)
- const [contentHeight, setContentHeight] = useState(0)
- const ref = useRef(null)
- useEffect(() => {
- const query = Taro.createSelectorQuery();
- query.select('#myScrollView').boundingClientRect();
- query.exec((res) => {
- setContentY(res[0].top)
- setContentHeight(res[0].height)
- })
- }, [])
- function longPress(e, index) {
- setChangedIndex(index)
- setStartOffsetY(e.target.offsetTop)
- setStartPageY(e.touches[0].pageY)
- setDragIndex(index)
- setDragElement(list[index])
- setMovaleViewY(e.target.offsetTop)
- setCanScroll(false)
- }
- function touchMove(e) {
- if (dragElement) {
- let clientY = e.touches[0].clientY;
- pageScroll(clientY);
- let pageY = e.touches[0].pageY;
- let targetMoveDistance = pageY - startPageY
- let movaleViewY2 = startOffsetY + targetMoveDistance
- let targetIndex = computeFutureIndex(targetMoveDistance, dragIndex)
- if (targetIndex !== false && targetIndex != changedIndex) {
- var temps = swapListItems(list, targetIndex, changedIndex)
- setList(temps)
- setChangedIndex(targetIndex)
- }
- if (targetIndex === false && targetIndex != changedIndex) {
- var temps = swapListItems(list, dragIndex, changedIndex)
- setList(temps)
- setChangedIndex(dragIndex)
- }
- setMovaleViewY(movaleViewY2)
- setLastTarget(targetIndex as any)
- setHiddenContent(true)
- }
- }
- function pageScroll(clientY) {
- return
- // console.log(clientY,contentY,contentHeight)
- if ((clientY - contentY) + upperThreshold >= contentHeight) {
- // var scroll = ref.current
- // debugger
- // (ref.current as any).scrollTo({scrollTop:100})
- // setScrollTop((clientY - contentY) + props.itemHeight)
- // setScrollTop(2200)
- // setCanScroll(true)
- Taro.pageScrollTo({
- selector: '#myScrollView',
- scrollTop: (clientY - contentY) + props.itemHeight,
- duration: 200
- })
- }
- else if ((clientY - contentY) - lowThreshold <= 0) {
- setScrollTop((clientY - contentY) - props.itemHeight)
- // setCanScroll(true)
- }
- else {
- // setCanScroll(true)
- }
- }
- function swapListItems<T>(list: T[], index1: number, index2: number): T[] {
- const newList = [...list];
- const temp = newList[index1];
- newList[index1] = newList[index2];
- newList[index2] = temp;
- return newList;
- }
- function touchEnd(e) {
- if (dragElement) {
- // let pageY = e.changedTouches[0].pageY
- // let targetMoveDistance = pageY - startPageY;
- // let dragElementIndex = dragIndex;
- // const futrueIndex = computeFutureIndex(targetMoveDistance, dragElementIndex)
- // if (futrueIndex !== false) {
- // var temps = list
- // temps.splice(futrueIndex, 0, temps.splice(dragIndex, 1)[0])
- // setList(temps)
- // }
- setDragElement(null)
- setLastTarget(null)
- setDragIndex(-1)
- }
- setChangedIndex(-1)
- setCanScroll(true)
- setHiddenContent(false)
- setMovaleViewY(-100)
- props.update(list)
- }
- function computeFutureIndex(targetMoveDistance, dragElementIndex) {
- let willInsertAfter = getSwapDirection(targetMoveDistance);
- if (willInsertAfter !== false) {
- /** 偏移索引 */
- let offsetElementIndex = dragElementIndex + willInsertAfter;
- /** 移动步数 */
- let step = targetMoveDistance / props.itemHeight;
- /** 步数补偿,当只有移动距离超过单项 _scrollThreshold 时才算有效 */
- if (step <= -1) {
- step += scrollThreshold;
- } else if (step >= 1) {
- step -= scrollThreshold;
- }
- /** 目标索引 */
- let futureIndex = parseInt(step) + offsetElementIndex;
- // 避免越界
- if (futureIndex < 0) {
- futureIndex = 0;
- } else if (futureIndex > list.length - 1) {
- futureIndex = list.length - 1;
- }
- return futureIndex;
- } else {
- return willInsertAfter;
- }
- }
- function getSwapDirection(targetMoveDistance) {
- if (Math.abs(targetMoveDistance) < props.itemHeight / 2) {
- // 轻轻拂动,滑动距离小于1/2单项高度
- return false;
- } else if (targetMoveDistance >= props.itemHeight / 2) {
- // console.log('[_getSwapDirection] 👇👇👇');
- return 1; // 下滑
- } else if (targetMoveDistance <= props.itemHeight / -2) {
- // console.log('[_getSwapDirection] 👆👆👆');
- return -1; // 上滑
- }
- }
- console.log(list)
- return <View id="myScrollView" ref={ref} style={{height:'100%', overflow: canScroll?'scroll':'hidden' }} catchMove>
- <MovableArea style={{ height: list.length * props.itemHeight, width: '100vw' }}>
- {list.map((item, index) => {
- return <View style={{ opacity: changedIndex == index && hiddenContent ? 0 : 1, height: props.itemHeight, width: '100vw' }}
- onLongPress={(e) => longPress(e, index)}
-
- onTouchMove={(e) => touchMove(e)}
- onTouchEnd={(e) => touchEnd(e)}
- >
- <View className='modal_order_item' style={{ height: 40}}>
- <Text style={{ color: props.color }}>{item.name}</Text>
- <IconDrag width={17} height={12} />
- {/* <Image src={require('@assets/images/menu.png')} style={{width:20,height:20}}/> */}
- </View>
- </View>
- })}
- <MovableView style={{ height: changedIndex>=0?props.itemHeight:0,width:'100vw' }}
- direction='vertical'
- disabled
- animation={false}
- y={movaleViewY}
- >
- <View className='drag_item' style={{ backgroundColor: props.color }}>
- {
- dragIndex >= 0 && <View className='modal_sel_item' style={{ height: 40, border:'none' }}>
- <Text style={{ color: 'black',fontWeight:'bold' }}>{list[changedIndex].name}</Text>
- <IconDrag width={17} height={12} />
- </View>
- }
- </View>
- </MovableView>
- </MovableArea>
- </View>
- }
|