跨越表格单元格移动<img>元素?

4
我正在尝试创建一个程序,在该程序中,您首先要点击“Step”按钮,然后左上角单元格内的<p>元素应替换为<img>元素,即您选择的<img>元素。
随着“Step”按钮的所有后续点击,该图像沿表格的周边单元格顺时针移动一个单元格。当该图像移出单元格时,应恢复该单元格的原始文本。点击“Reset”按钮应将页面恢复到其初始状态。
注意:或者,您可以仅将<p>添加到表格的周边单元格,并直接在不在表格周边的<td>元素中编写文本。
非常感谢您的帮助!
这里是一个JSfiddle,其中包含注释代码,以解释我为什么要这样做。

function moveImageAlongCells() { //Function to move the image along the cells
  var table = document.getElementById('myTable');

  reset(table);

  var img = document.createElement("IMG"); //create the image
  
  img.setAttribute("src", "img_pulpit.jpg"); //Example from internet

  for (var r = 0, n = table.rows.length; r < n; r++) {
    for (var c = 0, m = table.rows[r].cells.length; c < m; c++) {
      // alert(table.rows[r].cells[c].innerHTML); // This worked as it went across all the the cells
      temp = table.rows[r].cells[c];
      table.rows[r].cells[c].removechild("P"); //Do I remove the <P> element?
      table.rows[r].celss[c].appendChild("img"); // And then add the <img> element
    }
  }
}

function reset(old) {
  document.getElement(old); //Trying to save the table without edits so that the reset button works
}
table, td {
  border: 1px solid black;
}
<p>Click the Step button and it will move the image over to the next cell all the way along the PERIMETER of the cell. The reset button then will reset the table back to normal. With no images</p>

<table id="myTable">
  <tr>
    <td>
      <p>Row1 cell1</p>
    </td>
    <td>
      <p>Row1 cell2</p>
    </td>
    <td>
      <p>Row1 cell3</p>
    </td>
    <td>
      <p>Row1 cell4</p>
    </td>
  </tr>
  <tr>
    <td>
      <p>Row2 cell1</p>
    </td>
    <td>
      <p>Row2 cell2</p>
    </td>
    <td>
      <p>Row2 cell3</p>
    </td>
    <td>
      <p>Row2 cell4</p>
    </td>
  </tr>
  <tr>
    <td>
      <p>Row3 cell1</p>
    </td>
    <td>
      <p>Row3 cell2</p>
    </td>
    <td>
      <p>Row3 cell3</p>
    </td>
    <td>
      <p>Row3 cell4</p>
    </td>
  </tr>
  <tr>
    <td>
      <p>Row4 cell1</p>
    </td>
    <td>
      <p>Row4 cell2</p>
    </td>
    <td>
      <p>Row4 cell3</p>
    </td>
    <td>
      <p>Row4 cell4</p>
    </td>
  </tr>
</table>
<br>

<!-- calls the function that moves the image -->
<button onclick="moveImageAlongCells()">STEP</button>

<!-- resets the table to it's original form. (without any images) -->
<button onclick="reset()">RESET</button>


什么是问题?这很简单!对于您的声誉来说,这应该非常容易。 - Tone Škoda
当然这很简单,但对我来说还没有领悟。我尝试了数十种方法,似乎无法让它工作。看起来已经走到了死胡同。 - newbs
4个回答

3
为了使图像环绕周边,需要在每一步检查其当前位置并将其与表格边界进行比较。
同时,在每一步中,需要保持当前单元格和先前的子<p>元素。
尝试此示例:

var table = document.getElementById('myTable');
var img = document.createElement("IMG"); //create the image
img.setAttribute("src", "http://images.clipartpanda.com/circle-clip-art-niBB6kXiA.png");
var temp;
var row = 0, column = 0;
var currentCell;

function moveImageAlongCells() { //Function to move the image along the cells
  if (temp) {
    currentCell.removeChild(currentCell.firstElementChild);
    currentCell.appendChild(temp);
  }
  currentCell = table.rows[row].cells[column];
  temp = currentCell.firstElementChild;
  if (row === 0 && column < table.rows[0].cells.length - 1) {
    column++;
  } else if (column === table.rows[0].cells.length - 1 && row < table.rows.length - 1) {
    row++;
  } else if (row === table.rows.length - 1 && column > 0) {
    column--;
  } else {
    row--;
  }
  currentCell.removeChild(currentCell.firstElementChild);
  currentCell.appendChild(img);
}

