RXJS DnD

by balefrost

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.8.1/rxjs.umd.min.js"></script>
<style>
  .draggable {
    position:absolute; 
    background-color: pink; 
    height: 200px; 
    width: 100px;
    cursor: pointer; 
  }
</style>

<div class="draggable">
</div>

JavaScript

const box = document.querySelector('.draggable');

const mousedown$ = rxjs.fromEvent(box, 'mousedown');
const mousemove$ = rxjs.fromEvent(document, 'mousemove');
const mouseup$ = rxjs.fromEvent(box, 'mouseup');

const drag$ = mousedown$.pipe(
  rxjs.switchMap((start) => {
    return mousemove$.pipe(
      rxjs.map((move) => {
        move.preventDefault();
        return {
          left: move.clientX - start.offsetX,
          top: move.clientY - start.offsetY,
        };
      }),
      rxjs.takeUntil(mouseup$)
    );
  })
);

const position$ = drag$.pipe(rxjs.subscribeOn(rxjs.animationFrameScheduler));

position$.subscribe((pos) => {
  box.style.top = `${pos.top}px`;
  box.style.left = `${pos.left}px`;
});