Компонент реагировать на то, что участки графика Д3


Редактировать: если есть лучший способ, чтобы сделать это воспроизводимость, пожалуйста, дайте мне знать. Я могу создать некоторые фиктивные данные и вставьте его в сайт CodePen, но это не действительно отражают взаимодействие с реагировать, что требуется.

Мне нужно построить несколько среагировать Д3 компоненты для веб-приложения, что я строю - я хочу убедиться, что первый делается правильно, прежде чем двигаться на следующий.

Трудно получить полностью рабочую точных примеру, однако вот полный код компонента (с моими мыслями ниже):

Примечание: компонент может показаться длинным, но большую часть кода просто получать осей и сетки. В общем я думаю, что это короткое компонент..

import React, { Component } from 'react';
import * as d3 from "d3";

class D3Scatter extends Component {

    // When component mounts, get
    componentDidMount() {
        const context = this.setContext();
        this.drawScatter(context);  
    }

    componentDidUpdate() {
        var context = d3.select(`#${this.props.svgID}`);
        context.remove();

        context = this.setContext();
        this.drawScatter(context);  
    }

    // This adds the SVG to the <div ref="scatter"> with some attrs
    setContext() {
        const { height, width, svgID } = this.props;
        return d3.select(this.refs.scatter).append('svg')
            .attr('id', svgID)
            .attr('width', '100%')
            .attr('height', '100%')
            .attr('viewBox', "0 0 " + width + " " + height)
            .attr('preserveAspectRatio', "xMaxYMax")

            .append('g')
            .attr('transform', `translate(25, 25)`);
    }

    // drawScatter called each time new props are passed
    drawScatter(context) {    
        const { 
            // data
            playerData,
            colorData,

            // formatting vals
            padding,
            margin, 
            height, 
            width,

            // chart parameters
            chartType,
            position,
            teamName, 
            playerName,
            xColname,
            yColname

        } = this.props;


        // Fit The Data to the SVG size and width
        var xScale = d3.scaleLinear()
            .domain(d3.extent(playerData, d => d[xColname]))
            .range([padding, width - padding])

        var yScale = d3.scaleLinear()
            .domain(d3.extent(playerData, d => d[yColname]))
            .range([height - padding, padding])

        var xAxis = d3.axisBottom(xScale)
            .tickSize(2*padding-height)
            .tickSizeOuter(0);

        var yAxis = d3.axisLeft(yScale)
            .tickSize(-width - 2*padding)
            .tickSizeOuter(0);


        // Size Scale for the markers
        // if a certain playerName or teamName is passed, change marker size
        var sizeScale = (player) => {
            // console.log("playerName:", playerName)
            // console.log("teamName:", teamName)
            if(player.playerFullName === playerName) {
                return "24px";
            } else if(player.teamName === teamName) {
                return "12px";
            } else {
                return "6px";
            }
        }

        // also change color for certain teamName or playerName passed
        var colorScale = (player) => {
            if(player.playerFullName === playerName) {
                var playersTeam = playerData
                    .filter(d => d.playerFullName === playerName)
                    .map(d => d.teamName)
                var thisColor = colorData
                    .filter(d => d.teamname === playersTeam)
                    .map(d => d.colorhex1)
                return thisColor;
            }
            else if(player.teamName === teamName) {
                var teamColor = colorData
                    .filter(d => d.teamname === teamName)
                    .map(d => d.colorhex1);
                return teamColor;
            } else {
                return '#DDD'; 
            }
        }

        // append the circles onto the page
        context
            .append('g')
            .selectAll("circle")
            .data(playerData)
            .enter()
            .append("circle")
                .attr("cx", d => xScale(d[xColname]))
                .attr("cy", d => yScale(d[yColname]))
                .attr("r", d => sizeScale(d))
                .attr("fill", d => colorScale(d))
                .attr("stroke", "#FFF")


        // Title, Y-Axis Name, X-Axis Name, Y-Axis Lines, X-Axis Lines
        context
            .append("text")
                .attr("x", width/2)
                .attr("y", padding)
                .attr("dy", "-1.5em")
                .style("text-anchor", "middle")
                .style("font-size", "2.5em") 
                .text(`Highlighting ${teamName} and ${playerName}!`)

        context
            .append("text")
                .attr("transform", "rotate(-90)")
                .attr("x", -height/2) // 
                .attr("y", padding)
                .attr("dy", "-2.5em") // gap from axis numbers
                .style("font-size", "1.5em") // axis name size
                .style("text-anchor", "middle")
                .text(`Player ${yColname}`)

        context
            .append("text")
                .attr("x", width/2)
                .attr("y", height - padding)
                .attr("dy", "2.5em")
                .style("font-size", "1.5em")
                .style("text-anchor", "middle")
                .text(`Player ${xColname}`)

        context
            .append("g")
                .attr("transform", "translate(0," + (height-padding) + ")")
                .call(xAxis);

        context
            .append("g")
            .attr("transform", "translate(" + padding + ",0)")
            .call(yAxis);

        return context
    }

