使用 javascript 在 table 中移动图像

Moving images in a table using javascript

我终于从头完成了一个棋盘的小标记。代码非常简单,可能可以更容易地完成,但是我想在返回之前完成该项目,看看我可以做得更好。

话虽如此,我在尝试移动棋盘上的棋子时遇到了很多问题,所以我希望有人能给我一些建议,告诉我下一步该怎么做。

结帐https://github.com/kevin6767/Chessboard.js

希望有人能快速浏览并很快弄清楚,或者给我指出正确的方向

我研究了 onclick 和 onmousedown 选项,但是一旦我得到图像中的代码保持不变,我就不会收到错误或任何它们只是保持相同行为的东西。

问题是您的 genBoard 函数没有动态数据,因此每次调用它时都会生成完全相同的板。

这一篇就是问题所在:

function genBoard (){
  // these image sets are always the same
  var urls1 = ["image/a0.png",/* ...etc */]
  var urls2 = ["image/a8.png",/* ...etc */]
  var urls3 = ["image/a16.png",/* ...etc */]
  var urls4 = ["image/a24.png",/* ...etc */]

  // the rest renders the board using the image sets that never change
}

我不确定您打算通过何种交互来允许用户移动一块,但您需要跟踪哪些块被移动到哪里并重新渲染这些块。我会有一个单独的函数来渲染棋盘和棋子。这可能看起来像这样:

const whitePieces = [
  { id: "wr1", name: "rook", color: "white", position: "A8" },
  { id: "wk1", name: "knight", color: "white", position: "B8" },
  { id: "wb1", name: "bishop", color: "white", position: "C8" },
  { id: "wk", name: "king", color: "white", position: "D8" },
  { id: "wq", name: "queen", color: "white", position: "E8" },
  { id: "wb2", name: "bishop", color: "white", position: "F8" },
  { id: "wk2", name: "knight", color: "white", position: "G8" },
  { id: "wr2", name: "rook", color: "white", position: "H8" },
  { id: "wp1", name: "pawn", color: "white", position: "A7" },
  { id: "wp2", name: "pawn", color: "white", position: "B7" },
  { id: "wp3", name: "pawn", color: "white", position: "C7" },
  { id: "wp4", name: "pawn", color: "white", position: "D7" },
  { id: "wp5", name: "pawn", color: "white", position: "E7" },
  { id: "wp6", name: "pawn", color: "white", position: "F7" },
  { id: "wp7", name: "pawn", color: "white", position: "G7" },
  { id: "wp8", name: "pawn", color: "white", position: "H7" }
];

const blackPieces = [
  { id: "br1", name: "rook", color: "black", position: "A1" },
  { id: "bk1", name: "knight", color: "black", position: "B1" },
  { id: "bb1", name: "bishop", color: "black", position: "C1" },
  { id: "bk", name: "king", color: "black", position: "D1" },
  { id: "bq", name: "queen", color: "black", position: "E1" },
  { id: "bb2", name: "bishop", color: "black", position: "F1" },
  { id: "bk2", name: "knight", color: "black", position: "G1" },
  { id: "br2", name: "rook", color: "black", position: "H1" },
  { id: "bp1", name: "pawn", color: "black", position: "A2" },
  { id: "bp2", name: "pawn", color: "black", position: "B2" },
  { id: "bp3", name: "pawn", color: "black", position: "C2" },
  { id: "bp4", name: "pawn", color: "black", position: "D2" },
  { id: "bp5", name: "pawn", color: "black", position: "E2" },
  { id: "bp6", name: "pawn", color: "black", position: "F2" },
  { id: "bp7", name: "pawn", color: "black", position: "G2" },
  { id: "bp8", name: "pawn", color: "black", position: "H2" }
];

function genBoard() {
  var columns = ["A", "B", "C", "D", "E", "F", "G", "H"];
  var table = document.createElement("table");
  table.setAttribute("id", "myTable");

  for (var i = 0; i < 8; i++) {
    var row = document.createElement("tr");
    for (var j = 0; j < 8; j++) {
      var cell = document.createElement("td");
      cell.id = columns[j] + (i + 1);
      if (i % 2 == j % 2) {
        cell.className += "white" + (j + 1);
      } else {
        cell.className += "grey" + (j + 1);
      }
      row.appendChild(cell);
    }
    table.appendChild(row);
  }

  document.body.appendChild(table);
}