function reset() {
  if (currentCell && temp) {
    currentCell.removeChild(currentCell.firstElementChild);
    currentCell.appendChild(temp);
    row = 0;
    column = 0;
  }
}
table, td {
  border: 1px solid black;
}
img {
  width: 20px;
  height: 20px;
  position: relative;
  left: calc(50% - 10px);
}
<table id="myTable">
  <tr>
    <td>
      <p>Row1 cell1</p>
    </td>
    <td>
      <p>Row1 cell2</p>
    </td>
    <td>
      <p>Row1 cell3</p>
    </td>
    <td>
      <p>Row1 cell4</p>
    </td>
  </tr>
  <tr>
    <td>
      <p>Row2 cell1</p>
    </td>
    <td>
      <p>Row2 cell2</p>
    </td>
    <td>
      <p>Row2 cell3</p>
    </td>
    <td>
      <p>Row2 cell4</p>
    </td>
  </tr>
  <tr>
    <td>
      <p>Row3 cell1</p>
    </td>
    <td>
      <p>Row3 cell2</p>
    </td>
    <td>
      <p>Row3 cell3</p>
    </td>
    <td>
      <p>Row3 cell4</p>
    </td>
  </tr>
  <tr>
    <td>
      <p>Row4 cell1</p>
    </td>
    <td>
      <p>Row4 cell2</p>
    </td>
    <td>
      <p>Row4 cell3</p>
    </td>
    <td>
      <p>Row4 cell4</p>
    </td>
  </tr>
</table>
<br>

<!-- calls the function that moves the image -->
<button onclick="moveImageAlongCells()">STEP</button>

<!-- resets the table to it's original form. (without any images) -->
<button onclick="reset()">RESET</button>


重置函数中我使用的参数是不是不必要的?除此之外,你的代码很容易理解,我正在尝试看看它为什么这样做以及如何做到的。谢谢你的回答。 - newbs
1
@newbs 是的,考虑到您从未传递它,您的重置函数参数是不必要的。我的重置函数使用外部的 currentCelltemp 变量来恢复页面状态。如果您对我的代码有任何疑问,我很乐意帮助! - Kirill Simonov
好的,那很有道理。非常感谢你。现在我明白了很多。如果我遇到任何问题,我会告诉你的 :D - newbs

2

尝试这个解决方案:

nr_cells = $("#myTable").find('td').length;
position = 0;
$(".next").click(function(i, v) {
  console.log(i + " " + position);

  $("#myTable").find('td').each(function(i, v) {
    
    if (i == position) {
      $(v).append('<img class="irc_mi" src="https://img.stockfresh.com/img/header-avatar.jpg" style="z-index:99999" width="50" height="50">');
      $(v).find('p').css('display', 'none');

    }

     $("#myTable").find('td').each(function(i, v) {
      if(i != position && nr_cells != i+1) {
       $(v).find('img').remove();
      $(v).find('p').css('display', 'block');
      }
    });
   
  });
  position++;
  
   
});

