英文:
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 "react";
import Node from './Node/Node';
import './Node/Node.css'
import './PathfindingVisualizer.css';
//import { render } from "@testing-library/react";
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);
}
/*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(
<>
<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,
//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: [], // 🟥 新状态,有一个空网格副本
mouseIsPressed: false
};
}
componentDidMount() {
const grid = getInitialGrid();
this.setState({
grid,
animatedGrid: structuredClone(grid) // 🟥 传递网格的深度副本
});
}
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); // 🟥 为了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; // 🟥 在此处使用新状态
return (
<>
<button onClick={() => this.visualizeDijkstra()}>
Visualize Dijkstra Algorithm
</button>
<div className="grid">
{animatedGrid.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
};
};
英文:
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)
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: [], // 🟥 new state to have an empty grid
mouseIsPressed: false
};
}
componentDidMount() {
const grid = getInitialGrid();
this.setState({
grid,
animatedGrid: structuredClone(grid) // 🟥 passing a deepcopy of the grid
});
}
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); // 🟥 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; // 🟥 using the new state here
return (
<>
<button onClick={() => this.visualizeDijkstra()}>
Visualize Dijkstra Algorithm
</button>
<div className="grid">
{animatedGrid.map((row, rowIdx) => {
// 🟥 using the new state here
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
};
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论