    render() {

        const { gridID } = this.props;
        return (
            <div id={gridID} ref="scatter"></div>
        )
    }
}

export default D3Scatter;

Существует ряд реквизит переданные этот компонент, который я разбила на 3 разных ведер:

  1. данные реквизиты

    • playerData: все данные, которые получает нанесены
    • colorData: есть цвета для каждой команды (карты teamName в цвет)
  2. реквизит форматирования

    • padding, margin, height, width все используемые для СВГ
  3. родительского компонента государственного реквизит (для фильтрации playerData)

    • chartType: (не привыкла еще)
    • position: (не привыкла еще)
    • `teamName: используется для настройки цвета / размеры
    • playerName: используется для настройки цвета / размеры
    • xColname: изменения ключа в playerData используется для оси X значения
    • yColname: изменения ключа в playerData используется для оси Y значения

Мой контейнер приложения (тот, который вызывает D3Scatter) имеет chartType, position, teamName, playerName, xColname и yColname в его состояние, и передает вниз D3Scatter в зависимости от того, какие кнопки / Выберите виджеты выбраны.

В конце концов, я хочу добавить переходы / анимации, так что когда xColname и yColname обновляются, очки, скольжение на их новые места. Я также планирую добавить подсказку и потенциально другие onClick эффекты, но я не сделал те еще. В настоящее время я переживаю ли я обновить карту (если я правильно с использованием компонентов цикла), и другие общие рекомендации.

Последний, пример того, как это называется в его родительский компонент:

<D3Scatter
    gridID="graph1"
    svgID={'d3-scatterplot'}
    playerData={playerSeasonData}
    colorData={mlbLogos}

    height={window.innerWidth*0.425}
    width={window.innerWidth*0.85}
    padding={50}
    margins={{top: 80, right: 35, bottom: 80, left: 25}}

    chartType={null}
    xColname={statNameX}
    yColname={statNameY}
    position={position}
    teamName={selectedTeam && selectedTeam.label}
    playerName={"Jay Bruce"} />


154
3
задан 15 апреля 2018 в 03:04 Источник Поделиться
Комментарии
1 ответ

Я думал о нечестивый союз D3 и прежде чем реагировать, и я был бы осторожен. Я бы сказал, что до сих пор, ваш код выглядит нормально, и если вы умеете с высокой степенью достоверности вам не нужно гораздо больше, чем это, тогда ты в порядке.

Однако, я подозреваю, что вы только приступили к делу, и это все будущие усовершенствования, которые оставят вас биться головой (особенно обработчиков входных и анимации).

Я не думаю, что проблема в том, что Д3 не любит играть с реагировать (хотя я знаю, что есть такие закидоны), а то, что графика-это сложная тема. Они имеют свой собственный абстрактный язык, и большинство людей не владеет.

Вы могли бы рассмотреть, используя новый график-части. Если вы хотите более прочную основу для строительства, вы можете посмотреть на оберточной Вега в собственных компонентов. Или вы может хотите просто посмотреть, что еще там есть: https://npms.io/search?q=react+графика.

Вот отличное видео с более глубокого объяснения моего предупреждения: недостающие абстракции графиков - Крис Тревино - реагировать конф 2018

0
ответ дан 5 ноября 2018 в 07:11 Источник Поделиться