我在使用 Angular 11 的 CDK 材质通过拖放缩放整个场景时遇到了同样的问题。
dragConstrainPoint 解决方案不适用于我的上下文。
这个想法实际上是为了避免变换缩放或缩放,让它与鼠标和对象位置混淆,使其成为多人拖放的噩梦。
我的解决方案在具有不同场景比例的多人游戏中效果很好
解决方案:
我在包装 div 上使用了 CSS 变量 --scale,并进行了动态缩放计算
<div class="game-wrapper" style="{{'--scale:'+ gameScale}}">
在 Angular 中,场景比例是这样计算的:
...
private _unsubscriber$: Subject<any> = new Subject();
public screenWidth$: BehaviorSubject<number> = new BehaviorSubject(null);
public screenHeight$: BehaviorSubject<number> = new BehaviorSubject(null);
public gameScale: number = 1;
public constructor(
@Inject(DOCUMENT) private document: any
) { }
...
ngOnInit(): void {
//Manage screen width
this._setScreenResolution(window.innerWidth, window.innerHeight);
fromEvent(window, 'resize')
.pipe(
debounceTime(1000),
takeUntil(this._unsubscriber$)
).subscribe((evt: any) => {
this._setScreenResolution(evt.target.innerWidth, evt.target.innerHeight);
});
}
ngOnDestroy() {
this._unsubscriber$.next();
this._unsubscriber$.complete();
}
private _setScreenResolution(width: number, height: number): void {
this.screenWidth$.next(width);
this.screenHeight$.next(height);
let scaleX = windowWidth / this.sceneWidth;
let scaleY = windowHeight / this.sceneHeight;
let scale = scaleX;
if(scaleX > scaleY) {
scale = scaleY;
}
//console.log("getGameScale", scale.toFixed(3));
scale = parseFloat(scale.toFixed(3));
this.gameScale = scale;
}
在 HTML 模板和 CSS 中,每次涉及像素时,我们都会添加 calc()。
这里有一些带有这些计算的 CSS 示例
width: calc(18px * var(--scale));
padding: calc(1px * var(-scale)) calc(6px * var(-scale));
background-size: calc(30px * var(-scale)) calc(30px * var(-scale)), cover;
margin: calc(20px * var(-scale)) calc(30px * var(-scale));
bottom: calc(300px * var(--scale));
border-radius: calc(4px * var(--scale));
font-size: calc(21px * var(--scale));
left: calc(10px * var(--scale));
top: calc(4px * var(--scale));
box-shadow: 0 0 0 calc(4px * var(--scale)) rgba(0,0,0,0.1) inset;
border: calc(2px * var(--scale)) solid #6898f3;
height: calc(32px * var(--scale));
min-height: calc(26px * var(--scale));
line-height: calc(42px * var(--scale));
为了让本地CDK拖拽移动和拖拽结束值能够很好的发送给其他多人游戏,
您需要通过除以比例来缩放它们:
dragMoved(event: CdkDragMove) {
let {offsetLeft, offsetTop} = event.source.element.nativeElement;
let {x, y} = event.distance;
x = x / this.gameScale;
y = y / this.gameScale;
offsetLeft = offsetLeft / this.gameScale;
offsetTop = offsetTop / this.gameScale;
//Remove scene offset from calcul (ex. for aside left menu)
let xpos = ((offsetLeft + x) - this.offset.x);
let ypos = ((offsetTop + y) - this.offset.y);
let position: any = {x: xpos, y: ypos};
//The position is then sent to a multiplayer management relay message...
}
//same for drag end + do not forget to reset the transform 3D at the end of the function
dragEnded(event: CdkDragEnd) {
...
//The position at drag end is set on the object and for all other players
//Reset translate3D
//event.source._dragRef.setFreeDragPosition({x: 0, y: 0});
event.source._dragRef.reset();
}
瞧!