手写一个性能不错的排序

2023 年 02 月 27 日

Js基础
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <style>
    .container {
      width: 400px;
      margin: 0 auto;
      background: pink;
      padding: 20px;
    }

    .list {
      display: flex;
      flex-wrap: wrap;
      gap: 15px;
    }

    .list-item {
      width: 100px;
      height: 100px;
      border: 1px solid #000;
      background: #fff;
      line-height: 100px;
      text-align: center;
      list-style: none;
      user-select: none;
    }

    .active {
      background: skyblue;
    }

    .clone-item {
      position: fixed;
      left: 0;
      top: 0;
      z-index: 1;
      width: 100px;
      height: 100px;
      border: 1px solid #000;
      background: #fff;
      line-height: 100px;
      text-align: center;
      list-style: none;
      user-select: none;
      pointer-events: none;
      opacity: 0.8;
    }
  </style>

</head>

<body>
  <div class="container">
    <ul class="list">
      <li class="list-item">111</li>
      <li class="list-item">222</li>
      <li class="list-item">333</li>
      <li class="list-item">444</li>
      <li class="list-item">555</li>
      <li class="list-item">666</li>
      <li class="list-item">777</li>
      <li class="list-item">888</li>
      <li class="list-item">999</li>
    </ul>
  </div>

  <script>
    class Draggable {
      containerElement = null;
      rectList = [];
      isPointerDown = false;
      drag = { element: null, index: 0, firstIndex: 0 };
      clone = { element: null, x: 0, y: 0 };
      diff = { x: 0, y: 0 };
      referenceElement = null;
      lastPointerMove = { x: 0, y: 0 };

      constructor(options) {
        console.log('options: ', options.element);
        this.containerElement = options.element;
        this.init();
      }
      init() {
        this.getRectList();
        this.bindEventListener();
      }

      getRectList() {
        this.rectList.length = 0;
        for (const item of this.containerElement.children) {
          this.rectList.push(item.getBoundingClientRect());
        }
      }

      onPointerDown(e) {
        console.log('e: ', e);
        if (e.pointerType === 'mouse' && e.button !== 0) {
          return;
        }
        if (e.target === this.containerElement) {
          return;
        }

        this.isPointerDown = true;

        this.containerElement.setPointerCapture(e.pointerId);

        this.lastPointerMove.x = e.clientX;
        this.lastPointerMove.y = e.clientY;

        this.drag.element = e.target;
        this.drag.element.classList.add('active');

        const index = [].indexOf.call(this.containerElement.children, this.drag.element);

        this.drag.index = index;
        this.drag.firstIndex = index;

        this.clone.x = this.rectList[index].left;
        this.clone.y = this.rectList[index].top;

        this.clone.element = this.drag.element.cloneNode(true);
        document.body.appendChild(this.clone.element);

        this.clone.element.style.transition = 'none';
        this.clone.element.className = 'clone-item';
        this.clone.element.style.transform = 'translate3d(' + this.clone.x + 'px, ' + this.clone.y + 'px, 0)';

        for (const item of this.containerElement.children) {
          item.style.transition = 'transform 500ms';
        }
      }
      onPointerMove(e) {
        if (this.isPointerDown) {
          this.diff.x = e.clientX - this.lastPointerMove.x;
          this.diff.y = e.clientY - this.lastPointerMove.y;

          this.lastPointerMove.x = e.clientX;
          this.lastPointerMove.y = e.clientY;

          this.clone.x += this.diff.x;
          this.clone.y += this.diff.y;

          this.clone.element.style.transform = 'translate3d(' + this.clone.x + 'px, ' + this.clone.y + 'px, 0)';

          for (let i = 0; i < this.rectList.length; i++) {
            if (i !== this.drag.index && e.clientX > this.rectList[i].left && e.clientX < this.rectList[i].right &&
              e.clientY > this.rectList[i].top && e.clientY < this.rectList[i].bottom) {
              if (this.drag.index < i) {
                for (let j = this.drag.index; j < i; j++) {
                  if (j < this.drag.firstIndex) {
                    this.containerElement.children[j].style.transform = 'translate3d(0px, 0px, 0)';
                  } else {
                    const x = this.rectList[j].left - this.rectList[j + 1].left;
                    const y = this.rectList[j].top - this.rectList[j + 1].top;
                    this.containerElement.children[j + 1].style.transform = 'translate3d(' + x + 'px, ' + y + 'px, 0)';
                  }
                }
                this.referenceElement = this.containerElement.children[i + 1];
              } else if (this.drag.index > i) {
                for (let j = i; j < this.drag.index; j++) {
                  if (this.drag.firstIndex <= j) {
                    this.containerElement.children[j + 1].style.transform = 'translate3d(0px, 0px, 0)';
                  } else {
                    const x = this.rectList[j + 1].left - this.rectList[j].left;
                    const y = this.rectList[j + 1].top - this.rectList[j].top;
                    this.containerElement.children[j].style.transform = 'translate3d(' + x + 'px, ' + y + 'px, 0)';
                  }
                }
                this.referenceElement = this.containerElement.children[i];
              }
              const x = this.rectList[i].left - this.rectList[this.drag.firstIndex].left;
              const y = this.rectList[i].top - this.rectList[this.drag.firstIndex].top;
              this.drag.element.style.transform = 'translate3d(' + x + 'px, ' + y + 'px, 0)';
              this.drag.index = i;
              break;
            }
          }
        }
      }
      onPointerUp(e) {
        if (this.isPointerDown) {
          this.isPointerDown = false;

          this.drag.element.classList.remove('active');
          this.clone.element.remove();

          for (const item of this.containerElement.children) {
            item.style.transition = 'none';
            item.style.transform = 'translate3d(0px, 0px, 0px)';
          }

          if (this.referenceElement !== null) {
            this.containerElement.insertBefore(this.drag.element, this.referenceElement);
          }
        }
      }
      bindEventListener() {
        this.containerElement.addEventListener('pointerdown', this.onPointerDown.bind(this));
        this.containerElement.addEventListener('pointermove', this.onPointerMove.bind(this));
        this.containerElement.addEventListener('pointerup', this.onPointerUp.bind(this));

        window.addEventListener('scroll', this.getRectList.bind(this));
        window.addEventListener('resize', this.getRectList.bind(this));
        window.addEventListener('orientationchange', this.getRectList.bind(this));
      }
    }
    new Draggable({
      element: document.querySelector('.list')
    });
  </script>
</body>

</html>

交流专区 文明发言

手写一个性能不错的排序

2023 年 02 月 27 日

0

Like

0

Download

28

Viewed