dom 拖拽样式_实战Directive -- 图片拖拽显示

前言

Directive即Angular中常说的"指令",在Angular中通过如下代码:

@Directive

将一个类标注为指令(只指定selector是指令的最简化的定义)。这样我们在html模板中使用的时候就可以通过这样的方式:

<div MyDirective></div>

给使用了我们的指令的DOM中的元素添加自定义行为,如上述代码中的div。

本篇文章通过一个图片拖拽的例子让大家对Directive的使用有一个具体的了解。实现效果为:拖动一个图片到指定的框中,能显示图片。

拖放事件

首先我们需要对HTML中的拖放特性有一个简单的了解。拖放我们可以将它看作是一个传输数据的动作,它有一个(data source)以及一个目标(data target),也就是说拖放将数据从source传到了target。

拖放有如下对象/事件:

  • DataTransfer对象:我们通过这个对象来传递数据,使用方式为Event.dataTransfer。
  • draggable属性:即标签元素设置draggable=true才有效果。
  • ondragstart 事件:当拖拽元素开始被拖拽的时候触发的事件,此事件作用在被拖曳元素上。
  • ondragenter 事件:当拖曳元素进入目标元素的时候触发的事件,此事件作用在目标元素上。
  • ondragover 事件:拖拽元素在目标元素上移动的时候触发的事件,此事件作用在目标元素上。
  • ondragleave 事件:拖拽元素在目标元素上移动的时候触发的事件,此事件作用在目标元素上。
  • ondrop 事件:被拖拽的元素在目标元素上同时鼠标放开触发的事件,此事件作用在目标元素上。
  • ondragend 事件:当拖拽完成后触发的事件,此事件作用在被拖曳元素上。
  • event.preventDefault() 方法:阻止默认的事件方法等执行。在ondragover中一定要执行preventDefault(),否则ondrop事件不会被触发。另外,如果是从其他应用软件或是文件中拖东西进来,尤其是图片的时候,默认的动作是显示这个图片或是相关信息,并不是真的执行drop。此时需要用用document的ondragover事件把它直接干掉。
  • event.setDataTransfer.effectAllowed 属性:就是拖拽的效果。
  • evetn.setDataTransfer.setDragImage() 方法:指定图片或者文档元素做拖动时的视觉效果。

上述是在HTML5中的拖放事件说明,在Angular稍显区别:

ca3198e23c2fdce578c88248e27d4243.png

在Web Storm(弃坑Vscode :))的任意html文件中,我们利用IDE的提示可以看到,Angular中与HTML5的拖放事件也是一一对应的。

Start

新建工程

ng new DragDemo

加入Angular Material[可选]

这里呢直接使用Angular Material这个UI,大家可加可不加,自从经历调博客园样式事件之后,能不CSS则不CSS。

ng add @angular/material

创建指令文件

执行

ng g d drag-drop

生成指令文件与指令测试文件。如果你导入了Angular Material的话,再创建一个管理Angular Material的模块文件。

此时目录如下:

app/
├── app.component.css
├── app.component.html
├── app.component.spec.ts
├── app.component.ts
├── app.module.ts
├── app-routing.module.ts
├── drag-drop.directive.spec.ts
└── drag-drop.directive.ts //指令文件

0 directories, 8 files

创建HTML

先画一个放置图片的框,

f5d4485b07c25a9ed4038ce4258edaea.png

然后加上appDragDrop指令。最终的html代码如下:

<div id="container" [ngClass]="{'bg-border':true, 'dragEnterBg': isDragging}"
     appDragDrop (dropHandler)="onDropHandler($event)"       (dragHandler)="onDragHandler($event)">
  <img [src]="imageSrc"/>
</div>

其中[ngClass]可以将CSS样式与ts代码绑定起来,这里的dragEnterBg就是灰色背景,当isDragging为true的时候,背景就会变灰。

dropHandler是放下的处理事件,就将图片数据传输过来。dragHandler是实时刷新isDragging变量的值。

指令

指令代码如下:

import {Directive, Output, HostListener, EventEmitter, Input, OnInit, Host} from '@angular/core';

@Directive({
  selector: '[appDragDrop]',
})
export class DragDropDirective {
  @Output() dropHandler: EventEmitter<any> = new EventEmitter();
  @Output() dragHandler: EventEmitter<any> = new EventEmitter();

  public isDragging: boolean;
  public isInvalid: boolean;
  public imageSrc: string;

  @HostListener('dragover') onDragOver(e) {
    return false;
  }
  @HostListener('dragenter') onDragEnter() {
    this.isDragging = true;
    this.dragHandler.emit(this.isDragging);
  }

  @HostListener('dragleave') onDragLeave() {
    this.isDragging = false;
    this.dragHandler.emit(this.isDragging);
  }

  @HostListener('drop', ['$event']) onDrop(e) {
    e.preventDefault();
    this.isDragging = false;
    this.dragHandler.emit(this.isDragging);
    this.handleInputChange(e);
  }

  handleInputChange(e) {
    console.log(e);
    const file = e.dataTransfer ? e.dataTransfer.files[0] : 'null';
    const pattern = /.*png/;
    const reader = new FileReader();
    this.isInvalid = false;

    if (!file.type.match(pattern)) {
      this.isInvalid = true;
      console.log('invalid format');
      return this.dropHandler.emit({
        event: e,
        isInvalid: this.isInvalid
      });
    }

    reader.onload = this.handleReaderLoaded.bind(this);
    reader.readAsDataURL(file);
  }

  handleReaderLoaded(e) {
    const reader = e.target;
    this.imageSrc = reader.result;
    this.dropHandler.emit({ event: e, invalidFlag: this.isInvalid });
  }
}

通过FileReader来读取文件。并通过@Output将数据传输到指令附着的标签上。@HostListener即是监听指令附着在的标签中的事件。

拖放操作放下的效果如图:

52eb124ac5c894485ef830eeb92506df.png

最后

喜欢这篇文章欢迎关注这个专栏,日常笔记都会同步到我的公众号Plus技术栈上。

需要源码的同学移步:专栏简介

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值