逐个节点动画未渲染。

huangapple go评论67阅读模式
英文:

Node by node animation is not rendered

问题

I am trying to implement Clement's Pathfinding visualizer by watching his Youtube tutorial.
我正在尝试通过观看Clement的Youtube教程来实现路径可视化。

However, my node by node animation is not getting rendered even if I provide the delay for each node animation.
然而,即使我为每个节点动画提供了延迟,我的逐个节点动画也没有被渲染。

Can you please take a look at the code?
请你看一下这段代码好吗?

The output I want is the node by node animation
我想要的输出是逐个节点的动画。

Also, I am new to React JS and a beginner at JavaScript. Although I understand what is going on, on the surface level, it is a bit difficult to make changes like this. Can you also suggest what can I do to strengthen my fundamentals.
此外,我是React JS的新手,也是JavaScript的初学者。虽然我理解表面上正在发生的事情,但要像这样进行更改有点困难。你能否提出一些建议,以加强我的基础知识。

Thank you
谢谢

import React, { Component } from "react";
import Node from './Node/Node';
import './Node/Node.css';

import './PathfindingVisualizer.css';
import { dijkstra_algorithm as dijkstra } from '../algorithms/dijkstra';

const START_NODE_ROW = 10;
const START_NODE_COL = 15;
const FINISH_NODE_ROW = 15;
const FINISH_NODE_COL = 30;

export default class PathfindingVisualizer extends Component {
  constructor() {
    super();
    this.state = {
      grid: [],
      mouseIsPressed: false
    };
  }

  componentDidMount() {
    const grid = getInitialGrid();
    this.setState({ grid });
  }

  animateDijkstra(visitedNodesInOrder) {
    visitedNodesInOrder.forEach((node, i) => {
      setTimeout(() => {
        this.setState((prevState) => {
          const newGrid = prevState.grid.slice();
          const newNode = {
            ...node,
            isVisited: true,
          };
          newGrid[node.row][node.col] = newNode;
          return { grid: newGrid };
        });
      }, 1000 * i); // Delay each animation by 1000 milliseconds (1 second)
    });
  }

  visualizeDijkstra() {
    const { grid } = this.state;
    const startNode = grid[START_NODE_ROW][START_NODE_COL];
    const finishNode = grid[FINISH_NODE_ROW][FINISH_NODE_COL];
    const visitedNodesInOrder = dijkstra(grid, startNode, finishNode);
    this.animateDijkstra(visitedNodesInOrder);
  }

  render() {
    const { grid } = this.state;

    return (
      <>
        <button onClick={() => this.visualizeDijkstra()}>
          Visualize Dijkstra Algorithm
        </button>
        <div className="grid">
          {grid.map((row, rowIdx) => {
            return (
              <div key={rowIdx}>
                {row.map((node, nodeIdx) => {
                  const { isStart, isFinish, isVisited } = node;
                  return (
                    <Node
                      key={nodeIdx}
                      isStart={isStart}
                      isFinish={isFinish}
                      isVisited={isVisited}
                    >
                    </Node>
                  );
                })}
              </div>
            );
          })}
        </div>
      </>
    );
  }
}

const getInitialGrid = () => {
  const grid = [];

  for (let row = 0; row < 20; row++) {
    const currentRow = [];
    for (let col = 0; col < 50; col++) {
      currentRow.push(createNode(col, row));
    }

    grid.push(currentRow);
  }
  return grid;
};

const createNode = (col, row) => {
  return {
    col,
    row,
    isStart: row === START_NODE_ROW && col === START_NODE_COL,
    isFinish: row === FINISH_NODE_ROW && col === FINISH_NODE_COL,
    distance: Infinity,
    isVisited: false,
    previousNode: null,
  };
};

This is my output in one go.
这是我的一次性输出。

英文:

I am trying to implement Clement's Pathfinding visualizer by watching his Youtube tutorial.
However, my node by node animation is not getting rendered even if I provide the delay for each node animation.
Can you please take a look at the code?

The output I want is the node by node animation

Also, I am new to React JS and a beginner at JavaScript. Although I understand what is going on, on the surface level, it is a bit difficult to make changes like this. Can you also suggest what can I do to strengthen my fundamentals.

Thank you

