components icon indicating copy to clipboard operation
components copied to clipboard

feat(cdk/drag-drop): X and Y as percentage values instead of px

Open SvenBudak opened this issue 2 years ago • 2 comments

Feature Description

We are developing a mobile app in which users should be able to move elements back and forth in a certain area. The position of the elements should obviously be identical for every user. However, this does not work since each user has a different smartphone and therefore a different screen width, as cdk/drag-drop works with px values. One should be able to switch from px to % in order to ensure the correct position regardless of the screen resolution (or the width of the boundary element).

SvenBudak avatar Feb 19 '24 00:02 SvenBudak

This may be tricky to do, because we currently map 1px of movement to 1px in the transform value.

crisbeto avatar Feb 19 '24 11:02 crisbeto

This may be tricky to do, because we currently map 1px of movement to 1px in the transform value.

My math skills are at the level of a 12-year-old. 😅 Otherwise, I would participate in solving this problem. But, as I understand it, one must also scale the object to be moved by x% proportionally to the boundary. This ensures that the movable objects appear visually the same size at each scale.

I just realized that using transform: translate3d(97%, 100%, 0px) in percentage terms does not behave as I expected...

Unfortunately, this is really a problem, thus drag is not usable if it represents an element that is synchronized across multiple users, each with different screen widths.

A friend mentioned this conversion as a possible solution... however, I don't understand much of it. Maybe it helps with this issue:

Canvas:
baseCanvasWidth: 1080px
baseCanvasHeight: 1920px

A random image on the canvas:
originalImageWidth: 32px
originalImageHeight: 32px
originalImagePosX: 100px
originalImagePosY: 100px

---

Case 1:
deviceCanvasWidth: 720px
deviceCanvasHeight: 1280px

-> Results for Case 1 (see below) <-

Case 1 random image on the canvas:
imageWidth: 720px / 1080px * 32px = 21.333px
imageHeight: 1280px / 1920px * 32px = 21.333px
imagePosX: 720px / 1080px * 100px = 66.666px
imagePosY: 1280px / 1920px * 100px = 66.666px

---

Formula:

deviceCanvasWidth / baseCanvasWidth * originalImageWidth = rescaledImageWidth
deviceCanvasHeight / baseCanvasHeight * originalImageHeight = rescaledImageHeight

deviceCanvasWidth / baseCanvasWidth * originalImagePosX = rescaledImagePosX
deviceCanvasHeight / baseCanvasHeight * originalImagePosY = rescaledImagePosY

SvenBudak avatar Feb 19 '24 11:02 SvenBudak

I'm currently facing a similar problem where I have a container (that holds cdkDrag elements) which I scale using CSS transformation, if not mistaken the behaviour is similar to the one aforementioned here. I think adding an Input like cdkDragScaling and incorporating it into the following could help. https://github.com/angular/components/blob/436301f41f0a44f60c99bda4d121f893a6b63d55/src/cdk/drag-drop/drag-ref.ts#L648 When using cdkDrag in an application, one could then for example set [cdkDragScaling]="{ x: .75, y: .5 }" and the scaling would be applied onto the elements movement. That would leave the work of calculating the scaling on the side of the dev using cdkDrag and would leave a lot of freedom, if I'm not entirely mistaken.

edit: sadly I don't have a lot of time on my hands to test it out

Lubjan avatar Mar 28 '24 12:03 Lubjan

@Lubjan Do I understand you correctly? The necessary features already exist in cdkDrag for clean scaling?

SvenBudak avatar Mar 28 '24 12:03 SvenBudak

@Lubjan Do I understand you correctly? The necessary features already exist in cdkDrag for clean scaling?

No, it is a proposal to add cdkDragScaling as a feature into cdkDrag itself. If something like that already exists, I am not aware of it or wasn't able to find it yet. (I don't mean visibly scaling the element)

Lubjan avatar Mar 28 '24 13:03 Lubjan