function placePieces() {
  whitePieces.concat(blackPieces).forEach(function(piece) {
    var tile = document.getElementById(piece.position);
    var img = document.createElement("img");
    var name = piece.name + "-" + piece.color;
    img.src = "image/" + name + ".png";
    img.id = piece.id;
    img.alt = name;
    tile.appendChild(img);
  });
}

genBoard();
placePieces();

然后您将需要跟踪点击次数以了解某人想要移动哪一块以及移动到哪里。根据其 id 更新片段的 position 并重新渲染片段。

好吧,这真是个好家伙。但是,如果您只是使用 javascript 学习它,我建议您使用像 Angular 这样的框架或像 JQuery/React

这样的库

第一件事是映射路线或制作规则引擎,根据您拖动的项目和您悬停或打算放下的单元格,哪个部分可以去哪里。

您需要将这些事件 dragstart、dragend、dragenter、dragleave、dragover、drop 绑定到您的 img 和 td 标签。

我还做了一个规定,如果cell已经有棋子,就不允许掉落

干杯!

查看以下代码段。

let pieceArray = [
    { name: 'rook', image: 'a0.png' },
    { name: 'knight', image: 'a1.png' },
    { name: 'bishop', image: 'a2.png' },
    { name: 'king', image: 'a3.png' },
    { name: 'queen', image: 'a4.png' },
    { name: 'bishop2', image: 'a5.png' },
    { name: 'knight2', image: 'a6.png' },
    { name: 'rook2', image: 'a8.png' },
];


function genBoard() {
    var urls1 = ["image/a0.png", "image/a1.png", "image/a2.png", "image/a3.png", "image/a4.png", "image/a5.png", "image/a6.png", "image/a7.png"]
    var urls2 = ["image/a8.png", "image/a9.png", "image/a10.png", "image/a11.png", "image/a12.png", "image/a13.png", "image/a14.png", "image/a15.png"]
    var urls3 = ["image/a16.png", "image/a17.png", "image/a18.png", "image/a19.png", "image/a20.png", "image/a21.png", "image/a22.png", "image/a23.png"]
    var urls4 = ["image/a24.png", "image/a25.png", "image/a26.png", "image/a27.png", "image/a28.png", "image/a29.png", "image/a30.png", "image/a31.png"]
    
    //Do not include in code just to work the snippet
    
    urls1 = urls1.map(i => 'https://github.com/kevin6767/Chessboard.js/raw/master/' + i);
    urls2 = urls2.map(i => 'https://github.com/kevin6767/Chessboard.js/raw/master/' + i);
    urls3 = urls3.map(i => 'https://github.com/kevin6767/Chessboard.js/raw/master/' + i);
    urls4 = urls4.map(i => 'https://github.com/kevin6767/Chessboard.js/raw/master/' + i);

    var p = 1;
    var table = document.createElement("table");
    table.setAttribute("id", "myTable");
    for (var i = 0; i < 8; i++) {
        var row = document.createElement('tr');
        for (var j = 0; j < 8; j++) {
            var cell = document.createElement('td');
            if (i < 1) {
                cell.insertAdjacentHTML('beforeend', '<img class="piece" draggable="true" id="' + urls1[j] + '" src="' + urls1[j] + '">');
            }
            if (i > 0 && i < 2) {
                cell.insertAdjacentHTML('beforeend', '<img class="piece" draggable="true" id="' + urls2[j] + '" src="' + urls2[j] + '">');
            }
            if (i > 5 && i < 7) {
                cell.insertAdjacentHTML('beforeend', '<img class="piece" draggable="true" id="' + urls3[j] + '" src="' + urls3[j] + '">');
            }
            if (i < 8 && i > 6) {
                cell.insertAdjacentHTML('beforeend', '<img class="piece" draggable="true" id="' + urls4[j] + '" src="' + urls4[j] + '">');
            }

            if (i % 2 == j % 2) {
                cell.className += "white" + p;
            } else {
                cell.className += "grey" + p;
            }
            row.appendChild(cell);
            p++;

        }
        table.appendChild(row);


    }
    document.body.appendChild(table);

    addEventListeners(document.querySelectorAll('img'), 'dragstart', function(e){
        this.parentNode.classList.add('source');
        dragData(e, { id: e.target.id, source: '.'+this.parentNode.classList.toString().split(' ')[0] });
    });

    addEventListeners(document.querySelectorAll('td'), 'dragend', function(e){
        document.querySelectorAll('.source').forEach(function(node){node.classList.remove('source');})
    });

    addEventListeners(document.querySelectorAll('td'), 'drop', function(e){
        e.preventDefault();
        e.stopPropagation();
        var data = dragData(e);
        this.classList.remove('allowed', 'denied', 'active');
        var incoming = dragData(e).id;
        var source = dragData(e).source;
        var target = '.' + this.classList.toString().split(' ')[0];
        // TODO: some rule engine the incoming piece can go to this target or not
        var allowed = !(document.querySelector(target).children.length); // doesn't have a piece already. need more rules if the piece move is needed to be here 
        if(allowed) {
            this.appendChild(document.getElementById(data.id));
        } else {
            // nothing
        }
    });

    addEventListeners(document.querySelectorAll('td'), 'dragover', function(e){
        e.preventDefault();
    });

    addEventListeners(document.querySelectorAll('td'), 'dragenter', function(e){
        e.preventDefault();
        this.classList.add('active');
        var incoming = dragData(e).id;
        var source = dragData(e).source;
        var target = '.' + this.classList.toString().split(' ')[0];
        // TODO: some rule engine the incoming piece can go to this target or not
        var allowed = !(document.querySelector(target).children.length); // doesn't have a piece already. need more rules if the piece move is needed to be here 
        if(!this.classList.contains('source')){
            this.classList.toggle('allowed', allowed);
            this.classList.toggle('denied', !allowed);
        }
    });

    addEventListeners(document.querySelectorAll('td'), 'dragleave', function(e){
        e.preventDefault();
        if(!this.contains(e.relatedTarget)){
            this.classList.remove('allowed', 'denied', 'active');
        }
    });


}

