@ohkit/draggable-box 0.0.3 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +173 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.es.js +1 -1
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +1 -1
- package/dist/index.modern.mjs.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/types/index.d.ts +24 -9
- package/dist/types/type.d.ts +20 -0
- package/package.json +2 -2
- package/src/index.tsx +86 -23
- package/src/style.scss +9 -1
- package/src/type.ts +21 -0
- package/LICENSE.md +0 -5
package/dist/index.umd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.umd.js","sources":["../src/utils.ts","../src/constants.ts","../src/index.tsx"],"sourcesContent":["import {findParent} from '@ohkit/dom-helper';\n\n/**\n * 检查元素是否创建了新的定位上下文(包含块)\n * @param element 要检查的元素\n * @param includePosition 是否检查position属性(absolute/relative/fixed)\n */\nexport function isPositioningContextCreator(element: HTMLElement, includePosition: boolean): boolean {\n const style = window.getComputedStyle(element);\n const position = style.getPropertyValue('position');\n const transform = style.getPropertyValue('transform');\n const filter = style.getPropertyValue('filter');\n const perspective = style.getPropertyValue('perspective');\n const contain = style.getPropertyValue('contain');\n const willChange = style.getPropertyValue('will-change');\n \n return (includePosition && position !== 'static') || \n transform !== 'none' || \n filter !== 'none' || \n perspective !== 'none' ||\n contain.includes('paint') ||\n contain.includes('layout') ||\n contain.includes('strict') ||\n willChange.includes('transform') ||\n willChange.includes('perspective') ||\n willChange.includes('filter');\n}\n\n/**\n * 查找影响 fixed 定位的父元素\n * 当父元素有 transform/filter/perspective/contain/will-change 等属性时,fixed 定位会相对于该父元素\n */\nexport function findFixedPositionParent(dom?: HTMLElement | null) {\n if (!dom) {\n return document.documentElement;\n }\n const fixedPositionParent = findParent(dom, (parent) => {\n return isPositioningContextCreator(parent, false);\n }, {excludeOwn: true}); // 没有找到,返回 window(通过 document.documentElement)\n return fixedPositionParent;\n}\n\n/**\n * 查找 absolute 定位的父元素\n * 查找最近的包含块创建者,包含所有可能影响absolute定位的属性\n */\nexport function findAbsolutePositionParent(dom?: HTMLElement | null) {\n if (!dom) {\n return document.body;\n }\n return findParent(dom, (parent) => {\n return isPositioningContextCreator(parent, true);\n }, {excludeOwn: true});\n}\n\n/**\n * 获取容器的缩放比例\n * 通过比较元素的实际尺寸和 getBoundingClientRect 返回的尺寸来计算缩放比例\n */\nexport function getScaleRatio(dom?: HTMLElement | null): { scaleX: number; scaleY: number } {\n if (!dom) {\n return { scaleX: 1, scaleY: 1 };\n }\n // 通过比较 offsetWidth 和 getBoundingClientRect().width 来获取缩放比例\n const rect = dom.getBoundingClientRect();\n let scaleX = 1;\n let scaleY = 1;\n // 扩大{magnification}倍进行计算, 相当于保留小数点后4位\n const magnification = 10000;\n scaleX = dom.offsetWidth > 0 ? Math.round(rect.width / dom.offsetWidth * magnification) / magnification : 1;\n scaleY = dom.offsetHeight > 0 ? Math.round(rect.height / dom.offsetHeight * magnification) / magnification : 1;\n // console.log('rect.width dom.offsetWidth', rect.width, dom.offsetWidth);\n // console.log('rect.height dom.offsetHeight', rect.height, dom.offsetHeight);\n // console.log('scaleX', scaleX, 'scaleY', scaleY);\n return { scaleX, scaleY };\n}\n\n/**\n * 限制数值在指定范围内\n * \n * @param value 要限制的数值\n * @param min 最小值\n * @param max 最大值\n * @returns 限制后的数值,确保在 [min, max] 范围内\n */\nexport function clamp(value: number, min: number, max: number) {\n return Math.min(Math.max(value, min), max);\n}\n\n\n/**\n * 检测当前环境是否支持触摸事件\n * \n * @returns 如果环境支持触摸事件返回 true,否则返回 false\n */\nexport function supportsTouchEvents() {\n return typeof window !== 'undefined' && ('ontouchstart' in window || navigator.maxTouchPoints > 0);\n};","\nexport const ValidPlacement = ['top-left', 'top-right', 'bottom-left', 'bottom-right'] as const;\n","import React from 'react';\nimport {\n prefixClassname as p,\n classNames as cx,\n} from \"@ohkit/prefix-classname\";\nimport {addEventListener, addClass} from '@ohkit/dom-helper';\nimport {findFixedPositionParent, findAbsolutePositionParent, getScaleRatio, clamp, supportsTouchEvents} from './utils';\nimport {ValidPlacement} from './constants';\nimport {DraggableBoxProps, DraggableBoxState} from './type';\n\nimport './style.scss';\n\nexport const c = p(\"ohkit-draggable-box__\");\nexport class DraggableBox extends React.Component<DraggableBoxProps, DraggableBoxState> {\n static defaultProps: Partial<DraggableBoxProps> = {\n zIndex: 9999,\n offsetX: 20,\n offsetY: 20,\n placement: 'bottom-right',\n disabled: false,\n lockAxis: 'none',\n showDragArea: false,\n showDragAreaOverMoveDistanse: 5,\n positionMode: 'fixed',\n };\n\n constructor(props: DraggableBoxProps) {\n super(props);\n \n const { placement = 'bottom-right', offsetY = 20, offsetX = 20 } = props;\n const [placementY, placementX] = placement.split('-') as ['top' | 'bottom', 'left' | 'right'];\n \n // 简化状态初始化\n this.state = {\n top: placementY === 'top' ? offsetY : undefined,\n bottom: placementY === 'bottom' ? offsetY : undefined,\n left: placementX === 'left' ? offsetX : undefined,\n right: placementX === 'right' ? offsetX : undefined,\n };\n }\n\n private prePositionMode: DraggableBoxProps['positionMode'];\n private preDraggerRef: HTMLElement | null = null;\n private container: HTMLElement | null = null;\n /**\n * 获取定位容器\n * 根据 positionMode 返回对应的定位父元素\n */\n private getContainer(useCache = true) {\n const { positionMode = 'fixed' } = this.props;\n if (!this.container || !useCache || this.prePositionMode !== positionMode || this.preDraggerRef !== this.draggerRef) {\n this.prePositionMode = positionMode;\n this.preDraggerRef = this.draggerRef;\n this.container = positionMode === 'fixed' \n ? findFixedPositionParent(this.draggerRef) \n : findAbsolutePositionParent(this.draggerRef);\n }\n return this.container;\n }\n\n /**\n * 获取容器的尺寸和位置信息\n */\n private getContainerRect() {\n const container = this.getContainer(false);\n if (!container) {\n return {\n width: window.innerWidth,\n height: window.innerHeight,\n left: 0,\n top: 0,\n scrollLeft: 0,\n scrollTop: 0,\n scrollerScrollLeft: 0,\n scrollerScrollTop: 0,\n borderLeftWidth: 0,\n borderTopWidth: 0\n };\n }\n const containerRect = container.getBoundingClientRect();\n \n // 获取容器的border宽度(仅 top, left 对坐标计算有影响)\n const containerStyle = window.getComputedStyle(container);\n const borderLeftWidth = parseFloat(containerStyle.borderLeftWidth) || 0;\n const borderTopWidth = parseFloat(containerStyle.borderTopWidth) || 0;\n const borderRightWidth = parseFloat(containerStyle.borderRightWidth) || 0;\n const borderBottomWidth = parseFloat(containerStyle.borderBottomWidth) || 0;\n const yScrollerWidth = container.offsetWidth - container.clientWidth - borderLeftWidth - borderRightWidth;\n const xScrollerHeight = container.offsetHeight - container.clientHeight - borderTopWidth - borderBottomWidth;\n // console.log('yScrollerWidth, xScrollerHeight', yScrollerWidth, xScrollerHeight);\n\n return {\n width: containerRect.width / this.cachedScaleX - borderLeftWidth - borderRightWidth - yScrollerWidth,\n height: containerRect.height / this.cachedScaleY - borderTopWidth - borderBottomWidth - xScrollerHeight,\n left: containerRect.left / this.cachedScaleX,\n top: containerRect.top / this.cachedScaleY,\n scrollLeft: container.scrollLeft,\n scrollTop: container.scrollTop,\n borderLeftWidth: borderLeftWidth,\n borderTopWidth: borderTopWidth,\n };\n }\n\n get dragBoxSize() {\n let width = 0;\n let height = 0;\n if (this.draggerRef) {\n width = this.draggerRef.offsetWidth;\n height = this.draggerRef.offsetHeight;\n }\n return {\n height,\n width\n };\n }\n\n get dragPositionBoundaries() {\n const { boundsX, boundsY, placement = 'bottom-right' } = this.props;\n const dragSize = this.dragBoxSize;\n const {width: containerWidth, height: containerHeight} = this.getContainerRect();\n const [placementY, placementX] = placement.split('-') as ['top' | 'bottom', 'left' | 'right'];\n \n const defaultBounds = {\n minX: 0,\n maxX: Math.max(containerWidth - dragSize.width, 0),\n minY: 0,\n maxY: Math.max(containerHeight- dragSize.height, 0),\n };\n // 初始化边界\n let {minX, maxX, minY, maxY} = defaultBounds\n\n // 处理X轴边界\n if (boundsX) {\n const [minBound, maxBound] = boundsX;\n if (placementX === 'left') {\n // 左边位置:boundsX=[左边最小距离, 左边最大距离]\n if (minBound !== undefined) minX = Math.max(minX, minBound);\n if (maxBound !== undefined) maxX = Math.min(maxX, maxBound);\n } else {\n // 右边位置:boundsX=[右边最小距离, 右边最大距离]\n // 直接使用边界值作为right的限制\n if (minBound !== undefined && maxBound !== undefined) {\n minX = Math.max(minX, containerWidth - maxBound - dragSize.width);\n maxX = Math.min(maxX, containerWidth - minBound - dragSize.width);\n } else if (minBound !== undefined) {\n // 只有minBound:设置最大边界,最小边界保持默认\n maxX = Math.min(maxX, containerWidth - minBound - dragSize.width);\n } else if (maxBound !== undefined) {\n // 只有maxBound:设置最小边界,最大边界保持默认\n minX = Math.max(minX, containerWidth - maxBound - dragSize.width);\n }\n }\n }\n\n // 处理Y轴边界\n if (boundsY) {\n const [minBound, maxBound] = boundsY;\n \n if (placementY === 'top') {\n // 顶部位置:boundsY=[顶边最小距离, 顶边最大距离]\n if (minBound !== undefined) minY = Math.max(minY, minBound);\n if (maxBound !== undefined) maxY = Math.min(maxY, maxBound);\n } else {\n // 底部位置:boundsY=[底边最小距离, 底边最大距离]\n // 直接使用边界值作为bottom的限制\n if (minBound !== undefined && maxBound !== undefined) {\n minY = Math.max(minY, containerHeight - maxBound - dragSize.height);\n maxY = Math.min(maxY, containerHeight - minBound - dragSize.height);\n } else if (minBound !== undefined) {\n // 只有minBound:设置最大边界,最小边界保持默认\n maxY = Math.min(maxY, containerHeight - minBound - dragSize.height);\n } else if (maxBound !== undefined) {\n // 只有maxBound:设置最小边界,最大边界保持默认\n minY = Math.max(minY, containerHeight - maxBound - dragSize.height);\n }\n }\n }\n // 确保各个边界值在默认范围内\n minX = clamp(minX, defaultBounds.minX, defaultBounds.maxX);\n maxX = clamp(maxX, minX, defaultBounds.maxX);\n minY = clamp(minY, defaultBounds.minY, defaultBounds.maxY);\n maxY = clamp(maxY, minY, defaultBounds.maxY);\n\n return { minX, maxX, minY, maxY };\n }\n\n get curPositionKey() {\n let {placement} = this.props;\n if (!placement || !ValidPlacement.includes(placement)) {\n placement = 'bottom-right';\n }\n return placement.split('-') as ['top' | 'bottom', 'left' | 'right']; // [y, x]\n }\n\n get position() {\n const [y, x] = this.curPositionKey;\n const positionStyles: Record<string, string> = {};\n \n // 确保位置值存在且是有效的数字\n if (this.state[y] !== undefined) {\n positionStyles[y] = `${this.state[y]}px`;\n }\n if (this.state[x] !== undefined) {\n positionStyles[x] = `${this.state[x]}px`;\n }\n \n return positionStyles;\n }\n\n draggerRef: HTMLDivElement | null = null;\n\n isDragging = false;\n\n axisX?: number;\n axisY?: number;\n dX = 0;\n dY = 0;\n startTop = 0;\n startLeft = 0;\n\n // 缓存缩放比例,避免在 dragging 中频繁计算\n cachedScaleX = 1;\n cachedScaleY = 1;\n\n __moveDisposer?: () => void;\n __clickDisposer?: () => void;\n __bodyClassDisposer?: () => void;\n __upDisposer?: () => void;\n __resizeDisposer?: () => void;\n __preventScrollDisposer?: () => void;\n\n dragAreaRef: HTMLDivElement | null = null;\n\n reportStartPosition() {\n if (this.draggerRef) {\n // 获取缩放比例\n const { scaleX, scaleY } = getScaleRatio(this.getContainer());\n this.cachedScaleX = scaleX;\n this.cachedScaleY = scaleY;\n const { top, left } = this.draggerRef.getBoundingClientRect();\n const containerRect = this.getContainerRect();\n // console.log(containerRect, 'containerRect');\n \n // 计算相对于容器的位置,并除以缩放比例得到未缩放的坐标\n this.startTop = top / scaleY - containerRect.top + containerRect.scrollTop - containerRect.borderTopWidth;\n this.startLeft = left / scaleY - containerRect.left + containerRect.scrollLeft - containerRect.borderLeftWidth;\n }\n }\n\n enableDrag = (isTouch = false) => {\n this.reportStartPosition();\n this.__moveDisposer?.();\n this.__moveDisposer = addEventListener(isTouch && this.draggerRef ? this.draggerRef : document, isTouch ? 'touchmove' : 'mousemove', (evt) => {\n evt.stopPropagation();\n if (isTouch) {\n evt.preventDefault();\n }\n // INFO: 移动过程中禁止click事件\n if (!this.__clickDisposer) {\n const moveDistanse = Math.sqrt(Math.pow(this.dX, 2) + Math.pow(this.dY, 2));\n // INFO: 移动超过px?? 确保用户有真实的移动意愿,而不是手抖~~\n if (moveDistanse > (this.props.showDragAreaOverMoveDistanse || 5)) {\n this.__clickDisposer = addEventListener(\n document,\n 'click',\n (evt) => {\n evt.stopPropagation();\n },\n true\n );\n this.__bodyClassDisposer = addClass([document.body, this.draggerRef], c('moving')) || undefined;\n \n // 显示拖拽区域\n if (this.props.showDragArea && this.dragAreaRef) {\n this.showDragArea();\n }\n }\n }\n this.dragging(evt as TouchEvent | MouseEvent);\n }, {\n passive: !isTouch\n });\n\n this.__upDisposer?.();\n this.__upDisposer = addEventListener(\n document,\n 'mouseup',\n () => {\n this.endDrag();\n },\n true\n );\n };\n\n startDrag = (evt: React.MouseEvent<HTMLDivElement>) => {\n // 判断鼠标非右击才继续执行\n if (evt.nativeEvent.button === 2) {\n return;\n }\n this.axisX = evt.nativeEvent.pageX;\n this.axisY = evt.nativeEvent.pageY;\n if (!this.props.disabled) {\n this.enableDrag();\n }\n };\n\n dragging = (evt: MouseEvent | TouchEvent) => {\n this.isDragging = true;\n const { lockAxis } = this.props;\n const { minX, maxX, minY, maxY } = this.dragPositionBoundaries;\n \n // 使用缓存的缩放比例,避免频繁计算\n const scaleX = this.cachedScaleX;\n const scaleY = this.cachedScaleY;\n \n // 获取坐标\n let pageX: number, pageY: number;\n if (evt instanceof TouchEvent) {\n const touch = evt.touches[0];\n if (!touch) return;\n pageX = touch.pageX;\n pageY = touch.pageY;\n } else {\n pageX = evt.pageX;\n pageY = evt.pageY;\n }\n \n // 计算原始偏移量(需要除以缩放比例)\n this.dX = (pageX - (this.axisX || 0)) / scaleX;\n this.dY = (pageY - (this.axisY || 0)) / scaleY;\n \n // 应用方向锁定并计算变换值\n let translateX = this.dX;\n let translateY = this.dY;\n \n if (lockAxis === 'x') {\n translateY = 0; // 锁定Y方向\n } else if (lockAxis === 'y') {\n translateX = 0; // 锁定X方向\n }\n \n // 应用边界条件到允许移动的方向\n const potentialLeft = this.startLeft + translateX;\n const potentialTop = this.startTop + translateY;\n \n // X轴边界条件(在允许X轴移动时应用)\n if (lockAxis !== 'y') {\n if (potentialLeft < minX) {\n translateX = minX - this.startLeft;\n } else if (potentialLeft > maxX) {\n translateX = maxX - this.startLeft;\n }\n }\n \n // Y轴边界条件(在允许Y轴移动时应用)\n if (lockAxis !== 'x') {\n if (potentialTop < minY) {\n translateY = minY - this.startTop;\n } else if (potentialTop > maxY) {\n translateY = maxY - this.startTop;\n }\n }\n \n if (this.draggerRef) {\n this.draggerRef.style.transform = `translate(${translateX}px, ${translateY}px)`;\n }\n };\n\n startTouchDrag = (evt: React.TouchEvent<HTMLDivElement>) => {\n const touch = evt.touches[0];\n if (!touch) return;\n this.axisX = touch.pageX;\n this.axisY = touch.pageY;\n if (!this.props.disabled) {\n this.enableDrag(true);\n }\n };\n\n endDrag = () => {\n if (this.isDragging) {\n this.calcPosition();\n if (this.draggerRef) {\n this.draggerRef.style.transform = '';\n }\n \n // 隐藏拖拽区域\n if (this.props.showDragArea) {\n this.hideDragArea();\n }\n }\n\n if (this.__moveDisposer) {\n this.__moveDisposer();\n this.__moveDisposer = undefined;\n }\n if (this.__clickDisposer) {\n requestAnimationFrame(() => {\n if (this.__clickDisposer) {\n this.__clickDisposer();\n this.__clickDisposer = undefined;\n }\n });\n }\n if (this.__upDisposer) {\n this.__upDisposer();\n this.__upDisposer = undefined;\n }\n if (this.__bodyClassDisposer) {\n this.__bodyClassDisposer();\n this.__bodyClassDisposer = undefined;\n }\n\n this.isDragging = false;\n };\n\n showDragArea = () => {\n if (!this.props.showDragArea || !this.dragAreaRef) return;\n \n const { lockAxis } = this.props;\n const { minX, maxX, minY, maxY } = this.dragPositionBoundaries;\n const dragSize = this.dragBoxSize;\n \n // 重置样式\n this.dragAreaRef.style.border = '1px dashed var(--ohkit-color-primary, #1890ff)';\n this.dragAreaRef.style.backgroundColor = 'rgba(173, 216, 230, 0.2)'; // 淡透蓝色\n \n if (lockAxis === 'x') {\n // 锁定Y方向,显示为水平虚线区域\n this.dragAreaRef.style.width = `${maxX - minX + dragSize.width}px`;\n this.dragAreaRef.style.height = '2px'; // 更细的虚线高度\n this.dragAreaRef.style.left = `${minX}px`;\n this.dragAreaRef.style.top = `${this.startTop + dragSize.height / 2}px`;\n } else if (lockAxis === 'y') {\n // 锁定X方向,显示为垂直虚线区域\n this.dragAreaRef.style.width = '2px'; // 更细的虚线宽度\n this.dragAreaRef.style.height = `${maxY - minY + dragSize.height}px`;\n this.dragAreaRef.style.left = `${this.startLeft + dragSize.width / 2}px`;\n this.dragAreaRef.style.top = `${minY}px`;\n } else {\n // 自由拖拽,显示完整区域\n this.dragAreaRef.style.width = `${maxX - minX + dragSize.width}px`;\n this.dragAreaRef.style.height = `${maxY - minY + dragSize.height}px`;\n this.dragAreaRef.style.left = `${minX}px`;\n this.dragAreaRef.style.top = `${minY}px`;\n }\n \n this.dragAreaRef.style.display = 'block';\n };\n\n hideDragArea = () => {\n if (this.dragAreaRef) {\n this.dragAreaRef.style.display = 'none';\n }\n };\n calcPosition = () => {\n const { lockAxis } = this.props;\n const { minX, maxX, minY, maxY } = this.dragPositionBoundaries;\n const {height, width} = this.getContainerRect();\n \n // 计算新的位置\n let newTop = this.startTop;\n let newLeft = this.startLeft;\n \n if (lockAxis !== 'y') {\n newLeft += this.dX;\n }\n if (lockAxis !== 'x') {\n newTop += this.dY;\n }\n \n // 应用边界限制\n const realTop = clamp(newTop, minY, maxY);\n const realLeft = clamp(newLeft, minX, maxX);\n const realBottom = height - realTop - this.dragBoxSize.height;\n const realRight = width - realLeft - this.dragBoxSize.width;\n if (realTop !== this.state.top || realLeft !== this.state.left || this.state.bottom !== realBottom || this.state.right !== realRight) {\n // console.log(minY, maxY, this.startTop, this.dY, newTop, realTop, 'minY, maxY, this.startTop, this.dY, newTop, realTop --- calcPosition y');\n // console.log(minX, maxX, this.startLeft, this.dX, newLeft, realLeft, 'minX, maxX, this.startLeft, this.dX, newLeft, realLeft ---calcPosition x');\n this.setState({\n top: realTop,\n left: realLeft,\n bottom: realBottom,\n right: realRight\n });\n }\n this.startTop = realTop;\n this.startLeft = realLeft;\n this.dX = this.dY = 0;\n };\n\n\n componentDidMount() {\n // 检查初始位置是否在边界范围内,如果不在则修正\n this.reportStartPosition();\n this.calcPosition();\n \n this.__resizeDisposer = addEventListener(window, 'resize', () => {\n this.calcPosition();\n });\n\n // 触屏设备时,阻止拖拽时滚动页面\n if (supportsTouchEvents() && this.draggerRef) {\n this.__preventScrollDisposer = addEventListener(this.draggerRef, 'touchmove', (evt) => {\n evt.preventDefault();\n });\n }\n }\n\n componentWillUnmount() {\n this.__resizeDisposer?.();\n this.__bodyClassDisposer?.();\n this.__moveDisposer?.();\n this.__clickDisposer?.();\n this.__upDisposer?.();\n this.__preventScrollDisposer?.();\n }\n\n render() {\n const { className, zIndex, children, showDragArea, positionMode = 'fixed' } = this.props;\n const { startDrag, startTouchDrag, endDrag } = this;\n const stl = {\n zIndex,\n ...this.position,\n position: positionMode\n };\n return (\n <>\n {showDragArea && (\n <div\n className={c('drag-area')}\n ref={(r) => {\n this.dragAreaRef = r;\n }}\n style={{\n display: 'none',\n position: positionMode,\n backgroundColor: 'rgba(173, 216, 230, 0.2)', // 淡透蓝色\n border: '1px dashed var(--ohkit-color-primary, #1890ff)',\n pointerEvents: 'none',\n zIndex: (zIndex || 9999) - 1,\n boxSizing: 'border-box',\n borderRadius: this.props.lockAxis !== 'none' ? '2px' : '0',\n }}\n />\n )}\n <div\n className={cx(c('container'), className)}\n style={stl}\n ref={(r) => {\n this.draggerRef = r;\n }}\n onMouseDownCapture={startDrag}\n onMouseUpCapture={endDrag}\n onTouchStartCapture={startTouchDrag}\n onTouchEndCapture={endDrag}\n >\n {children}\n </div>\n </>\n );\n }\n}\n\nexport default DraggableBox;"],"names":["isPositioningContextCreator","element","includePosition","style","window","getComputedStyle","position","getPropertyValue","transform","filter","perspective","contain","willChange","includes","clamp","value","min","max","Math","ValidPlacement","c","p","prefixClassname","DraggableBox","_React$Component","props","_this","call","this","prePositionMode","preDraggerRef","container","draggerRef","isDragging","axisX","axisY","dX","dY","startTop","startLeft","cachedScaleX","cachedScaleY","__moveDisposer","__clickDisposer","__bodyClassDisposer","__upDisposer","__resizeDisposer","__preventScrollDisposer","dragAreaRef","enableDrag","isTouch","reportStartPosition","addEventListener","document","evt","stopPropagation","preventDefault","sqrt","pow","showDragAreaOverMoveDistanse","addClass","body","undefined","showDragArea","dragging","passive","endDrag","startDrag","nativeEvent","button","pageX","pageY","disabled","lockAxis","_this$dragPositionBou","dragPositionBoundaries","minX","maxX","minY","maxY","scaleY","TouchEvent","touch","touches","translateX","translateY","potentialLeft","potentialTop","startTouchDrag","calcPosition","hideDragArea","requestAnimationFrame","_this$dragPositionBou2","dragSize","dragBoxSize","border","backgroundColor","width","height","left","top","display","_this$dragPositionBou3","_this$getContainerRec","getContainerRect","newTop","newLeft","realTop","realLeft","realBottom","realRight","state","bottom","right","setState","_props$placement","placement","_props$offsetY","offsetY","_props$offsetX","offsetX","_placement$split","split","placementY","placementX","_proto","prototype","getContainer","useCache","dom","_this$props$positionM","positionMode","findParent","parent","excludeOwn","documentElement","findAbsolutePositionParent","innerWidth","innerHeight","scrollLeft","scrollTop","scrollerScrollLeft","scrollerScrollTop","borderLeftWidth","borderTopWidth","containerRect","getBoundingClientRect","containerStyle","parseFloat","borderRightWidth","borderBottomWidth","offsetWidth","clientWidth","offsetHeight","clientHeight","_getScaleRatio","scaleX","rect","magnification","round","getScaleRatio","_this$draggerRef$getB","componentDidMount","_this2","navigator","maxTouchPoints","componentWillUnmount","_this$__resizeDispose","_this$__bodyClassDisp","_this$__moveDisposer","_this$__clickDisposer","_this$__upDisposer","_this$__preventScroll","render","_this3","_this$props","className","zIndex","children","_this$props$positionM2","stl","_extends","React","createElement","Fragment","ref","r","pointerEvents","boxSizing","borderRadius","cx","onMouseDownCapture","onMouseUpCapture","onTouchStartCapture","onTouchEndCapture","key","get","_this$props2","boundsX","boundsY","_this$props2$placemen","_this$getContainerRec2","containerWidth","containerHeight","_placement$split2","defaultBounds","minBound","maxBound","_this$curPositionKey","curPositionKey","y","x","positionStyles","Component","defaultProps"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/utils.ts","../src/constants.ts","../src/index.tsx"],"sourcesContent":["import {findParent} from '@ohkit/dom-helper';\n\n/**\n * 检查元素是否创建了新的定位上下文(包含块)\n * @param element 要检查的元素\n * @param includePosition 是否检查position属性(absolute/relative/fixed)\n */\nexport function isPositioningContextCreator(element: HTMLElement, includePosition: boolean): boolean {\n const style = window.getComputedStyle(element);\n const position = style.getPropertyValue('position');\n const transform = style.getPropertyValue('transform');\n const filter = style.getPropertyValue('filter');\n const perspective = style.getPropertyValue('perspective');\n const contain = style.getPropertyValue('contain');\n const willChange = style.getPropertyValue('will-change');\n \n return (includePosition && position !== 'static') || \n transform !== 'none' || \n filter !== 'none' || \n perspective !== 'none' ||\n contain.includes('paint') ||\n contain.includes('layout') ||\n contain.includes('strict') ||\n willChange.includes('transform') ||\n willChange.includes('perspective') ||\n willChange.includes('filter');\n}\n\n/**\n * 查找影响 fixed 定位的父元素\n * 当父元素有 transform/filter/perspective/contain/will-change 等属性时,fixed 定位会相对于该父元素\n */\nexport function findFixedPositionParent(dom?: HTMLElement | null) {\n if (!dom) {\n return document.documentElement;\n }\n const fixedPositionParent = findParent(dom, (parent) => {\n return isPositioningContextCreator(parent, false);\n }, {excludeOwn: true}); // 没有找到,返回 window(通过 document.documentElement)\n return fixedPositionParent;\n}\n\n/**\n * 查找 absolute 定位的父元素\n * 查找最近的包含块创建者,包含所有可能影响absolute定位的属性\n */\nexport function findAbsolutePositionParent(dom?: HTMLElement | null) {\n if (!dom) {\n return document.body;\n }\n return findParent(dom, (parent) => {\n return isPositioningContextCreator(parent, true);\n }, {excludeOwn: true});\n}\n\n/**\n * 获取容器的缩放比例\n * 通过比较元素的实际尺寸和 getBoundingClientRect 返回的尺寸来计算缩放比例\n */\nexport function getScaleRatio(dom?: HTMLElement | null): { scaleX: number; scaleY: number } {\n if (!dom) {\n return { scaleX: 1, scaleY: 1 };\n }\n // 通过比较 offsetWidth 和 getBoundingClientRect().width 来获取缩放比例\n const rect = dom.getBoundingClientRect();\n let scaleX = 1;\n let scaleY = 1;\n // 扩大{magnification}倍进行计算, 相当于保留小数点后4位\n const magnification = 10000;\n scaleX = dom.offsetWidth > 0 ? Math.round(rect.width / dom.offsetWidth * magnification) / magnification : 1;\n scaleY = dom.offsetHeight > 0 ? Math.round(rect.height / dom.offsetHeight * magnification) / magnification : 1;\n // console.log('rect.width dom.offsetWidth', rect.width, dom.offsetWidth);\n // console.log('rect.height dom.offsetHeight', rect.height, dom.offsetHeight);\n // console.log('scaleX', scaleX, 'scaleY', scaleY);\n return { scaleX, scaleY };\n}\n\n/**\n * 限制数值在指定范围内\n * \n * @param value 要限制的数值\n * @param min 最小值\n * @param max 最大值\n * @returns 限制后的数值,确保在 [min, max] 范围内\n */\nexport function clamp(value: number, min: number, max: number) {\n return Math.min(Math.max(value, min), max);\n}\n\n\n/**\n * 检测当前环境是否支持触摸事件\n * \n * @returns 如果环境支持触摸事件返回 true,否则返回 false\n */\nexport function supportsTouchEvents() {\n return typeof window !== 'undefined' && ('ontouchstart' in window || navigator.maxTouchPoints > 0);\n};","\nexport const ValidPlacement = ['top-left', 'top-right', 'bottom-left', 'bottom-right'] as const;\n","import React from 'react';\nimport {\n prefixClassname as p,\n classNames as cx,\n} from \"@ohkit/prefix-classname\";\nimport {addEventListener, addClass} from '@ohkit/dom-helper';\nimport {findFixedPositionParent, findAbsolutePositionParent, getScaleRatio, clamp, supportsTouchEvents} from './utils';\nimport {ValidPlacement} from './constants';\nimport {DraggableBoxProps, DraggableBoxState} from './type';\n\nimport './style.scss';\n\nexport * from './utils';\nexport * from './type';\nexport const c = p(\"ohkit-draggable-box__\");\nexport class DraggableBox extends React.Component<DraggableBoxProps, DraggableBoxState> {\n static defaultProps: Partial<DraggableBoxProps> = {\n zIndex: 9999,\n offsetX: 20,\n offsetY: 20,\n placement: 'bottom-right',\n disabled: false,\n lockAxis: 'none',\n showDragArea: false,\n showDragAreaOverMoveDistanse: 5,\n positionMode: 'fixed',\n };\n\n constructor(props: DraggableBoxProps) {\n super(props);\n const { offsetX, offsetY } = this.props;\n this.state = this.formatState({offsetX, offsetY});\n }\n\n private formatState({offsetX = DraggableBox.defaultProps.offsetX, offsetY = DraggableBox.defaultProps.offsetY} = {}) {\n const { placement = 'bottom-right' } = this.props;\n const [placementY, placementX] = placement.split('-') as ['top' | 'bottom', 'left' | 'right'];\n const newState = {\n top: placementY === 'top' ? offsetY : undefined,\n bottom: placementY === 'bottom' ? offsetY : undefined,\n left: placementX === 'left' ? offsetX : undefined,\n right: placementX === 'right' ? offsetX : undefined,\n }\n return newState;\n }\n\n private prePositionMode: DraggableBoxProps['positionMode'];\n private preDraggerRef: HTMLElement | null = null;\n private container: HTMLElement | null = null;\n /**\n * 获取定位容器\n * 根据 positionMode 返回对应的定位父元素\n */\n private getContainer(useCache = true) {\n const { positionMode = 'fixed' } = this.props;\n if (!this.container || !useCache || this.prePositionMode !== positionMode || this.preDraggerRef !== this.draggerRef) {\n this.prePositionMode = positionMode;\n this.preDraggerRef = this.draggerRef;\n this.container = positionMode === 'fixed' \n ? findFixedPositionParent(this.draggerRef) \n : findAbsolutePositionParent(this.draggerRef);\n }\n return this.container;\n }\n\n /**\n * 获取容器的尺寸和位置信息\n */\n private getContainerRect() {\n const container = this.getContainer(false);\n if (!container) {\n return {\n width: document.documentElement.clientWidth, // window.innerWidth, 避免滚动条影响计算\n height: document.documentElement.clientHeight, // window.innerHeight, 避免滚动条影响计算\n left: 0,\n top: 0,\n scrollLeft: 0,\n scrollTop: 0,\n scrollerScrollLeft: 0,\n scrollerScrollTop: 0,\n borderLeftWidth: 0,\n borderTopWidth: 0\n };\n }\n const containerRect = container.getBoundingClientRect();\n \n // 获取容器的border宽度(仅 top, left 对坐标计算有影响)\n const containerStyle = window.getComputedStyle(container);\n const borderLeftWidth = parseFloat(containerStyle.borderLeftWidth) || 0;\n const borderTopWidth = parseFloat(containerStyle.borderTopWidth) || 0;\n const borderRightWidth = parseFloat(containerStyle.borderRightWidth) || 0;\n const borderBottomWidth = parseFloat(containerStyle.borderBottomWidth) || 0;\n const yScrollerWidth = container.offsetWidth - container.clientWidth - borderLeftWidth - borderRightWidth;\n const xScrollerHeight = container.offsetHeight - container.clientHeight - borderTopWidth - borderBottomWidth;\n // console.log('yScrollerWidth, xScrollerHeight', yScrollerWidth, xScrollerHeight);\n\n return {\n width: containerRect.width / this.cachedScaleX - borderLeftWidth - borderRightWidth - yScrollerWidth,\n height: containerRect.height / this.cachedScaleY - borderTopWidth - borderBottomWidth - xScrollerHeight,\n left: containerRect.left / this.cachedScaleX,\n top: containerRect.top / this.cachedScaleY,\n scrollLeft: container.scrollLeft,\n scrollTop: container.scrollTop,\n borderLeftWidth: borderLeftWidth,\n borderTopWidth: borderTopWidth,\n };\n }\n\n get dragBoxSize() {\n let width = 0;\n let height = 0;\n if (this.draggerRef) {\n width = this.draggerRef.offsetWidth;\n height = this.draggerRef.offsetHeight;\n }\n return {\n height,\n width\n };\n }\n\n get dragPositionBoundaries() {\n const { boundsX, boundsY, placement = 'bottom-right' } = this.props;\n const dragSize = this.dragBoxSize;\n const {width: containerWidth, height: containerHeight} = this.getContainerRect();\n const [placementY, placementX] = placement.split('-') as ['top' | 'bottom', 'left' | 'right'];\n \n const defaultBounds = {\n minX: 0,\n maxX: Math.max(containerWidth - dragSize.width, 0),\n minY: 0,\n maxY: Math.max(containerHeight- dragSize.height, 0),\n };\n // 初始化边界\n let {minX, maxX, minY, maxY} = defaultBounds\n\n // 处理X轴边界\n if (boundsX) {\n const [minBound, maxBound] = boundsX;\n if (placementX === 'left') {\n // 左边位置:boundsX=[左边最小距离, 左边最大距离]\n if (minBound !== undefined) minX = Math.max(minX, minBound);\n if (maxBound !== undefined) maxX = Math.min(maxX, maxBound);\n } else {\n // 右边位置:boundsX=[右边最小距离, 右边最大距离]\n // 直接使用边界值作为right的限制\n if (minBound !== undefined && maxBound !== undefined) {\n minX = Math.max(minX, containerWidth - maxBound - dragSize.width);\n maxX = Math.min(maxX, containerWidth - minBound - dragSize.width);\n } else if (minBound !== undefined) {\n // 只有minBound:设置最大边界,最小边界保持默认\n maxX = Math.min(maxX, containerWidth - minBound - dragSize.width);\n } else if (maxBound !== undefined) {\n // 只有maxBound:设置最小边界,最大边界保持默认\n minX = Math.max(minX, containerWidth - maxBound - dragSize.width);\n }\n }\n }\n\n // 处理Y轴边界\n if (boundsY) {\n const [minBound, maxBound] = boundsY;\n \n if (placementY === 'top') {\n // 顶部位置:boundsY=[顶边最小距离, 顶边最大距离]\n if (minBound !== undefined) minY = Math.max(minY, minBound);\n if (maxBound !== undefined) maxY = Math.min(maxY, maxBound);\n } else {\n // 底部位置:boundsY=[底边最小距离, 底边最大距离]\n // 直接使用边界值作为bottom的限制\n if (minBound !== undefined && maxBound !== undefined) {\n minY = Math.max(minY, containerHeight - maxBound - dragSize.height);\n maxY = Math.min(maxY, containerHeight - minBound - dragSize.height);\n } else if (minBound !== undefined) {\n // 只有minBound:设置最大边界,最小边界保持默认\n maxY = Math.min(maxY, containerHeight - minBound - dragSize.height);\n } else if (maxBound !== undefined) {\n // 只有maxBound:设置最小边界,最大边界保持默认\n minY = Math.max(minY, containerHeight - maxBound - dragSize.height);\n }\n }\n }\n // 确保各个边界值在默认范围内\n minX = clamp(minX, defaultBounds.minX, defaultBounds.maxX);\n maxX = clamp(maxX, minX, defaultBounds.maxX);\n minY = clamp(minY, defaultBounds.minY, defaultBounds.maxY);\n maxY = clamp(maxY, minY, defaultBounds.maxY);\n\n return { minX, maxX, minY, maxY };\n }\n\n get curPositionKey() {\n let {placement} = this.props;\n if (!placement || !ValidPlacement.includes(placement)) {\n placement = 'bottom-right';\n }\n return placement.split('-') as ['top' | 'bottom', 'left' | 'right']; // [y, x]\n }\n\n get position() {\n const [y, x] = this.curPositionKey;\n const positionStyles: Record<string, string> = {};\n \n // 确保位置值存在且是有效的数字\n if (this.state[y] !== undefined) {\n positionStyles[y] = `${this.state[y]}px`;\n }\n if (this.state[x] !== undefined) {\n positionStyles[x] = `${this.state[x]}px`;\n }\n \n return positionStyles;\n }\n\n draggerRef: HTMLDivElement | null = null;\n\n isDragging = false;\n\n axisX?: number;\n axisY?: number;\n dX = 0;\n dY = 0;\n startTop = 0;\n startLeft = 0;\n startBottom = 0;\n startRight = 0;\n translateX = 0;\n translateY = 0;\n\n // 缓存缩放比例,避免在 dragging 中频繁计算\n cachedScaleX = 1;\n cachedScaleY = 1;\n\n private __moveDisposer?: () => void;\n private __clickDisposer?: () => void;\n private __bodyClassDisposer?: () => void;\n private __upDisposer?: () => void;\n private __resizeDisposer?: () => void;\n private __preventScrollDisposer?: () => void;\n\n dragAreaRef: HTMLDivElement | null = null;\n\n private reportStartPosition() {\n if (this.draggerRef) {\n // 获取缩放比例\n const { scaleX, scaleY } = getScaleRatio(this.getContainer());\n this.cachedScaleX = scaleX;\n this.cachedScaleY = scaleY;\n const { top, left } = this.draggerRef.getBoundingClientRect();\n const containerRect = this.getContainerRect();\n // console.log(containerRect, 'containerRect');\n \n // 计算相对于容器的位置,并除以缩放比例得到未缩放的坐标\n this.startTop = top / scaleY - containerRect.top + containerRect.scrollTop - containerRect.borderTopWidth;\n this.startLeft = left / scaleY - containerRect.left + containerRect.scrollLeft - containerRect.borderLeftWidth;\n this.startBottom = containerRect.height - this.startTop - this.dragBoxSize.height;\n this.startRight = containerRect.width - this.startLeft - this.dragBoxSize.width;\n }\n }\n\n dragingClassMap: Record<NonNullable<DraggableBoxProps['lockAxis']>, string> = {\n 'none': 'moving',\n 'x': 'moving-x',\n 'y': 'moving-y'\n }\n\n enableDrag = (isTouch = false) => {\n this.reportStartPosition();\n this.__moveDisposer?.();\n this.__moveDisposer = addEventListener(isTouch && this.draggerRef ? this.draggerRef : document, isTouch ? 'touchmove' : 'mousemove', (evt) => {\n evt.stopPropagation();\n if (isTouch) {\n evt.preventDefault();\n }\n // INFO: 移动过程中禁止click事件\n if (!this.__clickDisposer) {\n const moveDistanse = Math.sqrt(Math.pow(this.dX, 2) + Math.pow(this.dY, 2));\n // INFO: 移动超过px?? 确保用户有真实的移动意愿,而不是手抖~~\n if (moveDistanse > (this.props.showDragAreaOverMoveDistanse || 5)) {\n this.__clickDisposer = addEventListener(\n document,\n 'click',\n (evt) => {\n evt.stopPropagation();\n },\n true\n );\n this.__bodyClassDisposer = addClass([document.documentElement, this.draggerRef], c(this.dragingClassMap[this.props.lockAxis || 'none'])) || undefined;\n \n // 显示拖拽区域\n if (this.props.showDragArea && this.dragAreaRef) {\n this.showDragArea();\n }\n }\n }\n // 调用拖拽开始回调\n if (!this.isDragging && this.props.onDragStart) {\n const positionChange = {\n top: this.startTop,\n left: this.startLeft,\n bottom: this.startBottom,\n right: this.startRight,\n diffX: 0,\n diffY: 0\n };\n this.props.onDragStart(positionChange);\n }\n this.dragging(evt as TouchEvent | MouseEvent);\n }, {\n passive: !isTouch\n });\n\n this.__upDisposer?.();\n this.__upDisposer = addEventListener(\n document,\n 'mouseup',\n () => {\n this.endDrag();\n },\n true\n );\n };\n\n startDrag = (evt: React.MouseEvent<HTMLDivElement>) => {\n // 判断鼠标非右击才继续执行\n if (evt.nativeEvent.button === 2) {\n return;\n }\n this.axisX = evt.nativeEvent.pageX;\n this.axisY = evt.nativeEvent.pageY;\n if (!this.props.disabled) {\n this.enableDrag();\n }\n };\n\n dragging = (evt: MouseEvent | TouchEvent) => {\n this.isDragging = true;\n const { lockAxis } = this.props;\n const { minX, maxX, minY, maxY } = this.dragPositionBoundaries;\n \n // 使用缓存的缩放比例,避免频繁计算\n const scaleX = this.cachedScaleX;\n const scaleY = this.cachedScaleY;\n \n // 获取坐标\n let pageX: number, pageY: number;\n if (evt instanceof TouchEvent) {\n const touch = evt.touches[0];\n if (!touch) return;\n pageX = touch.pageX;\n pageY = touch.pageY;\n } else {\n pageX = evt.pageX;\n pageY = evt.pageY;\n }\n \n // 计算原始偏移量(需要除以缩放比例)\n this.dX = (pageX - (this.axisX || 0)) / scaleX;\n this.dY = (pageY - (this.axisY || 0)) / scaleY;\n \n // 应用方向锁定并计算变换值\n let translateX = this.dX;\n let translateY = this.dY;\n \n if (lockAxis === 'x') {\n translateY = 0; // 锁定Y方向\n } else if (lockAxis === 'y') {\n translateX = 0; // 锁定X方向\n }\n \n // 应用边界条件到允许移动的方向\n const potentialLeft = this.startLeft + translateX;\n const potentialTop = this.startTop + translateY;\n \n // X轴边界条件(在允许X轴移动时应用)\n if (lockAxis !== 'y') {\n if (potentialLeft < minX) {\n translateX = minX - this.startLeft;\n } else if (potentialLeft > maxX) {\n translateX = maxX - this.startLeft;\n }\n }\n \n // Y轴边界条件(在允许Y轴移动时应用)\n if (lockAxis !== 'x') {\n if (potentialTop < minY) {\n translateY = minY - this.startTop;\n } else if (potentialTop > maxY) {\n translateY = maxY - this.startTop;\n }\n }\n if (this.translateX === translateX && this.translateY === translateY) {\n return;\n }\n\n // 调用拖拽中回调\n if (this.props.onDrag) {\n const positionChange = {\n top: this.startTop + translateY,\n left: this.startLeft + translateX,\n bottom: this.startBottom - translateY,\n right: this.startRight - translateX,\n diffX: translateX,\n diffY: translateY\n };\n this.props.onDrag(positionChange);\n }\n \n if (this.draggerRef) {\n this.draggerRef.style.transform = `translate(${translateX}px, ${translateY}px)`;\n }\n this.translateX = translateX;\n this.translateY = translateY;\n };\n\n startTouchDrag = (evt: React.TouchEvent<HTMLDivElement>) => {\n const touch = evt.touches[0];\n if (!touch) return;\n this.axisX = touch.pageX;\n this.axisY = touch.pageY;\n if (!this.props.disabled) {\n this.enableDrag(true);\n }\n };\n\n endDrag = () => {\n if (this.isDragging) {\n const positionChange = this.calcPosition();\n // 调用拖拽结束回调\n this.props.onDragEnd?.(positionChange);\n if (this.draggerRef) {\n this.draggerRef.style.transform = '';\n }\n \n // 隐藏拖拽区域\n if (this.props.showDragArea) {\n this.hideDragArea();\n }\n }\n\n if (this.__moveDisposer) {\n this.__moveDisposer();\n this.__moveDisposer = undefined;\n }\n if (this.__clickDisposer) {\n requestAnimationFrame(() => {\n if (this.__clickDisposer) {\n this.__clickDisposer();\n this.__clickDisposer = undefined;\n }\n });\n }\n if (this.__upDisposer) {\n this.__upDisposer();\n this.__upDisposer = undefined;\n }\n if (this.__bodyClassDisposer) {\n this.__bodyClassDisposer();\n this.__bodyClassDisposer = undefined;\n }\n\n this.isDragging = false;\n };\n\n showDragArea = () => {\n if (!this.props.showDragArea || !this.dragAreaRef) return;\n \n const { lockAxis } = this.props;\n const { minX, maxX, minY, maxY } = this.dragPositionBoundaries;\n const dragSize = this.dragBoxSize;\n \n // 重置样式\n this.dragAreaRef.style.border = '1px dashed var(--ohkit-color-primary, #1890ff)';\n this.dragAreaRef.style.backgroundColor = 'rgba(173, 216, 230, 0.2)'; // 淡透蓝色\n \n if (lockAxis === 'x') {\n // 锁定Y方向,显示为水平虚线区域\n this.dragAreaRef.style.width = `${maxX - minX + dragSize.width}px`;\n this.dragAreaRef.style.height = '2px'; // 更细的虚线高度\n this.dragAreaRef.style.left = `${minX}px`;\n this.dragAreaRef.style.top = `${this.startTop + dragSize.height / 2}px`;\n } else if (lockAxis === 'y') {\n // 锁定X方向,显示为垂直虚线区域\n this.dragAreaRef.style.width = '2px'; // 更细的虚线宽度\n this.dragAreaRef.style.height = `${maxY - minY + dragSize.height}px`;\n this.dragAreaRef.style.left = `${this.startLeft + dragSize.width / 2}px`;\n this.dragAreaRef.style.top = `${minY}px`;\n } else {\n // 自由拖拽,显示完整区域\n this.dragAreaRef.style.width = `${maxX - minX + dragSize.width}px`;\n this.dragAreaRef.style.height = `${maxY - minY + dragSize.height}px`;\n this.dragAreaRef.style.left = `${minX}px`;\n this.dragAreaRef.style.top = `${minY}px`;\n }\n \n this.dragAreaRef.style.display = 'block';\n };\n\n hideDragArea = () => {\n if (this.dragAreaRef) {\n this.dragAreaRef.style.display = 'none';\n }\n };\n calcPosition = () => {\n const { lockAxis } = this.props;\n const { minX, maxX, minY, maxY } = this.dragPositionBoundaries;\n const {height, width} = this.getContainerRect();\n \n // 计算新的位置\n let newTop = this.startTop;\n let newLeft = this.startLeft;\n \n if (lockAxis !== 'y') {\n newLeft += this.dX;\n }\n if (lockAxis !== 'x') {\n newTop += this.dY;\n }\n \n // 应用边界限制\n const realTop = clamp(newTop, minY, maxY);\n const realLeft = clamp(newLeft, minX, maxX);\n const realBottom = height - realTop - this.dragBoxSize.height;\n const realRight = width - realLeft - this.dragBoxSize.width;\n if (realTop !== this.state.top || realLeft !== this.state.left || this.state.bottom !== realBottom || this.state.right !== realRight) {\n this.setState({\n top: realTop,\n left: realLeft,\n bottom: realBottom,\n right: realRight\n });\n }\n const positionChange = {\n top: realTop,\n left: realLeft,\n bottom: realBottom,\n right: realRight,\n diffX: realLeft - this.startLeft,\n diffY: realTop - this.startTop\n };\n this.startTop = realTop;\n this.startLeft = realLeft;\n this.startBottom = realBottom;\n this.startRight = realRight;\n this.dX = this.dY = 0;\n return positionChange;\n };\n\n // 更新状态并计算位置 (外部可以调用)\n updateState = ({offsetX, offsetY}: Pick<DraggableBoxProps, 'offsetX' | 'offsetY'> = {}) => {\n this.setState(this.formatState({offsetX, offsetY}), () => {\n this.reportStartPosition();\n this.calcPosition();\n });\n }\n\n componentDidMount() {\n // 检查初始位置是否在边界范围内,如果不在则修正\n this.reportStartPosition();\n this.calcPosition();\n \n this.__resizeDisposer = addEventListener(window, 'resize', () => {\n this.calcPosition();\n });\n\n // 触屏设备时,阻止拖拽时滚动页面\n if (supportsTouchEvents() && this.draggerRef) {\n this.__preventScrollDisposer = addEventListener(this.draggerRef, 'touchmove', (evt) => {\n evt.preventDefault();\n });\n }\n }\n\n componentWillUnmount() {\n this.__resizeDisposer?.();\n this.__bodyClassDisposer?.();\n this.__moveDisposer?.();\n this.__clickDisposer?.();\n this.__upDisposer?.();\n this.__preventScrollDisposer?.();\n }\n\n render() {\n const { className, zIndex, children, showDragArea, positionMode = 'fixed' } = this.props;\n const { startDrag, startTouchDrag, endDrag } = this;\n const stl = {\n zIndex,\n ...this.position,\n position: positionMode\n };\n return (\n <React.Fragment>\n {showDragArea && (\n <div\n className={c('drag-area')}\n ref={(r) => {\n this.dragAreaRef = r;\n }}\n style={{\n display: 'none',\n position: positionMode,\n backgroundColor: 'rgba(173, 216, 230, 0.2)', // 淡透蓝色\n border: '1px dashed var(--ohkit-color-primary, #1890ff)',\n pointerEvents: 'none',\n zIndex: (zIndex || 9999) - 1,\n boxSizing: 'border-box',\n borderRadius: this.props.lockAxis !== 'none' ? '2px' : '0',\n }}\n />\n )}\n <div\n className={cx(c('container'), className)}\n style={stl}\n ref={(r) => {\n this.draggerRef = r;\n }}\n onMouseDownCapture={startDrag}\n onMouseUpCapture={endDrag}\n onTouchStartCapture={startTouchDrag}\n onTouchEndCapture={endDrag}\n >\n {children}\n </div>\n </React.Fragment>\n );\n }\n}\n"],"names":["isPositioningContextCreator","element","includePosition","style","window","getComputedStyle","position","getPropertyValue","transform","filter","perspective","contain","willChange","includes","findFixedPositionParent","dom","findParent","parent","excludeOwn","document","documentElement","findAbsolutePositionParent","body","getScaleRatio","scaleX","scaleY","rect","getBoundingClientRect","magnification","offsetWidth","Math","round","width","offsetHeight","height","clamp","value","min","max","supportsTouchEvents","navigator","maxTouchPoints","ValidPlacement","c","p","DraggableBox","_React$Component","props","_this","call","this","prePositionMode","preDraggerRef","container","draggerRef","isDragging","axisX","axisY","dX","dY","startTop","startLeft","startBottom","startRight","translateX","translateY","cachedScaleX","cachedScaleY","__moveDisposer","__clickDisposer","__bodyClassDisposer","__upDisposer","__resizeDisposer","__preventScrollDisposer","dragAreaRef","dragingClassMap","none","x","y","enableDrag","isTouch","reportStartPosition","addEventListener","evt","stopPropagation","preventDefault","sqrt","pow","showDragAreaOverMoveDistanse","addClass","lockAxis","undefined","showDragArea","onDragStart","top","left","bottom","right","diffX","diffY","dragging","passive","endDrag","startDrag","nativeEvent","button","pageX","pageY","disabled","_this$dragPositionBou","dragPositionBoundaries","minX","maxX","minY","maxY","TouchEvent","touch","touches","potentialLeft","potentialTop","onDrag","startTouchDrag","positionChange","calcPosition","onDragEnd","hideDragArea","requestAnimationFrame","_this$dragPositionBou2","dragSize","dragBoxSize","border","backgroundColor","display","_this$dragPositionBou3","_this$getContainerRec","getContainerRect","newTop","newLeft","realTop","realLeft","realBottom","realRight","state","setState","updateState","_temp","_ref","formatState","offsetX","offsetY","_this$props","_proto","prototype","_temp2","_ref2","_ref2$offsetX","defaultProps","_ref2$offsetY","_this$props$placement","placement","_placement$split","split","placementY","placementX","getContainer","useCache","_this$props$positionM","positionMode","clientWidth","clientHeight","scrollLeft","scrollTop","scrollerScrollLeft","scrollerScrollTop","borderLeftWidth","borderTopWidth","containerRect","containerStyle","parseFloat","borderRightWidth","borderBottomWidth","_getScaleRatio","_this$draggerRef$getB","componentDidMount","_this2","componentWillUnmount","_this$__resizeDispose","_this$__bodyClassDisp","_this$__moveDisposer","_this$__clickDisposer","_this$__upDisposer","_this$__preventScroll","render","_this3","_this$props2","className","zIndex","children","_this$props2$position","stl","_extends","React","createElement","Fragment","ref","r","pointerEvents","boxSizing","borderRadius","cx","onMouseDownCapture","onMouseUpCapture","onTouchStartCapture","onTouchEndCapture","key","get","_this$props3","boundsX","boundsY","_this$props3$placemen","_this$getContainerRec2","containerWidth","containerHeight","_placement$split2","defaultBounds","minBound","maxBound","_this$curPositionKey","curPositionKey","positionStyles","Component"],"mappings":"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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,10 +2,13 @@ import React from 'react';
|
|
|
2
2
|
import { classNames as cx } from "@ohkit/prefix-classname";
|
|
3
3
|
import { DraggableBoxProps, DraggableBoxState } from './type';
|
|
4
4
|
import './style.scss';
|
|
5
|
+
export * from './utils';
|
|
6
|
+
export * from './type';
|
|
5
7
|
export declare const c: (...arg: cx.ArgumentArray) => string;
|
|
6
8
|
export declare class DraggableBox extends React.Component<DraggableBoxProps, DraggableBoxState> {
|
|
7
9
|
static defaultProps: Partial<DraggableBoxProps>;
|
|
8
10
|
constructor(props: DraggableBoxProps);
|
|
11
|
+
private formatState;
|
|
9
12
|
private prePositionMode;
|
|
10
13
|
private preDraggerRef;
|
|
11
14
|
private container;
|
|
@@ -38,16 +41,21 @@ export declare class DraggableBox extends React.Component<DraggableBoxProps, Dra
|
|
|
38
41
|
dY: number;
|
|
39
42
|
startTop: number;
|
|
40
43
|
startLeft: number;
|
|
44
|
+
startBottom: number;
|
|
45
|
+
startRight: number;
|
|
46
|
+
translateX: number;
|
|
47
|
+
translateY: number;
|
|
41
48
|
cachedScaleX: number;
|
|
42
49
|
cachedScaleY: number;
|
|
43
|
-
__moveDisposer
|
|
44
|
-
__clickDisposer
|
|
45
|
-
__bodyClassDisposer
|
|
46
|
-
__upDisposer
|
|
47
|
-
__resizeDisposer
|
|
48
|
-
__preventScrollDisposer
|
|
50
|
+
private __moveDisposer?;
|
|
51
|
+
private __clickDisposer?;
|
|
52
|
+
private __bodyClassDisposer?;
|
|
53
|
+
private __upDisposer?;
|
|
54
|
+
private __resizeDisposer?;
|
|
55
|
+
private __preventScrollDisposer?;
|
|
49
56
|
dragAreaRef: HTMLDivElement | null;
|
|
50
|
-
reportStartPosition
|
|
57
|
+
private reportStartPosition;
|
|
58
|
+
dragingClassMap: Record<NonNullable<DraggableBoxProps['lockAxis']>, string>;
|
|
51
59
|
enableDrag: (isTouch?: boolean) => void;
|
|
52
60
|
startDrag: (evt: React.MouseEvent<HTMLDivElement>) => void;
|
|
53
61
|
dragging: (evt: MouseEvent | TouchEvent) => void;
|
|
@@ -55,9 +63,16 @@ export declare class DraggableBox extends React.Component<DraggableBoxProps, Dra
|
|
|
55
63
|
endDrag: () => void;
|
|
56
64
|
showDragArea: () => void;
|
|
57
65
|
hideDragArea: () => void;
|
|
58
|
-
calcPosition: () =>
|
|
66
|
+
calcPosition: () => {
|
|
67
|
+
top: number;
|
|
68
|
+
left: number;
|
|
69
|
+
bottom: number;
|
|
70
|
+
right: number;
|
|
71
|
+
diffX: number;
|
|
72
|
+
diffY: number;
|
|
73
|
+
};
|
|
74
|
+
updateState: ({ offsetX, offsetY }?: Pick<DraggableBoxProps, 'offsetX' | 'offsetY'>) => void;
|
|
59
75
|
componentDidMount(): void;
|
|
60
76
|
componentWillUnmount(): void;
|
|
61
77
|
render(): React.JSX.Element;
|
|
62
78
|
}
|
|
63
|
-
export default DraggableBox;
|
package/dist/types/type.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import type { ValidPlacement } from './constants';
|
|
3
|
+
export interface IPositionChange {
|
|
4
|
+
left: number;
|
|
5
|
+
top: number;
|
|
6
|
+
right: number;
|
|
7
|
+
bottom: number;
|
|
8
|
+
diffX: number;
|
|
9
|
+
diffY: number;
|
|
10
|
+
}
|
|
3
11
|
export interface DraggableBoxProps {
|
|
4
12
|
className?: string;
|
|
5
13
|
children?: React.ReactNode;
|
|
@@ -63,6 +71,18 @@ export interface DraggableBoxProps {
|
|
|
63
71
|
* @default 'fixed'
|
|
64
72
|
*/
|
|
65
73
|
positionMode?: 'fixed' | 'absolute';
|
|
74
|
+
/**
|
|
75
|
+
* 拖拽开始回调函数
|
|
76
|
+
*/
|
|
77
|
+
onDragStart?: (positionChange: IPositionChange) => void;
|
|
78
|
+
/**
|
|
79
|
+
* 拖拽中回调函数
|
|
80
|
+
*/
|
|
81
|
+
onDrag?: (positionChange: IPositionChange) => void;
|
|
82
|
+
/**
|
|
83
|
+
* 拖拽结束回调函数
|
|
84
|
+
*/
|
|
85
|
+
onDragEnd?: (positionChange: IPositionChange) => void;
|
|
66
86
|
}
|
|
67
87
|
export interface DraggableBoxState {
|
|
68
88
|
top?: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ohkit/draggable-box",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "可拖拽容器",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"draggable-box"
|
|
@@ -34,5 +34,5 @@
|
|
|
34
34
|
"react": ">=17",
|
|
35
35
|
"react-dom": ">=17"
|
|
36
36
|
},
|
|
37
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "0c377936f3902c76576a1850bdbbf6437d989637"
|
|
38
38
|
}
|
package/src/index.tsx
CHANGED
|
@@ -10,6 +10,8 @@ import {DraggableBoxProps, DraggableBoxState} from './type';
|
|
|
10
10
|
|
|
11
11
|
import './style.scss';
|
|
12
12
|
|
|
13
|
+
export * from './utils';
|
|
14
|
+
export * from './type';
|
|
13
15
|
export const c = p("ohkit-draggable-box__");
|
|
14
16
|
export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBoxState> {
|
|
15
17
|
static defaultProps: Partial<DraggableBoxProps> = {
|
|
@@ -26,17 +28,20 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
26
28
|
|
|
27
29
|
constructor(props: DraggableBoxProps) {
|
|
28
30
|
super(props);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
const { offsetX, offsetY } = this.props;
|
|
32
|
+
this.state = this.formatState({offsetX, offsetY});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private formatState({offsetX = DraggableBox.defaultProps.offsetX, offsetY = DraggableBox.defaultProps.offsetY} = {}) {
|
|
36
|
+
const { placement = 'bottom-right' } = this.props;
|
|
31
37
|
const [placementY, placementX] = placement.split('-') as ['top' | 'bottom', 'left' | 'right'];
|
|
32
|
-
|
|
33
|
-
// 简化状态初始化
|
|
34
|
-
this.state = {
|
|
38
|
+
const newState = {
|
|
35
39
|
top: placementY === 'top' ? offsetY : undefined,
|
|
36
40
|
bottom: placementY === 'bottom' ? offsetY : undefined,
|
|
37
41
|
left: placementX === 'left' ? offsetX : undefined,
|
|
38
42
|
right: placementX === 'right' ? offsetX : undefined,
|
|
39
|
-
}
|
|
43
|
+
}
|
|
44
|
+
return newState;
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
private prePositionMode: DraggableBoxProps['positionMode'];
|
|
@@ -65,8 +70,8 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
65
70
|
const container = this.getContainer(false);
|
|
66
71
|
if (!container) {
|
|
67
72
|
return {
|
|
68
|
-
width: window.innerWidth,
|
|
69
|
-
height: window.innerHeight,
|
|
73
|
+
width: document.documentElement.clientWidth, // window.innerWidth, 避免滚动条影响计算
|
|
74
|
+
height: document.documentElement.clientHeight, // window.innerHeight, 避免滚动条影响计算
|
|
70
75
|
left: 0,
|
|
71
76
|
top: 0,
|
|
72
77
|
scrollLeft: 0,
|
|
@@ -217,21 +222,25 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
217
222
|
dY = 0;
|
|
218
223
|
startTop = 0;
|
|
219
224
|
startLeft = 0;
|
|
225
|
+
startBottom = 0;
|
|
226
|
+
startRight = 0;
|
|
227
|
+
translateX = 0;
|
|
228
|
+
translateY = 0;
|
|
220
229
|
|
|
221
230
|
// 缓存缩放比例,避免在 dragging 中频繁计算
|
|
222
231
|
cachedScaleX = 1;
|
|
223
232
|
cachedScaleY = 1;
|
|
224
233
|
|
|
225
|
-
__moveDisposer?: () => void;
|
|
226
|
-
__clickDisposer?: () => void;
|
|
227
|
-
__bodyClassDisposer?: () => void;
|
|
228
|
-
__upDisposer?: () => void;
|
|
229
|
-
__resizeDisposer?: () => void;
|
|
230
|
-
__preventScrollDisposer?: () => void;
|
|
234
|
+
private __moveDisposer?: () => void;
|
|
235
|
+
private __clickDisposer?: () => void;
|
|
236
|
+
private __bodyClassDisposer?: () => void;
|
|
237
|
+
private __upDisposer?: () => void;
|
|
238
|
+
private __resizeDisposer?: () => void;
|
|
239
|
+
private __preventScrollDisposer?: () => void;
|
|
231
240
|
|
|
232
241
|
dragAreaRef: HTMLDivElement | null = null;
|
|
233
242
|
|
|
234
|
-
reportStartPosition() {
|
|
243
|
+
private reportStartPosition() {
|
|
235
244
|
if (this.draggerRef) {
|
|
236
245
|
// 获取缩放比例
|
|
237
246
|
const { scaleX, scaleY } = getScaleRatio(this.getContainer());
|
|
@@ -244,9 +253,17 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
244
253
|
// 计算相对于容器的位置,并除以缩放比例得到未缩放的坐标
|
|
245
254
|
this.startTop = top / scaleY - containerRect.top + containerRect.scrollTop - containerRect.borderTopWidth;
|
|
246
255
|
this.startLeft = left / scaleY - containerRect.left + containerRect.scrollLeft - containerRect.borderLeftWidth;
|
|
256
|
+
this.startBottom = containerRect.height - this.startTop - this.dragBoxSize.height;
|
|
257
|
+
this.startRight = containerRect.width - this.startLeft - this.dragBoxSize.width;
|
|
247
258
|
}
|
|
248
259
|
}
|
|
249
260
|
|
|
261
|
+
dragingClassMap: Record<NonNullable<DraggableBoxProps['lockAxis']>, string> = {
|
|
262
|
+
'none': 'moving',
|
|
263
|
+
'x': 'moving-x',
|
|
264
|
+
'y': 'moving-y'
|
|
265
|
+
}
|
|
266
|
+
|
|
250
267
|
enableDrag = (isTouch = false) => {
|
|
251
268
|
this.reportStartPosition();
|
|
252
269
|
this.__moveDisposer?.();
|
|
@@ -268,7 +285,7 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
268
285
|
},
|
|
269
286
|
true
|
|
270
287
|
);
|
|
271
|
-
this.__bodyClassDisposer = addClass([document.
|
|
288
|
+
this.__bodyClassDisposer = addClass([document.documentElement, this.draggerRef], c(this.dragingClassMap[this.props.lockAxis || 'none'])) || undefined;
|
|
272
289
|
|
|
273
290
|
// 显示拖拽区域
|
|
274
291
|
if (this.props.showDragArea && this.dragAreaRef) {
|
|
@@ -276,6 +293,18 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
276
293
|
}
|
|
277
294
|
}
|
|
278
295
|
}
|
|
296
|
+
// 调用拖拽开始回调
|
|
297
|
+
if (!this.isDragging && this.props.onDragStart) {
|
|
298
|
+
const positionChange = {
|
|
299
|
+
top: this.startTop,
|
|
300
|
+
left: this.startLeft,
|
|
301
|
+
bottom: this.startBottom,
|
|
302
|
+
right: this.startRight,
|
|
303
|
+
diffX: 0,
|
|
304
|
+
diffY: 0
|
|
305
|
+
};
|
|
306
|
+
this.props.onDragStart(positionChange);
|
|
307
|
+
}
|
|
279
308
|
this.dragging(evt as TouchEvent | MouseEvent);
|
|
280
309
|
}, {
|
|
281
310
|
passive: !isTouch
|
|
@@ -360,10 +389,28 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
360
389
|
translateY = maxY - this.startTop;
|
|
361
390
|
}
|
|
362
391
|
}
|
|
392
|
+
if (this.translateX === translateX && this.translateY === translateY) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// 调用拖拽中回调
|
|
397
|
+
if (this.props.onDrag) {
|
|
398
|
+
const positionChange = {
|
|
399
|
+
top: this.startTop + translateY,
|
|
400
|
+
left: this.startLeft + translateX,
|
|
401
|
+
bottom: this.startBottom - translateY,
|
|
402
|
+
right: this.startRight - translateX,
|
|
403
|
+
diffX: translateX,
|
|
404
|
+
diffY: translateY
|
|
405
|
+
};
|
|
406
|
+
this.props.onDrag(positionChange);
|
|
407
|
+
}
|
|
363
408
|
|
|
364
409
|
if (this.draggerRef) {
|
|
365
410
|
this.draggerRef.style.transform = `translate(${translateX}px, ${translateY}px)`;
|
|
366
411
|
}
|
|
412
|
+
this.translateX = translateX;
|
|
413
|
+
this.translateY = translateY;
|
|
367
414
|
};
|
|
368
415
|
|
|
369
416
|
startTouchDrag = (evt: React.TouchEvent<HTMLDivElement>) => {
|
|
@@ -378,7 +425,9 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
378
425
|
|
|
379
426
|
endDrag = () => {
|
|
380
427
|
if (this.isDragging) {
|
|
381
|
-
this.calcPosition();
|
|
428
|
+
const positionChange = this.calcPosition();
|
|
429
|
+
// 调用拖拽结束回调
|
|
430
|
+
this.props.onDragEnd?.(positionChange);
|
|
382
431
|
if (this.draggerRef) {
|
|
383
432
|
this.draggerRef.style.transform = '';
|
|
384
433
|
}
|
|
@@ -474,8 +523,6 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
474
523
|
const realBottom = height - realTop - this.dragBoxSize.height;
|
|
475
524
|
const realRight = width - realLeft - this.dragBoxSize.width;
|
|
476
525
|
if (realTop !== this.state.top || realLeft !== this.state.left || this.state.bottom !== realBottom || this.state.right !== realRight) {
|
|
477
|
-
// console.log(minY, maxY, this.startTop, this.dY, newTop, realTop, 'minY, maxY, this.startTop, this.dY, newTop, realTop --- calcPosition y');
|
|
478
|
-
// console.log(minX, maxX, this.startLeft, this.dX, newLeft, realLeft, 'minX, maxX, this.startLeft, this.dX, newLeft, realLeft ---calcPosition x');
|
|
479
526
|
this.setState({
|
|
480
527
|
top: realTop,
|
|
481
528
|
left: realLeft,
|
|
@@ -483,11 +530,29 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
483
530
|
right: realRight
|
|
484
531
|
});
|
|
485
532
|
}
|
|
533
|
+
const positionChange = {
|
|
534
|
+
top: realTop,
|
|
535
|
+
left: realLeft,
|
|
536
|
+
bottom: realBottom,
|
|
537
|
+
right: realRight,
|
|
538
|
+
diffX: realLeft - this.startLeft,
|
|
539
|
+
diffY: realTop - this.startTop
|
|
540
|
+
};
|
|
486
541
|
this.startTop = realTop;
|
|
487
542
|
this.startLeft = realLeft;
|
|
543
|
+
this.startBottom = realBottom;
|
|
544
|
+
this.startRight = realRight;
|
|
488
545
|
this.dX = this.dY = 0;
|
|
546
|
+
return positionChange;
|
|
489
547
|
};
|
|
490
548
|
|
|
549
|
+
// 更新状态并计算位置 (外部可以调用)
|
|
550
|
+
updateState = ({offsetX, offsetY}: Pick<DraggableBoxProps, 'offsetX' | 'offsetY'> = {}) => {
|
|
551
|
+
this.setState(this.formatState({offsetX, offsetY}), () => {
|
|
552
|
+
this.reportStartPosition();
|
|
553
|
+
this.calcPosition();
|
|
554
|
+
});
|
|
555
|
+
}
|
|
491
556
|
|
|
492
557
|
componentDidMount() {
|
|
493
558
|
// 检查初始位置是否在边界范围内,如果不在则修正
|
|
@@ -524,7 +589,7 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
524
589
|
position: positionMode
|
|
525
590
|
};
|
|
526
591
|
return (
|
|
527
|
-
|
|
592
|
+
<React.Fragment>
|
|
528
593
|
{showDragArea && (
|
|
529
594
|
<div
|
|
530
595
|
className={c('drag-area')}
|
|
@@ -556,9 +621,7 @@ export class DraggableBox extends React.Component<DraggableBoxProps, DraggableBo
|
|
|
556
621
|
>
|
|
557
622
|
{children}
|
|
558
623
|
</div>
|
|
559
|
-
|
|
624
|
+
</React.Fragment>
|
|
560
625
|
);
|
|
561
626
|
}
|
|
562
627
|
}
|
|
563
|
-
|
|
564
|
-
export default DraggableBox;
|
package/src/style.scss
CHANGED
|
@@ -2,7 +2,7 @@ $prefix: ohkit;
|
|
|
2
2
|
|
|
3
3
|
.#{$prefix}-draggable-box__ {
|
|
4
4
|
&container {
|
|
5
|
-
// position 由内联样式动态控制,默认为 fixed
|
|
5
|
+
// position 由内联样式动态控制,默认为 fixed, 外部可修改
|
|
6
6
|
user-select: none;
|
|
7
7
|
cursor: grab;
|
|
8
8
|
}
|
|
@@ -11,6 +11,14 @@ $prefix: ohkit;
|
|
|
11
11
|
cursor: move !important;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
&moving-x {
|
|
15
|
+
cursor: ew-resize !important;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
&moving-y {
|
|
19
|
+
cursor: ns-resize !important;
|
|
20
|
+
}
|
|
21
|
+
|
|
14
22
|
&drag-area {
|
|
15
23
|
transition: opacity 0.2s ease-in-out;
|
|
16
24
|
opacity: 0.7;
|
package/src/type.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import type {ValidPlacement} from './constants';
|
|
2
2
|
|
|
3
|
+
export interface IPositionChange {
|
|
4
|
+
left: number;
|
|
5
|
+
top: number;
|
|
6
|
+
right: number;
|
|
7
|
+
bottom: number;
|
|
8
|
+
diffX: number;
|
|
9
|
+
diffY: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
3
12
|
export interface DraggableBoxProps {
|
|
4
13
|
className?: string;
|
|
5
14
|
children?: React.ReactNode;
|
|
@@ -63,6 +72,18 @@ export interface DraggableBoxProps {
|
|
|
63
72
|
* @default 'fixed'
|
|
64
73
|
*/
|
|
65
74
|
positionMode?: 'fixed' | 'absolute';
|
|
75
|
+
/**
|
|
76
|
+
* 拖拽开始回调函数
|
|
77
|
+
*/
|
|
78
|
+
onDragStart?: (positionChange: IPositionChange) => void;
|
|
79
|
+
/**
|
|
80
|
+
* 拖拽中回调函数
|
|
81
|
+
*/
|
|
82
|
+
onDrag?: (positionChange: IPositionChange) => void;
|
|
83
|
+
/**
|
|
84
|
+
* 拖拽结束回调函数
|
|
85
|
+
*/
|
|
86
|
+
onDragEnd?: (positionChange: IPositionChange) => void;
|
|
66
87
|
}
|
|
67
88
|
|
|
68
89
|
export interface DraggableBoxState {
|
package/LICENSE.md
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
Copyright (c) [2025], [wuqiuyang]
|
|
2
|
-
|
|
3
|
-
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
|
4
|
-
|
|
5
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|