Angular7 Drag and Drop
完整代码在最后,下面讲解以此代码为例
1.环境配置
1.1 安装@angular/material、@angular/cdk
cnpm install --save @angular/material @angular/cdk
1.2 app.modules.ts导入
import { dragdropmodule } from '@angular/cdk/drag-drop';
imports: [
...
dragdropmodule
]
2.功能实现
2.1 拖拽
html编辑如下代码即可:
<div cdkdrag class="drag-box"
drag me
</div>
2.2 排序
html:
<h3>列表排序</h3>
<div class="box-list" cdkdroplist (cdkdroplistdropped)="drop($event)">
<div class="drag-box" *ngfor="let customer of customers" cdkdrag>
{{customer.name}}
</div>
</div>
ts:
import { ...cdkdragdrop, moveiteminarray } from '@angular/cdk/drag-drop';
customers = [
{ name: 'adam', age: 23 },
{ name: 'jack', age: 27 },
{ name: 'katherin', age: 26 },
{ name: 'john', age: 30 },
{ name: 'watson', age: 42 },
];
drop(event: cdkdragdrop<string[]>) {
console.log('列表排序:', event, this.customers);
moveiteminarray(this.customers, event.previousindex, event.currentindex);
}
执行如下操作:
打印结果:
2.3 横向排序
html:
<h3>横向排序</h3>
<div class="box-list-horizontal" cdkdroplist cdkdroplistorientation="horizontal"
(cdkdroplistdropped)="drop($event)">
<div class="drag-box" *ngfor="let customer of customers" cdkdrag>
{{customer.name}}
</div>
</div>
2.4 添加动画效果
为了设置动画,我们定义了一个以transform属性为目标的转换。拖放cdk支持动画:
--对列表中的元素进行拖动排序时的动画=> .cdk-drag
.cdk-drag {
transition: transform 100ms ease;
}
--从动画的位置到最终把它放在列表的位置上时的动画=> .cdk-drag-animating
.cdk-drag-animating {
transition: transform 300ms ease;
}
2.5 占位符元素 placeholder
默认占位符
使用.cdk-drag-placeholder来显示占位符元素,而不是实际的元素,因为它是在cdkdroplist中拖动的。默认情况下,这看起来与正在排序的元素完全相同。
.cdk-drag-placeholder {
background: #ccc;
border: dotted 1px #999;
transition: transform 500ms ease;
}
拖拽时效果如下图:
自定义占位符
使用*cdkdragplaceholder指令,我们可以用一个自定义的占位符来代替默认的占位符
html:
<div class="box-list customph" cdkdroplist (cdkdroplistdropped)="drop($event)">
<div class="drag-box draglist" *ngfor="let customer of customers" cdkdrag >
<div class="box-custom-placeholder" *cdkdragplaceholder></div>
{{customer.name}}
</div>
</div>
css:
// 自定义占位符
.customph{
.box-custom-placeholder {
height: 28px;
width: 100px;
background: #fff;
border: dotted 1px #0084ff;
transition: transform 200ms ease;
}
&.box-list.cdk-drop-list-dragging .drag-box:not(.cdk-drag-placeholder) {
transition: transform 500ms ease;
}
}
2.6 预览
当提取并拖动cdkdrag元素时,可以看到预览元素。默认情况下,预览元素看起来与被拖动的元素完全相同。
使用.cdk-drag-preview来定义预览css:
// 预览
.cdk-drag-preview {
height: 28px;
width: 100px;
box-shadow: 0 3px 3px -3px #0084ff;
}
我们还需要使用*cdkdragpreview提供一个自定义模板:
<div cdkdroplist class="box-list" (cdkdroplistdropped)="drop($event)">
<div class="drag-box draglist" *ngfor="let customer of customers" cdkdrag>
{{customer.name}}
<p *cdkdragpreview>age: {{customer.age}}</p>
</div>
</div>
2.7 多个列表之间拖拽
我们可以使用cdkdroplistconnectedto属性将一个或多个cdkdroplist连接到一起。然后设置cdkdroplistdata和cdkdragdata,将数据与cdkdroplist和cdkdrag关联起来。
html:
<div class="box-list" cdkdroplist #inactivelist="cdkdroplist" id="inactive customers"
[cdkdroplistdata]="inactivecustomers" [cdkdroplistconnectedto]="[activelist]"
(cdkdroplistdropped)="drop1($event)">
<div class="drag-box draglist"
[cdkdragdata]="customer"
*ngfor="let customer of inactivecustomers"
cdkdrag>
{{customer.name}}
</div>
</div>
<div class="box-list" cdkdroplist #activelist="cdkdroplist" id="active customers"
[cdkdroplistdata]="activecustomers" [cdkdroplistconnectedto]="[inactivelist]"
(cdkdroplistdropped)="drop1($event)">
<div class="drag-box draglist"
[cdkdragdata]="customer"
*ngfor="let customer of activecustomers"
cdkdrag>
{{customer.name}}
</div>
</div>
ts:
import { ...transferarrayitem } from '@angular/cdk/drag-drop';
inactivecustomers = [
{name: 'jack', age: 18},
{name: 'katherin', age: 16},
{name: 'adam', age: 36}
];
activecustomers = [
{name: 'john', age: 10},
{name: 'watson', age: 24}
];
drop1(event: cdkdragdrop<string[]>) {
console.log('拖拽事件:event', event);
if (event.previouscontainer === event.container) {
console.log('拖拽事件',
`> 拖 '${event.item.data}' 到 '${event.container.id}'`);
moveiteminarray(event.container.data, event.previousindex, event.currentindex);
} else {
console.log('拖拽事件',
`> 拖 '${event.item.data}' 到 '${event.container.id}'`);
transferarrayitem(
event.previouscontainer.data, event.container.data,
event.previousindex, event.currentindex);
}
}
执行如下操作:
打印结果:
cdkdroplistgroup
cdkdroplistgroup指令的范围比cdkdroplist要大一级。cdkdroplistgroup可以包含多个cdkdroplist。而且当cdkdroplistgroup包含多个cdkdroplist的时候,这些cdkdroplist直接是相互connect的(cdkdroplist就不用去写cdkdroplistconnectedto属性了)。
<div cdkdroplistgroup>
<div class="box-list" cdkdroplist id="inactive customers"
[cdkdroplistdata]="inactivecustomers"
(cdkdroplistdropped)="drop1($event)">
<div class="drag-box draglist" [cdkdragdata]="customer"
*ngfor="let customer of inactivecustomers" cdkdrag>
{{customer.name}}
</div>
</div>
<div class="box-list" cdkdroplist id="active customers"
[cdkdroplistdata]="activecustomers"
(cdkdroplistdropped)="drop1($event)">
<div class="drag-box draglist"
[cdkdragdata]="customer"
*ngfor="let customer of activecustomers"
cdkdrag>
{{customer.name}}
</div>
</div>
</div>
2.8 事件监听
drag event handlers
– cdkdragstarted: 当用户开始拖动时发出。
– cdkdragended: 当用户停止拖动时发出。
– cdkdragentered: 将item移动到新容器中时发出。
– cdkdragexited: 将item移出当前容器时发出。
drop event handlers
– cdkdroplistdropped: emits when an item was dropped inside the container.
– cdkdroplistentered: emits when a new item is dragged into this container.
– cdkdroplistexited: emits when an item is dragged from this container into another container.
cdkdragstarted、cdkdragended、cdkdragmoved
html:
<h3>事件监听</h3>
<div cdkdrag class="drag-box"
(cdkdragstarted)="dragstarted($event)"
(cdkdragended)="dragended($event)"
(cdkdragmoved)="dragmoved($event)"
>
drag me
</div>
<p>{{state}} {{position}}</p>
ts:
import { cdkdragend, cdkdragstart, cdkdragmove... } from '@angular/cdk/drag-drop';
dragstarted(event: cdkdragstart) {
this.state = '拖拽开始';
console.log('拖拽开始');
}
dragended(event: cdkdragend) {
this.state = '拖拽结束';
console.log('拖拽结束');
}
dragmoved(event: cdkdragmove) {
console.log('dragmoved');
this.position = `> position x: ${event.pointerposition.x} - y: ${event.pointerposition.y}`;
}
cdkdroplistentered、cdkdroplistexited、cdkdragentered、cdkdragexited
html:
<div class="box-list" cdkdroplist #inactivelist="cdkdroplist" id="inactive customers"
[cdkdroplistdata]="inactivecustomers" [cdkdroplistconnectedto]="[activelist]"
(cdkdroplistdropped)="drop1($event)"
(cdkdroplistentered)="droplistentered($event)" (cdkdroplistexited)="droplistexited($event)">
<div class="drag-box draglist" [cdkdragdata]="customer"
(cdkdragentered)="dragentered($event)" (cdkdragexited)="dragexited($event)"
*ngfor="let customer of inactivecustomers"
cdkdrag>
{{customer}}
</div>
</div>
<div class="box-list" cdkdroplist #activelist="cdkdroplist" id="active customers"
[cdkdroplistdata]="activecustomers" [cdkdroplistconnectedto]="[inactivelist]"
(cdkdroplistdropped)="drop1($event)">
<div class="drag-box draglist"
[cdkdragdata]="customer"
*ngfor="let customer of activecustomers"
cdkdrag>
{{customer}}
</div>
</div>
ts:
import { ...cdkdragenter, cdkdragexit} from '@angular/cdk/drag-drop';
dragentered(event: cdkdragenter) {
console.log(`drag:把 '${event.item.data}' 拖进 '${event.container.id}' `);
}
dragexited(event: cdkdragexit) {
console.log(`drag:把 '${event.item.data}' 从 '${event.container.id}' 中拖出 `);
}
droplistentered(event: cdkdragenter) {
console.log(`drop:'${event.container.id}' 中拖进了 '${event.item.data}'`);
}
droplistexited(event: cdkdragexit) {
console.log(`drop:从 '${event.container.id}' 中拖出 '${event.item.data}'`);
}
执行如下操作
打印结果:
再執行如下操作:
打印结果:
cdkdroplistsorted
拖拽过程中交换item的时候回调
<div class="box-list" cdkdroplist #activelist="cdkdroplist" id="active customers"
[cdkdroplistdata]="activecustomers" [cdkdroplistconnectedto]="[inactivelist]"
(cdkdroplistdropped)="drop1($event)"
(cdkdroplistsorted)="droplistsorted($event)">
<div class="drag-box draglist"
[cdkdragdata]="customer"
*ngfor="let customer of activecustomers"
cdkdrag>
{{customer.name}}
</div>
</div>
ts:
droplistsorted(event: cdkdroplist) {
console.log('sorted:', event);
}
2.9 属性
cdkdroplistenterpredicate
enterpredicate: (drag: cdkdrag, drop: cdkdroplist) => boolean
指定哪些item是可以拖拽到当前容器
html:
<div class="box-list" cdkdroplist #activelist="cdkdroplist" id="active customers"
[cdkdroplistdata]="activecustomers" [cdkdroplistconnectedto]="[inactivelist]"
(cdkdroplistdropped)="drop1($event)" [cdkdroplistenterpredicate]="predicate">
<div class="drag-box draglist"
[cdkdragdata]="customer"
*ngfor="let customer of activecustomers"
cdkdrag>
{{customer.name}}
</div>
</div>
ts:
import { ...cdkdrag, cdkdroplist } from '@angular/cdk/drag-drop';
predicate(drag: cdkdrag, drop: cdkdroplist) {
console.log('predicate:', drag, drop);
return drag.data.age >= 18;
}
cdkdrag属性:
cdkdroplist属性
代码:
html:
<div class="drag-box" cdkdrag>
drag me
</div>
<h3>锁定方向</h3>
<div class="drag-box" cdkdraglockaxis="y" cdkdrag>
only up/down
</div>
<div class="drag-box" cdkdraglockaxis="x" cdkdrag>
only left/right
</div>
<h3>事件监听</h3>
<div cdkdrag class="drag-box"
(cdkdragstarted)="dragstarted($event)"
(cdkdragended)="dragended($event)"
(cdkdragmoved)="dragmoved($event)"
>
drag me
</div>
<p>{{state}} {{position}}</p>
<h3>拖拽handler</h3>
<div class="drag-box-with-handler drag-box" cdkdrag>
<div class="box-handler" cdkdraghandle>
点我拖拽
</div>
</div>
<h3>列表排序</h3>
<div class="box-list" cdkdroplist (cdkdroplistdropped)="drop($event)">
<div class="drag-box draglist" *ngfor="let customer of customers" cdkdrag>
{{customer.name}}
</div>
</div>
<h3>横向排序</h3>
<div class="box-list-horizontal" cdkdroplist cdkdroplistorientation="horizontal"
(cdkdroplistdropped)="drop($event)">
<div class="drag-box draglisth" *ngfor="let customer of customers" cdkdrag>
{{customer.name}}
</div>
</div>
<h3>placeholder 默认占位符元素</h3>
<div>使用.cdk-drag-placeholder来显示占位符元素,而不是实际的元素,
因为它是在cdkdroplist中拖动的。默认情况下,占位符元素看起来与正在排序的元素完全相同。</div>
<div class="box-list defplaceh" cdkdroplist (cdkdroplistdropped)="drop($event)">
<div class="drag-box draglist" *ngfor="let customer of customers" cdkdrag>
{{customer.name}}
</div>
</div>
<h3>placeholder 自定义占位符元素</h3>
<div>使用*cdkdragplaceholder指令,我们可以用一个自定义的占位符来代替默认的占位符</div>
<div class="box-list customph" cdkdroplist (cdkdroplistdropped)="drop($event)">
<div class="drag-box draglist" *ngfor="let customer of customers" cdkdrag >
<div class="box-custom-placeholder" *cdkdragplaceholder></div>
{{customer.name}}
</div>
</div>
<h3>预览 preview</h3>
<div>当提取并拖动cdkdrag元素时,可以看到预览元素。默认情况下,
预览元素看起来与被拖动的元素完全相同。</div>
<div cdkdroplist class="box-list" (cdkdroplistdropped)="drop($event)">
<div class="drag-box draglist" *ngfor="let customer of customers" cdkdrag>
{{customer.name}}
<p *cdkdragpreview>age: {{customer.age}}</p>
</div>
</div>
<h3>两个列表间拖放</h3>
<div class="twolist">
<div class="box-list" cdkdroplist #inactivelist="cdkdroplist" id = "inactive customers"
[cdkdroplistdata]="inactivecustomers" [cdkdroplistconnectedto]="[activelist]"
(cdkdroplistdropped)="drop1($event)"
(cdkdroplistentered)="droplistentered($event)" (cdkdroplistexited)="droplistexited($event)"
[cdkdroplistenterpredicate]="predicate"
>
<div class="drag-box draglist" [cdkdragdata]="customer"
(cdkdragentered)="dragentered($event)" (cdkdragexited)="dragexited($event)"
*ngfor="let customer of inactivecustomers;islast as last"
cdkdrag>
{{customer.name}}
</div>
</div>
<div class="box-list" cdkdroplist #activelist="cdkdroplist" id = "active customers"
[cdkdroplistdata]="activecustomers" [cdkdroplistconnectedto]="[inactivelist]"
(cdkdroplistdropped)="drop1($event)" [cdkdroplistenterpredicate]="predicate"
(cdkdroplistsorted)="droplistsorted($event)"
>
<div
class="drag-box draglist"
[cdkdragdata]="customer"
*ngfor="let customer of activecustomers"
cdkdrag>
{{customer.name}}
</div>
</div>
</div>
<!-- <h3>两个列表间拖放 cdkdroplistgroup</h3>
<div class="twolist" cdkdroplistgroup>
<div class="box-list" cdkdroplist id = "inactive customers"
[cdkdroplistdata]="inactivecustomers"
(cdkdroplistdropped)="drop1($event)">
<div class="drag-box draglist" [cdkdragdata]="customer"
*ngfor="let customer of inactivecustomers" cdkdrag>
{{customer.name}}
</div>
</div>
<div class="box-list" cdkdroplist id = "active customers"
[cdkdroplistdata]="activecustomers"
(cdkdroplistdropped)="drop1($event)">
<div
class="drag-box draglist"
[cdkdragdata]="customer"
*ngfor="let customer of activecustomers"
cdkdrag>
{{customer.name}}
</div>
</div>
</div> -->
ts:
import { component, oninit } from '@angular/core';
import { cdkdragend, cdkdragstart, cdkdragmove,
cdkdragdrop, cdkdragenter, cdkdragexit, moveiteminarray,
transferarrayitem, cdkdrag, cdkdroplist } from '@angular/cdk/drag-drop';
@component({
selector: 'app-drag-drop',
templateurl: './drag-drop.component.html',
styleurls: ['./drag-drop.component.scss']
})
export class dragdropcomponent implements oninit {
state = '';
position = '';
customers = [
{ name: 'adam', age: 23 },
{ name: 'jack', age: 27 },
{ name: 'katherin', age: 26 },
{ name: 'john', age: 30 },
{ name: 'watson', age: 42 },
];
inactivecustomers = [
{name: 'jack', age: 18},
{name: 'katherin', age: 16},
{name: 'adam', age: 36}
];
activecustomers = [
{name: 'john', age: 10},
{name: 'watson', age: 24}
];
constructor() { }
ngoninit() {
}
dragstarted(event: cdkdragstart) {
this.state = '拖拽开始';
console.log('拖拽开始');
}
dragended(event: cdkdragend) {
this.state = '拖拽结束';
console.log('拖拽结束');
}
dragmoved(event: cdkdragmove) {
console.log('dragmoved');
this.position = `> position x: ${event.pointerposition.x} - y: ${event.pointerposition.y}`;
}
dragentered(event: cdkdragenter) {
console.log(`drag:把 '${event.item.data}' 拖进 '${event.container.id}' `);
}
dragexited(event: cdkdragexit) {
console.log(`drag:把 '${event.item.data}' 从 '${event.container.id}' 中拖出 `);
}
droplistentered(event: cdkdragenter) {
console.log(`drop:'${event.container.id}' 中拖进了 '${event.item.data}'`);
}
droplistexited(event: cdkdragexit) {
console.log(`drop:从 '${event.container.id}' 中拖出 '${event.item.data}'`);
}
drop(event: cdkdragdrop<string[]>) {
console.log('列表排序:', event, this.customers);
moveiteminarray(this.customers, event.previousindex, event.currentindex);
}
drop1(event: cdkdragdrop<string[]>) {
console.log('拖拽事件:event', event);
if (event.previouscontainer === event.container) {
console.log('拖拽事件',
`> 拖 '${event.item.data}' 到 '${event.container.id}'`);
moveiteminarray(event.container.data, event.previousindex, event.currentindex);
} else {
console.log('拖拽事件',
`> 拖 '${event.item.data}' 到 '${event.container.id}'`);
transferarrayitem(
event.previouscontainer.data, event.container.data,
event.previousindex, event.currentindex);
}
}
predicate(drag: cdkdrag, drop: cdkdroplist) {
console.log('predicate:', drag, drop);
return drag.data.age >= 18;
}
droplistsorted(event: cdkdroplist) {
console.log('sorted:', event);
}
}
app.module.ts
import { browsermodule } from '@angular/platform-browser';
import { ngmodule } from '@angular/core';
import { scrollingmodule } from '@angular/cdk/scrolling';
import { matcardmodule } from '@angular/material';
import { dragdropmodule } from '@angular/cdk/drag-drop';
// import { viewport_ruler_provider } from '@angular/cdk/scrolling';
import { approutingmodule } from './app-routing.module';
import { appcomponent } from './app.component';
import { virtualscrollcomponent } from './virtual-scroll/virtual-scroll.component';
import { dragdropcomponent } from './drag-drop/drag-drop.component';
@ngmodule({
declarations: [
appcomponent,
virtualscrollcomponent,
dragdropcomponent
],
imports: [
browsermodule,
approutingmodule,
scrollingmodule,
matcardmodule,
dragdropmodule
],
providers: [],
bootstrap: [appcomponent]
})
export class appmodule { }
css:
.drag-box{
height: 100px;
width: 100px;
border: 1px solid #000;
}
.box-handler{
width: 100%;
height: 20px;
background: #ccc;
}
.draglist{
height: 28px;
margin: 5px 0;
}
.draglisth{
display: inline-block;
margin: 0 5px;
height: 28px;
width: 55px;
}
// 动画效果
// .cdk-drag {
// transition: transform 100ms ease;
// }
.cdk-drag-animating {
transition: transform 300ms ease;
}
// 占位符 默认 placeholder
.defplaceh .cdk-drag-placeholder {
background: #ccc;
border: dotted 1px #999;
transition: transform 500ms ease;
}
// 自定义占位符
.customph{
.box-custom-placeholder {
height: 28px;
width: 100px;
background: #fff;
border: dotted 1px #0084ff;
transition: transform 200ms ease;
}
&.box-list.cdk-drop-list-dragging .drag-box:not(.cdk-drag-placeholder) {
transition: transform 500ms ease;
}
}
// 预览
.cdk-drag-preview {
height: 28px;
width: 100px;
box-shadow: 0 3px 3px -3px #0084ff;
}
.twolist{
overflow: hidden;
>div{
float: left;
margin: 10px;
}
}
上一篇: Python socket的客户端
推荐阅读
-
详细介绍通过HTML5的Drag和Drop生成拓扑图片Base64信息的案例
-
Drop user cascade failed ORA-00604 ORA-02429 处理一例
-
HTML5拖拽功能drag_html/css_WEB-ITnose
-
jQuery使用drag效果实现*拖拽div_jquery
-
学习drag and drop js实现代码经典之作_javascript技巧
-
mysql drop database删除数据库命令实例讲解
-
mysql drop database删除数据库命令实例讲解
-
Mysql 删除数据库drop database详细介绍
-
drop,truncate与delete的区别
-
Mysql 删除数据库drop database详细介绍