import React, {Component} from &quot;react&quot;;
import Node from &#39;./Node/Node&#39;;
import &#39;./Node/Node.css&#39;
import &#39;./PathfindingVisualizer.css&#39;;
//import { render } from &quot;@testing-library/react&quot;;
import {dijkstra_algorithm as dijkstra} from &#39;../algorithms/dijkstra&#39;
const START_NODE_ROW = 10;
const START_NODE_COL = 15;
const FINISH_NODE_ROW = 15; 
const FINISH_NODE_COL = 30;
export default class PathfindingVisualizer extends Component{
constructor(){
super();
this.state={
grid: [],
mouseIsPressed: false
};
}
componentDidMount() {
const grid= getInitialGrid();
this.setState({grid});
}
animateDijkstra(visitedNodesInOrder) {
visitedNodesInOrder.forEach((node, i) =&gt; {
setTimeout(() =&gt; {
this.setState((prevState) =&gt; {
const newGrid = prevState.grid.slice();
const newNode = {
...node,
isVisited: true,
};
newGrid[node.row][node.col] = newNode;
return { grid: newGrid };
});
}, 1000 * i); // Delay each animation by 1000 milliseconds (1 second)
});
}
visualizeDijkstra(){
const {grid} = this.state;
const startNode=grid[START_NODE_ROW][START_NODE_COL];
const finishNode=grid[FINISH_NODE_ROW][FINISH_NODE_COL];
const visitedNodesInOrder=dijkstra(grid, startNode,finishNode);
this.animateDijkstra(visitedNodesInOrder);
}
/*handleMouseEnter(row, col) {
if (!this.state.mouseIsPressed) return;
const newGrid = getNewGridWithWallToggled(this.state.grid, row, col);
this.setState({grid: newGrid});
}
handleMouseUp() {
this.setState({mouseIsPressed: false});
}*/
render(){
const {grid}=this.state;
return(
&lt;&gt;
&lt;button onClick={() =&gt; this.visualizeDijkstra()}&gt;
Visualize Dijkstra Algorithm
&lt;/button&gt;
&lt;div className=&quot;grid&quot;&gt;
{grid.map((row,rowIdx)=&gt;{
return(
&lt;div key={rowIdx}&gt;
{row.map((node,nodeIdx) =&gt; {
const {isStart, isFinish, isVisited} = node;
return(
&lt;Node
key={nodeIdx}
isStart={isStart}
isFinish={isFinish}
isVisited={isVisited}
&gt;
&lt;/Node&gt;
);
})}
&lt;/div&gt;
);
})}
&lt;/div&gt;
&lt;/&gt;
);
}
}
const getInitialGrid = () =&gt; {
const grid=[];
for(let row=0; row&lt;20; row++){
const currentRow=[];
for(let col=0; col&lt;50; col++){
currentRow.push(createNode(col,row));
}
grid.push(currentRow);
}
return grid;
};
const createNode = (col, row) =&gt; {
return{
col,
row,
isStart: row === START_NODE_ROW &amp;&amp; col === START_NODE_COL,
isFinish: row === FINISH_NODE_ROW &amp;&amp; col ===FINISH_NODE_COL,
distance: Infinity,
isVisited: false,
//isWall: false,
previousNode: null,
};
};

This is my output in one go.

逐个节点动画未渲染。

答案1

得分: 1

以下是您要翻译的代码部分:

问题在于您在进行计算等操作时更改了网格... 当您单击开始渲染时,网格已经全部设置好了。我通过在状态中保留一个空网格的副本来防止这种情况,并通过循环遍历这个空网格(使用 structuredClone 进行深度复制,如果使用 ....slice() 进行复制,将会进行浅复制,问题将会发生)

PathfindingVisualizer.jsx

import React, { Component } from "react";
import Node from "./Node/Node";
import "./Node/Node.css";

import "./PathfindingVisualizer.css";
import { dijkstra_algorithm as dijkstra } from "../algorithms/dijkstra";

const START_NODE_ROW = 10;
const START_NODE_COL = 15;
const FINISH_NODE_ROW = 15;
const FINISH_NODE_COL = 30;

export default class PathfindingVisualizer extends Component {
  constructor() {
    super();
    this.state = {
      grid: [],
      animatedGrid: [], // &#128997; 新状态,有一个空网格副本
      mouseIsPressed: false
    };
  }

  componentDidMount() {
    const grid = getInitialGrid();
    this.setState({
      grid,
      animatedGrid: structuredClone(grid) // &#128997; 传递网格的深度副本
    });
  }

  animateDijkstra(visitedNodesInOrder) {
    visitedNodesInOrder.forEach((node, i) => {
      setTimeout(() => {
        this.setState((prevState) => {
          const newGrid = prevState.animatedGrid;
          const newNode = {
            ...node,
            isVisited: true
          };
          newGrid[node.row][node.col] = newNode;
          return { animatedGrid: newGrid };
        });
      }, 30 * i); // &#128997; 为了1秒,将此更改回1000
    });
  }

  visualizeDijkstra() {
    const { grid } = this.state;
    const startNode = grid[START_NODE_ROW][START_NODE_COL];
    const finishNode = grid[FINISH_NODE_ROW][FINISH_NODE_COL];
    const visitedNodesInOrder = dijkstra(grid, startNode, finishNode);
    this.animateDijkstra(visitedNodesInOrder);
  }