function addEventListeners(list, event, fn) {
    for (var i = 0, len = list.length; i < len; i++) {
        list[i].addEventListener(event, fn.bind(list[i]), false);
    }
}


function dragData(event, data) {
    if (data) {
        event.dataTransfer.setData('text', JSON.stringify(data));
    } else {
        var response = event.dataTransfer.getData('text');
        try {
            response = JSON.parse(response);
        } catch (e) {
            response = {};
        }
        return response;
    }
}
// polyfill closest api
if (window.Element && !Element.prototype.closest) {
    Element.prototype.closest =
    function(s) {
      var matches = (this.document || this.ownerDocument).querySelectorAll(s),
          i,
          el = this;
      do {
        i = matches.length;
        while (--i >= 0 && matches.item(i) !== el) {};
      } while ((i < 0) && (el = el.parentElement));
      return el;
    };
  }

genBoard();
table {
  empty-cells: show;
}

td {
  width: 6em;
  height: 6em;
  line-height: 2em;
  text-align: center;
  border: 1px solid #000;
  padding: 20px;
  transition: all ease 200ms;
}

tbody tr:nth-child(odd) td:nth-child(even),
tbody tr:nth-child(even) td:nth-child(odd) {
  color: #fff;
  background-color: #00f;
}

tbody tr:nth-child(even) td:nth-child(even),
tbody tr:nth-child(odd) td:nth-child(odd) {
  background-color: #999;
}

tbody {
  counter-reset: rowNumber;
}

tr {
  counter-increment: rowNumber;
  counter-reset: cellNumber;
}

td {
  counter-increment: cellNumber;
}

td::after {
  content: counter(cellNumber, upper-alpha) counter(rowNumber, decimal);
}

td[class^="grey"] {
  background-color: grey;
}

td[class^="white"] {
  background-color: white;
}

td.allowed {
  transform: scale(1.1);
}

td.denied {
  background-color: red;
}
<html>

<head>
  <meta charset="utf-8">
  <title></title>

</head>

<body>



</body>

</html>