D3 bru sh лаг при движении - PullRequest
0 голосов
/ 26 мая 2020

работает на графике D3 с React. Я реализовал bru sh в d3.

Когда я прокручиваю bru sh, он работает нормально, но тормозит. Интересно, что если я удалю строку ниже (в NavChart. js), помеченную как проблема c, bru sh начнет работать нормально (без задержек). Эта строка, однако, важна, поскольку я обновляю переменную внутри ChartWrapper. js (называемую «выбор») с помощью хука реакции, который мне нужен для соединения диаграммы с помощью nav. Вот код:

ChartWrapper. js ->

import React, {useRef, useEffect, useState, useImperativeHandle} from 'react';
import  {select, selectAll, extent, axisBottom, axisLeft, scaleLinear, scaleTime, curve, line, curveCardinal, set} from 'd3';
import Chart from './Chart';
import NavChart from './NavChart';
import UsePrevious from './UsePrevious';

const MARGIN = {TOP: 50, BOTTOM: 50, LEFT: 50, RIGHT: 50};
const maxData = 10;
export default function ChartWrapper(props) {

    let [selection, setSelection] = useState([props.data[0].time, props.data[1].time]);
    const previousSelection = UsePrevious(selection);
    let [first, setFirst] = useState(true);
    const svgRef = useRef();
    let chart = null;
    let nav = null;
    const navRef = useRef();    

    useEffect(
        () => {
                console.log(`selection is : ${selection}`);
                //Chart component
                chart = new Chart(MARGIN, svgRef, props.data, props.xAxisText, props.yAxisText);
                // navigation component (Both aren't connected right now)
                nav = new NavChart(MARGIN, navRef, props.data, previousSelection.current, selection, setSelection, first);
                setFirst(false);


        }, [props.data, previousSelection, selection, first]        
    );

    return (
        <div>
            <svg ref = {svgRef} width = {700} height = {400}></svg>
            <br /><br/>
            <svg ref = {navRef} width = {700} height = {75}></svg>
        </div>
    );
}

NavChart. js ->

import {select,
    selectAll,
    extent,
    axisBottom,
    axisLeft,
    scaleLinear,
    scaleTime,
    line,
    brushX,
    event
} from 'd3';

const PADDING = {TOP: 10, BOTTOM: 30};

export default class NavChart {
    constructor(MARGIN, svgRef, data, previousSelection, selection, setSelection, firstTime) {

        this.svg = select(svgRef.current);
        this.MARGIN = MARGIN;
        this.data = data;

        this.chartWidth = this.svg.attr('width') - MARGIN.LEFT - MARGIN.RIGHT;
        this.chartHeight = this.svg.attr('height') - PADDING.TOP - PADDING.BOTTOM;

        this.xScale = scaleTime()
                        .domain(extent(
                            this.data.map((d) => d.time)
                        ))
                        .range([0, this.chartWidth]);

        this.yScale = scaleLinear()
                        .domain(extent(
                            this.data.map((d) => d.value)
                        ))
                        .range([this.chartHeight, 0]);

        this.myLine = line()
                        .x((d) => this.xScale(d.time))
                        .y((d) => this.yScale(d.value));

        this.chartArea = this.svg.append('g')
                        .attr('transform', `translate(${MARGIN.LEFT}, ${PADDING.TOP})`);

        this.chartArea.append('rect')
                        .attr('x', 0)
                        .attr('y', 0)
                        .attr('width', this.chartWidth)
                        .attr('height', this.chartHeight)
                        .attr('fill', '#f2f2f2');

        this.pathsG = this.chartArea.append('g')
                        .attr('class', 'pathsG')
                        .attr('transform', `translate(0,0)`);

        this.xAxis = axisBottom(this.xScale);

        this.xAxisG = this.chartArea.append('g')
                                       .attr('transform', `translate(0, ${this.chartHeight})`);

        this.xAxisG.call(this.xAxis);

        this.pathsG.selectAll('path')
            .data([this.data])
            .join('path')
            .attr('d', (value) => this.myLine(value))
            .attr('fill', 'none')
            .attr('stroke', '#D073BA')
            .attr('stroke-width', '1.5');

        this.circlesVar = this.pathsG.selectAll('.circle')
            .data(data);

        this.circlesVar.enter().append('circle')
            .attr('class', 'circle')
            .attr('r', '3')/*(value) => 
                    value.time > selection[0] && value.time <= selection[1] ? 4 : 2)*/
            .style('fill', '#D073BA')
            .attr('cx', (d) => this.xScale(d.time))
            .attr('cy', (d) => this.yScale(d.value));

        this.brushG = this.chartArea.append('g')
                        .attr('class', 'brush');

        this.brush = brushX().extent([
            [0, 0],
            [this.chartWidth, this.chartHeight]
        ]).on('start brush end', () => {
            if (event.selection  && (event.sourceEvent != null)) {
                const timeSelection = event.selection.map(this.xScale.invert);
                setSelection(timeSelection);    // This line is problematic
            }
        });
         this.brushG.call(this.brush)
                        .call(this.brush.move, selection.map(this.xScale));
    }
}

Я понимаю, что изменение переменной выбора (через метод setSelection в NavChart. js) вызовет перехватчик useEffect () в ChartWrapper. js, но я не знаю, почему это вызывает задержку. Нужно ли добавлять переход в bru sh?

Изменить: Ссылка на код онлайн -> 'https://stackblitz.com/edit/react-jxgqe8'

1 Ответ

2 голосов
/ 26 мая 2020

Текущий код прослушивает перекрывающиеся события и, следовательно, несколько раз реагирует параллельно.

Достаточно прослушивания события end, а не прослушивания start, brush и end все вместе:

    this.brush = brushX().extent([
        [0, 0],
        [this.chartWidth, this.chartHeight]
    ]).on('end', () => {
        if (event.selection  && (event.sourceEvent != null)) {
            const timeSelection = event.selection.map(this.xScale.invert);
            setSelection(timeSelection);
        }
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...