使用 Angular CDK DRAG 在拖动元素上丢失旋转位置
Lost Rotate position on Drag element with Angular CDK DRAG
我正在尝试使用范围滑块旋转一个元素,但每次我拖动该元素时,它都会在拖动时丢失旋转值,并且还会更改框的位置并将其放在开头。
我将 link 附加到我在 stackblitz 中创建的一个简单测试项目,以便我可以重现我遇到的问题。
stackblitz drag and rotate example
有人可以指导我解决问题吗?
我把代码放在这里以防有人不能很好地 link 测试项目:
app.module.ts
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { FormsModule } from "@angular/forms";
import { DragDropModule } from "@angular/cdk/drag-drop";
import { AppComponent } from "./app.component";
import { HelloComponent } from "./hello.component";
@NgModule({
imports: [BrowserModule, FormsModule, DragDropModule],
declarations: [AppComponent, HelloComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
app.component.ts
import { Component, Renderer2 } from "@angular/core";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
rotateValue = 0;
dragPosition = { x: 0, y: 0 };
constructor(private renderer: Renderer2) {}
setRotate(value: string) {
this.rotateValue = Number(value);
this.renderer.setStyle(
document.querySelector(".example-box"),
"transform",
`rotate(${this.rotateValue}deg)`
);
}
}
app.component.html
<h1 class="text-center m-3">Drag And Drop Project</h1>
<hr>
<div class="row m-5">
<div class="col-sm-7">
<div class="example-boundary">
<div class="example-box" cdkDragBoundary=".example-boundary" cdkDrag>
I can only be dragged within the dotted container
</div>
</div>
</div>
<div class="col-sm-5">
<h4>SETTINGS</h4>
<ul class="list-group mb-3">
<li class="list-group-item d-flex justify-content-between lh-condensed">
<div>
<h6 class="my-0">Rotate the box</h6>
<input #rotation
type="range"
class="custom-range my-2"
min="-150" max="150"
[(ngModel)]="rotateValue"
[value]='rotateValue'
(change)="setRotate(rotation.value)"
>
</div>
<span id="grados" class="text-muted">{{rotateValue}}º</span>
</li>
</ul>
</div>
</div>
app.component.css
.example-box {
width: 140px;
height: 140px;
border: solid 1px #ccc;
color: rgba(0, 0, 0, 0.87);
cursor: move;
display: inline-flex;
justify-content: center;
align-items: center;
text-align: center;
background: #fff;
border-radius: 4px;
margin-right: 25px;
position: relative;
z-index: 1;
box-sizing: border-box;
padding: 10px;
transition: box-shadow 200ms cubic-bezier(0, 0, 0.2, 1);
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),
0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
.example-box:active {
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
}
.example-boundary {
width: 300px;
height: 500px;
max-width: 100%;
border: dotted #ccc 2px;
}
非常感谢您
您遇到的问题是 Cdk 拖动是使用 CSS transform
规则实现的,与您的自定义旋转完全一样。
因此,当应用于完全相同的 HTML 元素时,两者基本上是不兼容的。最后一个操作,无论是拖动还是旋转,都会覆盖另一个。
IMO 最简单的解决方法是将旋转的元素包装在可拖动的包装器中。
这里是更新后的 StackBlitz:
https://stackblitz.com/edit/angular-ivy-ynzavj
编辑回顾:
在模板中,我将可旋转的 div 包装成可拖动的(我也使用 [ngStyle]
并完全避免了直接的 DOM 操作,这本身不是问题, 但没必要):
<div class="example-boundary">
<div class="box-draggable-wrapper" cdkDragBoundary=".example-boundary" cdkDrag>
<div class="example-box" [ngStyle]="{'transform':'rotate(' + rotateValue + 'deg)'}" >
I can only be dragged within the dotted container
</div>
</div>
</div>
box-draggable-wrapper
的CSS:
.box-draggable-wrapper {
width: 140px;
height: 140px;
display: block;
border: none;
}
组件被清理:
import { Component } from "@angular/core";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
rotateValue = 0;
dragPosition = { x: 0, y: 0 };
constructor() {}
setRotate(value: string) {
this.rotateValue = +value;
}
}
好吧,我想您已经猜到了,拖动操作会扰乱框的样式,每次拖动框时,您之前的旋转值都会丢失。但是,与此同时,您也通过用新的旋转值覆盖其当前值来弄乱框样式,因此每次旋转框时框位置都会不断重置(删除 translate3D
值)。
您可以通过获取元素的当前样式并将其与您的样式合并,然后再将其设置回原位来轻松修复代码,这样可以解决位置问题,但是再次拖动框时仍然会丢失旋转值。
好消息是已经有一个open issue for this bug and a proposed fix,但坏消息是它们还在营业
我正在尝试使用范围滑块旋转一个元素,但每次我拖动该元素时,它都会在拖动时丢失旋转值,并且还会更改框的位置并将其放在开头。 我将 link 附加到我在 stackblitz 中创建的一个简单测试项目,以便我可以重现我遇到的问题。
stackblitz drag and rotate example
有人可以指导我解决问题吗?
我把代码放在这里以防有人不能很好地 link 测试项目:
app.module.ts
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { FormsModule } from "@angular/forms";
import { DragDropModule } from "@angular/cdk/drag-drop";
import { AppComponent } from "./app.component";
import { HelloComponent } from "./hello.component";
@NgModule({
imports: [BrowserModule, FormsModule, DragDropModule],
declarations: [AppComponent, HelloComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
app.component.ts
import { Component, Renderer2 } from "@angular/core";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
rotateValue = 0;
dragPosition = { x: 0, y: 0 };
constructor(private renderer: Renderer2) {}
setRotate(value: string) {
this.rotateValue = Number(value);
this.renderer.setStyle(
document.querySelector(".example-box"),
"transform",
`rotate(${this.rotateValue}deg)`
);
}
}
app.component.html
<h1 class="text-center m-3">Drag And Drop Project</h1>
<hr>
<div class="row m-5">
<div class="col-sm-7">
<div class="example-boundary">
<div class="example-box" cdkDragBoundary=".example-boundary" cdkDrag>
I can only be dragged within the dotted container
</div>
</div>
</div>
<div class="col-sm-5">
<h4>SETTINGS</h4>
<ul class="list-group mb-3">
<li class="list-group-item d-flex justify-content-between lh-condensed">
<div>
<h6 class="my-0">Rotate the box</h6>
<input #rotation
type="range"
class="custom-range my-2"
min="-150" max="150"
[(ngModel)]="rotateValue"
[value]='rotateValue'
(change)="setRotate(rotation.value)"
>
</div>
<span id="grados" class="text-muted">{{rotateValue}}º</span>
</li>
</ul>
</div>
</div>
app.component.css
.example-box {
width: 140px;
height: 140px;
border: solid 1px #ccc;
color: rgba(0, 0, 0, 0.87);
cursor: move;
display: inline-flex;
justify-content: center;
align-items: center;
text-align: center;
background: #fff;
border-radius: 4px;
margin-right: 25px;
position: relative;
z-index: 1;
box-sizing: border-box;
padding: 10px;
transition: box-shadow 200ms cubic-bezier(0, 0, 0.2, 1);
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),
0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
.example-box:active {
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
}
.example-boundary {
width: 300px;
height: 500px;
max-width: 100%;
border: dotted #ccc 2px;
}
非常感谢您
您遇到的问题是 Cdk 拖动是使用 CSS transform
规则实现的,与您的自定义旋转完全一样。
因此,当应用于完全相同的 HTML 元素时,两者基本上是不兼容的。最后一个操作,无论是拖动还是旋转,都会覆盖另一个。
IMO 最简单的解决方法是将旋转的元素包装在可拖动的包装器中。
这里是更新后的 StackBlitz: https://stackblitz.com/edit/angular-ivy-ynzavj
编辑回顾:
在模板中,我将可旋转的 div 包装成可拖动的(我也使用 [ngStyle]
并完全避免了直接的 DOM 操作,这本身不是问题, 但没必要):
<div class="example-boundary">
<div class="box-draggable-wrapper" cdkDragBoundary=".example-boundary" cdkDrag>
<div class="example-box" [ngStyle]="{'transform':'rotate(' + rotateValue + 'deg)'}" >
I can only be dragged within the dotted container
</div>
</div>
</div>
box-draggable-wrapper
的CSS:
.box-draggable-wrapper {
width: 140px;
height: 140px;
display: block;
border: none;
}
组件被清理:
import { Component } from "@angular/core";
@Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
rotateValue = 0;
dragPosition = { x: 0, y: 0 };
constructor() {}
setRotate(value: string) {
this.rotateValue = +value;
}
}
好吧,我想您已经猜到了,拖动操作会扰乱框的样式,每次拖动框时,您之前的旋转值都会丢失。但是,与此同时,您也通过用新的旋转值覆盖其当前值来弄乱框样式,因此每次旋转框时框位置都会不断重置(删除 translate3D
值)。
您可以通过获取元素的当前样式并将其与您的样式合并,然后再将其设置回原位来轻松修复代码,这样可以解决位置问题,但是再次拖动框时仍然会丢失旋转值。
好消息是已经有一个open issue for this bug and a proposed fix,但坏消息是它们还在营业