fixed drag and drop problem when within parent and dragImage problem

This commit is contained in:
paul
2025-03-07 17:09:35 +05:30
parent 71c2bfd949
commit 217dedc121
3 changed files with 93 additions and 35 deletions

View File

@@ -683,9 +683,9 @@ class Canvas extends React.Component {
const container = draggedElement.getAttribute("data-container")
const canvasRect = this.canvasRef.current.getBoundingClientRect()
const draggedElementRect = draggedElement.getBoundingClientRect()
const elementWidth = draggedElementRect.width
const elementHeight = draggedElementRect.height
// const draggedElementRect = draggedElement.getBoundingClientRect()
// const elementWidth = draggedElementRect.width
// const elementHeight = draggedElementRect.height
const { clientX, clientY } = e
@@ -752,6 +752,7 @@ class Canvas extends React.Component {
parent: "",
initialData: {
...childData,
parentWidgetRef: null,
pos: { x: finalPosition.x, y: finalPosition.y },
positionType: PosType.ABSOLUTE, // makes sure that after dropping the position is set to absolute value
parentLayout: null,// reset the parent layout when its put on the canvas
@@ -795,7 +796,7 @@ class Canvas extends React.Component {
* @param {object} dragElement
* @param {boolean} create - if create is set to true the widget will be created before adding to the child tree
*/
handleAddWidgetChild = ({event, parentWidgetId, dragElementID, swap = false }) => {
handleAddWidgetChild = ({event, parentWidgetId, dragElementID, swap = false, posMetaData }) => {
// console.log("event: ", event)
// widgets data structure { id, widgetType: widgetComponentType, children: [], parent: "" }
@@ -813,13 +814,30 @@ class Canvas extends React.Component {
const parentWidget = this.widgetRefs[parentWidgetId].current
const parentRect = parentWidget.getBoundingRect()
const { clientX, clientY } = event
const {dragStartCursorPos, initialPos} = posMetaData
console.log("Pos meyta data: ", posMetaData)
let finalPosition = {
x: (clientX - parentRect.left) / this.state.zoom,
y: (clientY - parentRect.top) / this.state.zoom,
}
const canvasBoundingRect = this.getCanvasBoundingRect()
const initialOffset = {
x: ((dragStartCursorPos.x - canvasBoundingRect.left) / this.state.zoom - this.state.currentTranslate.x) - initialPos.x,
y: ((dragStartCursorPos.y - canvasBoundingRect.top) / this.state.zoom - this.state.currentTranslate.y) - initialPos.y
}
finalPosition = {
x: finalPosition.x - initialOffset.x - this.state.currentTranslate.x,
y: finalPosition.y - initialOffset.y - this.state.currentTranslate.y
}
// TODO: fix swapping for grid layouts
if (swap) {
// If swapping, we need to find the common parent
@@ -860,15 +878,18 @@ class Canvas extends React.Component {
const updatedDragWidget = {
...dragWidgetObj,
parent: dropWidgetObj.id, // Keep the parent reference
initialData: {
...dragData,
positionType: parentLayout === Layouts.PLACE ? PosType.ABSOLUTE : PosType.NONE,
parentLayout: parentWidget.getLayout() || null, // pass everything about the parent layout
parentWidgetRef: this.widgetRefs[parentWidgetId],
zIndex: 0,
pos: {x: finalPosition.x, y: finalPosition.y},
widgetContainer: WidgetContainer.WIDGET
}
}
console.log("added parent: ", updatedDragWidget)
const updatedDropWidget = {
...dropWidgetObj,
@@ -1044,9 +1065,10 @@ class Canvas extends React.Component {
renderWidget = (widget) => {
// FIXME: initial data parentWidgetRef is empty
const { id, widgetType: ComponentType, children = [], parent, initialData = {} } = widget
console.log("parent: ", parent)
const renderChildren = (childrenData) => {
// recursively render the child elements
return childrenData.map((child) => {
@@ -1057,6 +1079,7 @@ class Canvas extends React.Component {
return null
})
}
console.log("initial data: ", initialData, initialData.parentWidgetRef)
return (
@@ -1065,6 +1088,7 @@ class Canvas extends React.Component {
id={id}
ref={this.widgetRefs[id]}
initialData={initialData}
parentWidgetRef={initialData.parentWidgetRef || null}
canvasRef={this.canvasContainerRef}
canvasInnerContainerRef={this.canvasRef}
canvasMetaData={{

View File

@@ -782,9 +782,6 @@ class Widget extends React.Component {
if (parentLayout?.layout === Layouts.FLEX || parentLayout?.layout === Layouts.GRID){
const elementRect = this.elementRef.current.getBoundingClientRect()
const {pan: canvasPan, zoom: canvasZoom} = this.canvasMetaData
console.log("elemnt rect2: ", elementRect)
layoutUpdates = {
...layoutUpdates,
@@ -845,31 +842,30 @@ class Widget extends React.Component {
// this.props.onWidgetDragStart(this.elementRef?.current)
// Create custom drag image with full opacity, this will ensure the image isn't taken from part of the canvas
const dragImage = this.elementRef?.current.cloneNode(true)
dragImage.style.opacity = '1' // Ensure full opacity
dragImage.style.position = 'absolute'
dragImage.style.top = '-9999px' // Move it out of view
// const dragImage = this.elementRef?.current.cloneNode(true)
// dragImage.style.opacity = '1' // Ensure full opacity
// dragImage.style.position = 'absolute'
// dragImage.style.top = '-9999px' // Move it out of view
document.body.appendChild(dragImage)
const rect = this.elementRef?.current.getBoundingClientRect()
// document.body.appendChild(dragImage)
// const elementRect = this.elementRef.current.getBoundingClientRect()
// const canvasRect = this.props.canvasInnerContainerRef.current.getBoundingClientRect()
// snap to mouse pos
// const offsetX = e.clientX - rect.left
// const offsetY = e.clientY - rect.top
// const offsetX = e.clientX - elementRect.left
// const offsetY = e.clientY - elementRect.top
// console.log("element rect: ", elementRect, e.clientX, e.clientY, "offset: ", offsetX, offsetY)
// snap to middle
// const offsetX = rect.width / 2
// const offsetY = rect.height / 2
const offsetX = e.clientX - rect.left;
const offsetY = e.clientY - rect.top;
e.dataTransfer.setDragImage(dragImage, offsetX, offsetY);
// e.dataTransfer.setDragImage(dragImage, offsetX, offsetY);
// Remove the custom drag image after some time to avoid leaving it in the DOM
setTimeout(() => {
document.body.removeChild(dragImage)
}, 0)
// setTimeout(() => {
// document.body.removeChild(dragImage)
// }, 0)
// NOTE: this line will prevent problem's such as self-drop or dropping inside its own children
setTimeout(this.disablePointerEvents, 1)
@@ -951,7 +947,7 @@ class Widget extends React.Component {
}
handleDropEvent = (e, draggedElement, widgetClass = null) => {
handleDropEvent = (e, draggedElement, widgetClass = null, posMetaData) => {
if (!draggedElement || !draggedElement.getAttribute("data-drag-start-within")){
// if the drag is starting from outside (eg: file drop) or if drag doesn't exist
@@ -1004,6 +1000,8 @@ class Widget extends React.Component {
return
}
// TODO: check if the drop is allowed
console.log("Meta data: ", posMetaData)
if ([WidgetContainer.CANVAS, WidgetContainer.WIDGET].includes(container)) {
// console.log("Dropped on meee: ", swapArea, this.swappableAreaRef.current.contains(e.target), thisContainer)
@@ -1011,7 +1009,8 @@ class Widget extends React.Component {
event: e,
parentWidgetId: this.__id,
dragElementID: draggedElement.getAttribute("data-widget-id"),
swap: swapArea || false
swap: swapArea || false,
posMetaData
})
} else if (container === WidgetContainer.SIDEBAR) {
@@ -1021,7 +1020,8 @@ class Widget extends React.Component {
this.props.onAddChildWidget({
event: e,
parentWidgetId: this.__id,
dragElementID: id
dragElementID: id,
posMetaData
}) // if dragged from the sidebar create the widget first
})
@@ -1152,14 +1152,47 @@ class Widget extends React.Component {
}
const handleSetInitialPosition = (e, setPosMetaData) => {
e.stopPropagation() // prevent this event from bubbling up to parents
const {clientX, clientY} = e
const elementRect = this.elementRef.current.getBoundingClientRect()
const canvasInnerRect = this.props.canvasInnerContainerRef.current.getBoundingClientRect()
const {zoom, pan} = this.props.canvasMetaData
console.log("Loss: ", this.props.parentWidgetRef)
// TODO: if parent exist also subtract it
let initialPos = {
x: elementRect.left - canvasInnerRect.left,
y: elementRect.top - canvasInnerRect.top
}
let parent = this.props.parentWidgetRef?.current;
console.log("parent1111: ", this.__id, parent, this.props)
while (parent) {
// accounting for nested parents
const parentRect = parent.getBoundingRect()
console.log("parent: ", parentRect)
initialPos.x -= parentRect.left - canvasInnerRect.left
initialPos.y -= parentRect.top - canvasInnerRect.top
// Move up to the next parent (if any)
parent = parent.parentWidgetRef?.current
}
const posMetaData = {
dragStartCursorPos: {x: clientX, y: clientY},
initialPos: {...this.state.pos}
initialPos: {...initialPos}
}
console.log("initial pos: ", posMetaData)
setPosMetaData(posMetaData)
}
@@ -1174,7 +1207,7 @@ class Widget extends React.Component {
<DragContext.Consumer>
{
({ draggedElement, widgetClass, onDragStart, onDragEnd, overElement, setOverElement, setPosMetaData }) => {
({ draggedElement, widgetClass, onDragStart, onDragEnd, overElement, setOverElement, posMetaData, setPosMetaData }) => {
const canvasRect = this.canvas.getBoundingClientRect()
const canvasRectInner = this.props.canvasInnerContainerRef?.current.getBoundingClientRect()
@@ -1198,7 +1231,7 @@ class Widget extends React.Component {
draggable={this.state.dragEnabled}
onDragOver={(e) => this.handleDragOver(e, draggedElement)}
onDrop={(e) => {this.handleDropEvent(e, draggedElement, widgetClass); onDragEnd()}}
onDrop={(e) => {this.handleDropEvent(e, draggedElement, widgetClass, posMetaData); onDragEnd()}}
onDragEnter={(e) => this.handleDragEnter(e, draggedElement, setOverElement)}
onDragLeave={(e) => this.handleDragLeave(e, draggedElement, overElement)}

View File

@@ -16,10 +16,11 @@ const DraggableWrapper = memo(({dragElementType, dragWidgetClass=null, currentPo
const setInitialPos = (e) => {
const {clientX, clientY} = e
const draggableRect = draggableRef.current.getBoundingClientRect()
const posMetaData = {
dragStartCursorPos: {x: clientX, y: clientY},
initialPos: currentPos
initialPos: {x: draggableRect.x, y: draggableRect.y}
}
setPosMetaData(posMetaData)