I am already calculating left and top positions using getBoundingClientRect() of child element wrt to parent in px and passinig from one component to another , and able to place the child elements on the expected positions , however I want to make child elements responsive wrt to parent element , for that I need top and left positions in % I already tried changing values and unit from px to % from console and was able to get desired responsiveness, however trying to calculate in percentage in the code is not working as expected, it doesn't place the child element on correct position, though responsiveness is achieved.
minX: viewRect.left - movableClientRect.left + movable.position.x,
maxX: viewRect.right - movableClientRect.right + movable.position.x,
minY: viewRect.top - movableClientRect.top + movable.position.y,
maxY: viewRect.bottom - movableClientRect.bottom + movable.position.y
this.dataService.setData(this.zonePosition =
{
x : (viewRect.left - movableClientRect.left)/viewRect.left ,
y: (viewRect.top - movableClientRect.top)/viewRect.top
}
In the earlier code I was only doing viewRect.left - movableClientRect.left , so values were in pixel , and now I tried dividing by viewRect.left and then * 100 to convert it into % but the percentage value doesn't place the child elements correctly.
Updating with the directives for calculating the position
movable.directive In this I calculate the x and y pos of the child element
interface Position {
x: number;
y: number;
}
@Directive({
selector: '[appMovable]'
})
export class MovableDirective extends DraggableDirective {
@HostBinding('style.transform') get transform(): SafeStyle {
return this.sanitizer.bypassSecurityTrustStyle(
`translateX(${this.position.x}%) translateY(${this.position.y}%)`
);
}
@HostBinding('class.movable') movable = true;
position: Position = {x: 0, y: 0};
zonePosition = {x:0, y:0, id:""}
private startPosition: Position;
@Input('appMovableReset') reset = false;
constructor(private sanitizer: DomSanitizer, public element: ElementRef,
private dataService: DataService) {
super(element);
}
@HostListener('dragStart', ['$event'])
onDragStart(event: PointerEvent) {
this.startPosition = {
x: event.clientX - this.position.x,
y: event.clientY - this.position.y
}
}
@HostListener('dragMove', ['$event'])
onDragMove(event: PointerEvent) {
this.position.x = event.clientX - this.startPosition.x;
this.position.y = event.clientY - this.startPosition.y;
}
@HostListener('dragEnd', ['$event'])
onDragEnd(event: PointerEvent) {
if (this.reset) {
this.position = {x: 0, y: 0};
}
}
}
The directive in which I am calculating the left and top of the child element and assigning it to dataService
Directive({
selector: '[appMovableArea]'
})
export class MovableAreaDirective implements AfterContentInit {
@ContentChildren(MovableDirective) movables: QueryList<MovableDirective>;
private boundaries: Boundaries;
private subscriptions: Subscription[] = [];
zonePosition = {x:0, y:0, id:""}
constructor(private element: ElementRef, private dataService: DataService)
{}
ngAfterContentInit(): void {
this.movables.changes.subscribe(() => {
this.subscriptions.forEach(s => s.unsubscribe());
this.movables.forEach(movable => {
this.subscriptions.push(movable.dragStart.subscribe(() =>
this.measureBoundaries(movable)));
this.subscriptions.push(movable.dragMove.subscribe(() =>
this.maintainBoundaries(movable)));
});
});
this.movables.notifyOnChanges();
}
private measureBoundaries(movable: MovableDirective) {
const viewRect: ClientRect =
this.element.nativeElement.getBoundingClientRect();
const movableClientRect: ClientRect =
movable.element.nativeElement.getBoundingClientRect();
this.dataService.setData(this.zonePosition= {x : (viewRect.left -
movableClientRect.left)/viewRect.left , y: (viewRect.top -
movableClientRect.top)/viewRect.top, id: "" })
this.boundaries = {
minX: viewRect.left - movableClientRect.left + movable.position.x,
maxX: viewRect.right - movableClientRect.right + movable.position.x,
minY: viewRect.top - movableClientRect.top + movable.position.y,
maxY: viewRect.bottom - movableClientRect.bottom + movable.position.y
};
}
private maintainBoundaries(movable: MovableDirective) {
movable.position.x = Math.max(this.boundaries.minX,
movable.position.x);
movable.position.x = Math.min(this.boundaries.maxX, movable.position.x);
movable.position.y = Math.max(this.boundaries.minY, movable.position.y);
movable.position.y = Math.min(this.boundaries.maxY, movable.position.y);
}
}