I am working on the following Drag and Drop library as a side project. I am using transform translate to make a element draggable. I store the initial client.x and client.y and calculate the translate value by subtracting the current client.x and client.y when the mouse move. In simple terms I record the initial click coords(x,y) and when I subtract the current coords(x,y) on mouse move it will give me the distance by which mouse has moved from the initial position which I then apply to the element using translate.
It works as expected. I have even implemented cursor offset which also works but the only thing I am not able to figure out is how to adjust the position if scale property is applied to the element. When the element scale is changed from 1 to any other value the size and position of the element will change which is messing up my current calculation.
I have created a simple diagram which you can see here. I’m also sharing the screenshot bellow.

You might need to understand the flow of the program so below is a simple explanation
- when a element is made draggable a pointer down event is attached to trigger dragStart.
- dragStart creates the default drag preview, sets the initial position and cursor offset
- when the element is dragged #translateDragPreview method is called to set the position of the element.
The position of the element is handle by these two following methods
#translateDragPreview(x?: number, y?: number) {
if (this.#draggedPreview.element === null) return;
const cords = {
x: x ?? this.#internalState.activeCords.x,
y: y ?? this.#internalState.activeCords.y,
};
const initialX = this.#initialPosition.x / this.#draggedPreview.scale;
const initialY = this.#initialPosition.y / this.#draggedPreview.scale;
this.#draggedPreview.element.style.transform = `translate(
${cords.x - initialX}px,
${cords.y - initialY}px)
scale(${this.#draggedPreview.scale})`;
}
#setCursorOffset(
dragElement: HTMLElement,
event: PointerEvent,
offset: BaseDraggableType["modifiers"]["cursor"]["offset"],
) {
const cursorOffset = offset;
const rect = dragElement.getBoundingClientRect();
const { scale } = this.#draggedPreview;
const clickX = this.#internalState.initialCords.x - rect.left;
const clickY = this.#internalState.initialCords.y - rect.top;
const adjustRect: (value: number) => number = (value) => value + (value - value / scale);
const adjustedRect = {
left: rect.left / scale,
right: adjustRect(rect.right),
top: adjustRect(rect.top),
bottom: adjustRect(rect.bottom),
width: adjustRect(rect.width),
height: adjustRect(rect.height),
};
const presetOffset = {
"top-left": {
x: adjustedRect.left - cursorOffset.x,
y: adjustedRect.top - cursorOffset.y,
},
"top-right": {
x: adjustedRect.right + cursorOffset.x,
y: adjustedRect.top - cursorOffset.y,
},
"bottom-left": {
x: adjustedRect.left - cursorOffset.x,
y: adjustedRect.bottom + cursorOffset.y,
},
"bottom-right": {
x: adjustedRect.right + cursorOffset.x,
y: adjustedRect.bottom + cursorOffset.y,
},
center: {
x: adjustedRect.left + adjustedRect.width / 2 + cursorOffset.x - 4,
y: adjustedRect.top + adjustedRect.height / 2 + cursorOffset.y - 2,
},
auto: {
x: adjustedRect.left + clickX + cursorOffset.x,
y: adjustedRect.top + clickY + cursorOffset.y,
},
};
this.#initialPosition = presetOffset[cursorOffset.preset];
}
Some more information
- this.#internalState.activeCords stores the current client.x and client.y
- this.#internalState.initialCords.x stores the initial click coordinate (x,y)
- this.#initialPosition stores the intialPosition with offset applied. I also tried to adjust the scale but it is not working if scale value is more or less then 1
Here is a code sandbox link with setup. please check the index.html and main.ts file . In the main.ts file you fill see dragOptions with scale option set to 1 if you will change it to any other value the element position will not be set properly.
You can also change the preset to any of the following
- preset: “top-left” | “top-right” | “bottom-left” | “bottom-right” | “center” | “auto”;
if you don’t want to go through all the code, you can just help me formulate how to calculate a elements correct position when it is dragged using translate and adjusted for scale value. When scale is applied the size and position is change and how to adjust for that I need a formula for that.
I have also created a simple demo in codepen. Please have a look. it is the same approach I have used in my library.
Please let me know if any further information is required I’m happy to help.