两个拼图拖动互换位置怎么实现?

场景是这样,移动端页面,有两个3X3的拼图A和B,共18块碎片打乱填充,任意拖动复原拼图。
我的想法是,通过touch相关事件拖动,然后交换拖动元素的src和目标元素的src。但是尝试后发现由于拖动的事件从start到end都只绑定了拖动的元素,目标元素的数据拿不到,那该怎么获取呢?或者提供一下别的思路呢?

上代码:

<template>
  <div class="jigsaw" @touchmove.prevent>
    <canvas
      id="canvas"
      v-show="false"
      class="jigsaw-canvas"
      width="150"
      height="150"
    >Browser cannot support canvas.</canvas>
    <ul class="jigsaw-sudoku" id="sudoku">
      <li v-for="(item, index) in 9" :key="`sudoku_${index}`">
        <img :id="`_${index}`" src alt />
      </li>
    </ul>

    <ul class="jigsaw-selector" id="selector">
      <li v-for="(item, index) in 9" :key="`selector_${index}`">
        <img src alt draggable />
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: '',
  props: {
  },
  data() {
    return {
      imgSrc: require('@/assets/demo.jpg'),
      startX: 0,
      startY: 0,
      ctx: undefined,
      selectorList: [],
      selectorArr: [],
    };
  },
  computed: {
  },
  created() {
  },
  mounted() {
    this.onInit();
  },
  watch: {
  },
  methods: {
    /* ----------------------行为触发函数------------------------ */
    actionToDrag() {
      const sudoku = document.getElementById('sudoku')
      const selector = document.getElementById('selector')

      sudoku.addEventListener('dragover', function (e) {
        e.preventDefault();
      }, false);

      selector.addEventListener('dragover', function (e) {
        e.preventDefault();
      }, false);

      selector.addEventListener('dragstart', function (e) {
        const target = e.target;
        if (target.tagName.toLowerCase() == 'img') {
          e.dataTransfer.setData('id', target.id);
        }
      }, false);

      sudoku.addEventListener('drop', function (e) {
        const target = e.target;
        if (target.tagName.toLowerCase() == 'img') {
          const originObj = document.getElementById(e.dataTransfer.getData('id'));
          const endObj = target;
          if (target.id === `_${e.dataTransfer.getData('id')}`) {
            [endObj.src, originObj.src] = [originObj.src, endObj.src];
            [endObj.id, originObj.id] = [originObj.id, endObj.id];
            originObj.parentNode.remove()

            // let newImgArr = document.querySelectorAll('#sudoku img');
            // let idArr = [];
            // for (i = 0; i < 9; i++) {
            //   idArr.push(newImgArr[i].id);
            // }
            // if (idArr.toString() == [0, 1, 2, 3, 4, 5, 6, 7, 8].toString()) {
            //   alert('success')
            // }
          }
        }
      }, false);
    },

    /* ----------------------内部处理函数------------------------ */
    onRandomImage() {
      this.selectorArr = this.selectorArr.sort(function () {
        return Math.random() - Math.random();
      })
    },
    onRenderImage(image) {
      let index = 0;
      for (let i = 0; i < 3; i++) {
        for (let j = 0; j < 3; j++) {
          this.ctx.drawImage(image, 300 * j, 300 * i, 300, 300, 0, 0, 150, 150);
          this.selectorArr[index].src = document.getElementById('canvas').toDataURL('image/jpeg');
          this.selectorArr[index].id = index;
          index++;
        }
      }
    },
    onLoadImage(imgSrc) {
      const image = new Image();
      const _this = this
      image.src = imgSrc
      image.onload = function () {
        _this.onRandomImage()
        _this.onRenderImage(image)
        _this.actionToDrag()
      }
    },
    onInit() {
      this.ctx = document.getElementById('canvas').getContext('2d');
      this.selectorList = document.querySelectorAll('#selector img');
      this.selectorArr = Array.from(this.selectorList);
      this.onLoadImage(this.imgSrc)
    },

    /* ----------------------请求调用函数------------------------ */
    ajaxToDo() { }
  },
  components: {
  },
};
</script>

<style lang="less" scoped>
.jigsaw {
  &-sudoku {
    width: 246px;
    margin: 80px auto;
    overflow: hidden;
    > li {
      width: 80px;
      height: 80px;
      float: left;
      margin: 1px;
      > img {
        width: 80px;
        height: 80px;
      }
    }
  }
  &-selector {
    display: flex;
    overflow-x: auto;
    > li {
      width: 80px;
      height: 80px;
      margin: 1px;
      img {
        width: 80px;
        height: 80px;
      }
    }
  }
}
</style>
阅读 3.6k
1 个回答

使用HTML的Drag & Drop API。把3X3的区域设置为可拖拽区域,然后每块拼图设置为可拖拽元素,当元素drop释放后,拿到源信息和目标区域的信息,进行对比和后续的逻辑编写。

推荐问题