Directly on the code, annotations, simple small function, good understanding!

import { Directive,ElementRef,HostBinding,OnInit,Input } from '@angular/core';
import { fromEvent, merge, animationFrameScheduler, generate } from 'rxjs';
import { map, tap, throttleTime, debounceTime } from 'rxjs/operators';
import { TouchService } from './touch.service';
@Directive({
  selector: '[dragmove]'
})
export class DragmoveDirective implements OnInit {
  @HostBinding('style.left.px') _left: number;
  @HostBinding('style.top.px') _top: number;
  @HostBinding('style.position') _position: string = 'absolute'; _cacheKey: string; @Input()set dragmove(val: string) {
    if (val) {
      this._cacheKey = val;
      let p = localStorage.getItem(val);
      if (p) {
        let point = JSON.parse(p);
        this._left = point.left;
        this._top = point.top;
      }
    }
  }
  isStart: boolean = false;
  constructor(public ele: ElementRef) {}
  ngOnInit() {
    this.onDrag();
  }
  onDrag() {
    const mousemove = fromEvent(this.ele.nativeElement, 'mousemove');
    const touchmove = fromEvent(this.ele.nativeElement, 'touchmove');
    const nodeRect = this.ele.nativeElement.getBoundingClientRect();
    const rect = {
      height: nodeRect.height,
      width: nodeRect.width
    };
    const move = merge(
      mousemove.pipe(
        map((evt: MouseEvent) => {
          return {
            x: evt.clientX,
            y: evt.clientY
          };
        })
      ),
      touchmove.pipe(
        map((evt: TouchEvent) => {
          return {
            x: evt.touches[0].pageX,
            y: evt.touches[0].pageY
          };
        })
      ),
      animationFrameScheduler
    ).pipe(
      map(res => {
        this._top = res.y - rect.height / 2;
        this._left = res.x - rect.width / 2;
        return {
          left: this._left,
          top: this._top
        };
      }),
      debounceTime(300),
      tap(res => this._cacheKey && localStorage.setItem(this._cacheKey, JSON.stringify(res))) ); move.subscribe((res: any) => {}); }}Copy the code

use

<! --> <div class="cube"dragmove></div> <! --> <div class="cube" dragmove="dragmove-1"></div>

Copy the code
  • Super compact gesture control
import {
  Directive,
  OnInit,
  ElementRef,
  Input,
  Output,
  EventEmitter
} from '@angular/core';
import { fromEvent } from 'rxjs';
import { map, switchMap, takeUntil, debounceTime, tap } from 'rxjs/operators';
@Directive({
  selector: '[swipeMove]'
})
exportSwipeMoveDirective implements OnInit {// SwipeMoveDirective implements OnInit @output () swipeMove: Emitter<any> = New EventEmitter(); len: number = 10; constructor(public ele: ElementRef) {}ngOnInit() {
    this.handler(this.ele.nativeElement);
  }
  handler(ele: Element) {
    let start = fromEvent(ele, 'touchstart');
    let move = fromEvent(ele, 'touchmove');
    let end = fromEvent(ele, 'touchend');
    document.oncontextmenu = () => false;
    let t = (evt: TouchEvent) => ({
      x: evt.touches[0].pageX,
      y: evt.touches[0].pageY,
      t: new Date().getTime(),
      type: evt.type }); // |start---------------------------- // -----------|move------------------ // --------------------------|end---- // | -- -- -- -- -- -- -- -- -- -- -- -- -- - | start. Pipe (/ / neat map (t), switchMap (poi1 = > move. The pipe (/ / neat map (t), / / until the end takeUntil (end), X, dy: end.y-poi1. y, dt: end.t-poi1. t})), map(res => {// x is leadingif (Math.abs(res.dx) > Math.abs(res.dy)) {
                if (res.dx > this.len) return 'right';
                else if (res.dx < -this.len) return 'left';
                else return 'tap';
              } else {
                if (res.dy > this.len) return 'down';
                else if (res.dy < -this.len) return 'up';
                else return 'tap'; } }), tap(res=>this.swipeMove.next(res)), debounceTime(100) ) ) ) .subscribe(res => {}); }}Copy the code
<! --left right up down tap-->
<div class="cube" (swipeMove) ="swipeMove($event)"></div>
Copy the code

summary

The power of RXJS streaming responsive programming