  render() {
    const { animatedGrid } = this.state; // &#128997; 在此处使用新状态

    return (
      <>
        <button onClick={() => this.visualizeDijkstra()}>
          Visualize Dijkstra Algorithm
        </button>
        <div className="grid">
          {animatedGrid.map((row, rowIdx) => {
            // &#128997; 在此处使用新状态
            return (
              <div key={rowIdx}>
                {row.map((node, nodeIdx) => {
                  const { isStart, isFinish, isVisited } = node;
                  return (
                    <Node
                      key={nodeIdx}
                      isStart={isStart}
                      isFinish={isFinish}
                      isVisited={isVisited}
                    ></Node>
                  );
                })}
              </div>
            );
          })}
        </div>
      </>
    );
  }
}
const getInitialGrid = () => {
  const grid = [];

  for (let row = 0; row < 20; row++) {
    const currentRow = [];
    for (let col = 0; col < 50; col++) {
      currentRow.push(createNode(col, row));
    }

    grid.push(currentRow);
  }
  return grid;
};

const createNode = (col, row) => {
  return {
    col,
    row,
    isStart: row === START_NODE_ROW && col === START_NODE_COL,
    isFinish: row === FINISH_NODE_ROW && col === FINISH_NODE_COL,
    distance: Infinity,
    isVisited: false,
    previousNode: null
  };
};
英文:

The problem is that you are changing the grid while doing the calculations and stuff... and when you click to start rendering, the grid is already all set. I prevented that by having a copy of the empty grid in the state and loop through this empty one (copy using structuredClone to do a deep copy, if you copy by spreading ... or .slice() it would make a shallow copy and the same problem would happen)

https://codesandbox.io/s/spring-star-sgn2s5?file=/src/PathfindingVisualizer/PathfindingVisualizer.jsx

PathfindingVisualizer.jsx

import React, { Component } from &quot;react&quot;;
import Node from &quot;./Node/Node&quot;;
import &quot;./Node/Node.css&quot;;
import &quot;./PathfindingVisualizer.css&quot;;
import { dijkstra_algorithm as dijkstra } from &quot;../algorithms/dijkstra&quot;;
const START_NODE_ROW = 10;
const START_NODE_COL = 15;
const FINISH_NODE_ROW = 15;
const FINISH_NODE_COL = 30;
export default class PathfindingVisualizer extends Component {
constructor() {
super();
this.state = {
grid: [],
animatedGrid: [], // &#128997; new state to have an empty grid
mouseIsPressed: false
};
}
componentDidMount() {
const grid = getInitialGrid();
this.setState({
grid,
animatedGrid: structuredClone(grid) // &#128997; passing a deepcopy of the grid
});
}
animateDijkstra(visitedNodesInOrder) {
visitedNodesInOrder.forEach((node, i) =&gt; {
setTimeout(() =&gt; {
this.setState((prevState) =&gt; {
const newGrid = prevState.animatedGrid;
const newNode = {
...node,
isVisited: true
};
newGrid[node.row][node.col] = newNode;
return { animatedGrid: newGrid };
});
}, 30 * i); // &#128997; CHANGE BACK TO 1000 FOR 1 second
});
}
visualizeDijkstra() {
const { grid } = this.state;
const startNode = grid[START_NODE_ROW][START_NODE_COL];
const finishNode = grid[FINISH_NODE_ROW][FINISH_NODE_COL];
const visitedNodesInOrder = dijkstra(grid, startNode, finishNode);
this.animateDijkstra(visitedNodesInOrder);
}
render() {
const { animatedGrid } = this.state; // &#128997; using the new state here
return (
&lt;&gt;
&lt;button onClick={() =&gt; this.visualizeDijkstra()}&gt;
Visualize Dijkstra Algorithm
&lt;/button&gt;
&lt;div className=&quot;grid&quot;&gt;
{animatedGrid.map((row, rowIdx) =&gt; {
// &#128997; using the new state here
return (
&lt;div key={rowIdx}&gt;
{row.map((node, nodeIdx) =&gt; {
const { isStart, isFinish, isVisited } = node;
return (
&lt;Node
key={nodeIdx}
isStart={isStart}
isFinish={isFinish}
isVisited={isVisited}
&gt;&lt;/Node&gt;
);
})}
&lt;/div&gt;
);
})}
&lt;/div&gt;
&lt;/&gt;
);
}
}
const getInitialGrid = () =&gt; {
const grid = [];
for (let row = 0; row &lt; 20; row++) {
const currentRow = [];
for (let col = 0; col &lt; 50; col++) {
currentRow.push(createNode(col, row));
}
grid.push(currentRow);
}
return grid;
};
const createNode = (col, row) =&gt; {
return {
col,
row,
isStart: row === START_NODE_ROW &amp;&amp; col === START_NODE_COL,
isFinish: row === FINISH_NODE_ROW &amp;&amp; col === FINISH_NODE_COL,
distance: Infinity,
isVisited: false,
previousNode: null
};
};

huangapple
  • 本文由 发表于 2023年6月12日 04:02:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76452311.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定