$(".reset").click(function(i, v) {

  $("#myTable").find('td').each(function(i, v) {

    $(v).find('img').remove();
    $(v).find('p').css('display', 'block');

  });
  position = 0;
});
table,
td {
  border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
  Click the Step button and it will move the image over to the next cell all the way along the PERIMETER of the cell. The reset button then will reset the table back to normal. With no images</p>

<table id="myTable">
  <tr>
    <td>
      <p>Row1 cell1</p>
    </td>
    <td>
      <p>Row1 cell2</p>
    </td>
    <td>
      <p>Row1 cell3</p>
    </td>
    <td>
      <p>Row1 cell4</p>
    </td>
  </tr>
  <tr>
    <td>
      <p>Row2 cell1</p>
    </td>
    <td>
      <p>Row2 cell2</p>
    </td>
    <td>
      <p>Row2 cell3</p>
    </td>
    <td>
      <p>Row2 cell4</p>
    </td>
  </tr>
  <tr>
    <td>
      <p>Row3 cell1</p>
    </td>
    <td>
      <p>Row3 cell2</p>
    </td>
    <td>
      <p>Row3 cell3</p>
    </td>
    <td>
      <p>Row3 cell4</p>
    </td>
  </tr>
  <tr>
    <td>
      <p>Row4 cell1</p>
    </td>
    <td>
      <p>Row4 cell2</p>
    </td>
    <td>
      <p>Row4 cell3</p>
    </td>
    <td>
      <p>Row4 cell4</p>
    </td>
  </tr>
</table>
<button class="next">Next</button>
<button class="reset">Reset</button>


这看起来很有前途,但是图像停留在上一个单元格中,而不是在移动到下一个单元格时恢复。将单元格内容保存到临时变量中,不会让图像看起来像是在移动吗? - newbs

1
编辑:使图像覆盖整个表格数据单元。
<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        table,
        td {
            border: 1px solid black;
        }

        td{
            width: 70px;
        }

        img{
            width: 100%;
        }

        .hidden {
            display: none;
        }
    </style>
</head>

<body>
    <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
    <p>Click the Step button and it will move the image over to the next cell all the way along the PERIMETER of the cell. The
        reset button then will reset the table back to normal. With no images</p>

    <table id="myTable">
        <tr>
            <td>
                <p>Row1 cell1</p>
            </td>
            <td>
                <p>Row1 cell2</p>
            </td>
            <td>
                <p>Row1 cell3</p>
            </td>
            <td>
                <p>Row1 cell4</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Row2 cell1</p>
            </td>
            <td>
                <p>Row2 cell2</p>
            </td>
            <td>
                <p>Row2 cell3</p>
            </td>
            <td>
                <p>Row2 cell4</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Row3 cell1</p>
            </td>
            <td>
                <p>Row3 cell2</p>
            </td>
            <td>
                <p>Row3 cell3</p>
            </td>
            <td>
                <p>Row3 cell4</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Row4 cell1</p>
            </td>
            <td>
                <p>Row4 cell2</p>
            </td>
            <td>
                <p>Row4 cell3</p>
            </td>
            <td>
                <p>Row4 cell4</p>
            </td>
        </tr>
    </table>
    <br>

    <!-- calls the function that moves the image -->
    <button id="step">STEP</button>

    <!-- resets the table to it's original form. (without any images) -->
    <button id="reset">RESET</button>
    <script>
        var table = document.getElementById('myTable')
        var tdInTable = table.getElementsByTagName('td')
        var image = document.createElement('img')
        image.setAttribute('src', 'https://vignette.wikia.nocookie.net/logopedia/images/2/26/Research%40Google_Icon.png')
        var step = document.getElementById('step')
        var reset = document.getElementById('reset')
        var index = 0
        step.addEventListener('click', function () {
            if(index === 0){
                tdInTable[tdInTable.length - 1].getElementsByTagName('p')[0].classList.remove('hidden')

            }
            if (index > 0) {
                tdInTable[index - 1].getElementsByTagName('p')[0].classList.remove('hidden')
            }
            tdInTable[index].getElementsByTagName('p')[0].classList.add('hidden')
            tdInTable[index].appendChild(image)
            index++

            if (index >= tdInTable.length) {
                index = 0

            }
        })

        reset.addEventListener('click', function () {
            if(image.parentElement){
            tdInTable[--index].removeChild(image)
            tdInTable[index].getElementsByTagName('p')[0].classList.remove('hidden')
            index = 0
            }

        })
    </script>
</body>

</html>

1
太棒了!我看到你做的事情了,很有道理。有没有办法让图像只围绕周边走? - newbs

0

不是解决方案,而是解决此类问题的步骤。

将DOM操作或View逻辑与您的State分离。 State表示您拥有什么内容,(2,4)单元格中的文本或图像是什么,在(4,2)单元格中,它显示文本还是图像。然后,View应基于该State进行呈现。

步骤。

  1. 为表格中的每个单元格创建一个状态。例如:

    class CellState {
      constructor() {
      this.showText = true;
      this.text = 'bla bla';
      this.imgSrc = 'http...';
    }}
    
您将拥有一个CellState[][]来跟踪所有单元格。让有一个 function init() 来初始化CellState[][]到默认值。
  1. 创建一个render()函数,根据单元格状态进行渲染。例如对于16个单元格,它会进行迭代。如果showTexttrue,则显示文字,否则显示图像。如果有文本输入,则更改输入的值应该更改该CellState文本。
  2. 现在应该有两个事件:StepReset

Reset应该如下所示:

function onClickReset(){
  init(); //again init.
  render();
}

步骤应该是这样的

function onClickStep() {

  // handle your complex logic of changing or shifting the image etc.. 
  // or whatever you want to achieve.
  // But we won't have to modify the dom elements just the CellState[][],
  // as the dom manipulation will be automatically done in render();

  render();
}

不用担心任何性能问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接