【发布时间】:2020-01-16 07:51:20
【问题描述】:
我的代码比我正在复制的示例滞后得多,我不知道为什么。
我正在尝试将原版 JS + d3 的页面重做为 React + VX。 VX 是一个包装 d3 的库,以使其适合反应编程模式。还有其他类似的,比如Recharts。
当我添加一个在鼠标光标的 x 位置绘制一条垂直线的鼠标悬停回调时,我的问题就出现了。
我在关注this example,很流畅。您可以看到,当您将光标移到图表上时,线条流畅地跟随。
尽我所能,我做了同样的事情,但在我的图表上,光标后面的线非常滞后。
这不仅仅是画线。我在 DOM 中输出 X 位置作为健全性检查,并且似乎以相同的滞后间隔更新。
UI 更新是滞后的,尽管我可以看出鼠标移动时鼠标悬停回调被连续快速地调用,因为我可以看到 console.log 输出更快。
这是我的代码。我想知道:为什么我的会比我复制的示例慢这么多?
import React from 'react';
import rawData from 'lib/data.js';
import ChartData from 'lib/chart-data.js';
import { extent } from 'd3-array';
import { AxisLeft, AxisBottom } from '@vx/axis';
import { Group } from '@vx/group';
import { scaleTime, scaleLinear } from '@vx/scale';
import { Line, LinePath, Bar } from '@vx/shape';
import { localPoint } from '@vx/event';
import styles from './BitcoinPrice.scss';
const chartDimensions = (() => {
const margin = { top: 20, right: 20, bottom: 35, left: 75 };
const width = 800;
const height = 400;
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
return { margin, width, height, innerWidth, innerHeight };
})();
class BitcoinPrice extends React.Component {
constructor(props) {
super(props);
this.state = {
lineX: 0,
lineVisible: false,
};
this.chartData = new ChartData(rawData);
}
onMouseOver() {
this.setState({ lineVisible: true });
}
onMouseOut() {
this.setState({ lineVisible: false });
}
onMouseMove(e, data, xScale) {
const { margin } = chartDimensions;
const point = localPoint(e);
const x = point.x - margin.left;
console.log(`x`, x);
this.setState({ lineX: x });
}
render() {
const { data } = this.chartData;
const { margin, width, height, innerWidth, innerHeight } = chartDimensions;
const xScale = scaleTime({
range: [0, innerWidth],
domain: extent(data, (d) => d.date)
});
const yScale = scaleLinear({
range: [innerHeight, 0],
domain: extent(data, (d) => d.price)
});
const lineX = this.state.lineX;
const lineVisibility = this.state.lineVisible ? 'visible' : 'hidden';
return (
<div>
<h1>Example chart: Bitcion price over time</h1>
<p>Mouse X position: {lineX}</p>
<svg width={800} height={400} viewBox={`0 0 ${width} ${height}`}>
<Group top={margin.top} left={margin.left}>
{/* The bitcoin price line */}
<LinePath
data={data}
x={(d) => xScale(d.date)}
y={(d) => yScale(d.price)}
className={`${styles['path-line']} ${styles['path-price']}`}
/>
{/* The vertical line that follows the cursor when hovering */}
<Line
visibility={lineVisibility}
x1={0}
y1={0}
x2={0}
y2={innerHeight}
transform={`translate(${lineX}, 0)`}
className={styles['mouse-line']}
/>
{/* Left axis */}
<AxisLeft
scale={yScale}
/>
{/* Bottom axis */}
<AxisBottom
scale={xScale}
top={innerHeight}
/>
{/* Hover detection area */}
<Bar
width={innerWidth}
height={innerHeight}
className={styles['mouse-overlay']}
onMouseOver={() => this.onMouseOver()}
onMouseOut={() => this.onMouseOut()}
onMouseMove={(e) => this.onMouseMove(e, data, xScale)}
/>
</Group>
</svg>
</div>
)
}
}
export default BitcoinPrice;
【问题讨论】:
-
我认为您的性能问题与
mouseMove中的 setState 相关,如果您真的不需要在其中设置 setState,请忽略它并改用refs来更新 UI 和值检索。 -
@mamounothman 成功了——谢谢!我发布了更新的代码作为答案。
-
Glade 成功了,接受您的回答,以便将此问题标记为已回答。
-
我会在 1 天后做。
标签: reactjs