javascript - d3 - 使用 React 的单击事件由于质心坐标而响应缓慢

标签 javascript reactjs d3.js

我正在使用 React 和 d3 构建美国 map 。 我遇到了一个特殊的场景,我在 render 时在 jsx path 元素上分配了一个 clickhandler。

出于某种原因,我注意到当我单击时,事件似乎立即触发(因为我可以控制台日志),但弹出窗口状态需要多花几毫秒的时间。 这里奇怪的细微差别是,如果我从应该呈现的 text 元素中删除 xy 属性(见下文,使用 >.state-label 作为选择器),然后单击...它会按预期响应。 不完全确定为什么这些 text 元素会延长事件立即触发的时间,并且希望得到任何建议或想法。

import React, { Component } from "react";
import "components/general/NationalMap.css";
import * as d3 from "d3";
import { geoPath, geoAlbersUsa } from "d3-geo";
import {
  STATE_LABELS
} from "components/shared/Variables";

export default class NationalMap extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  mapClicks = (event, d) => {
    console.log('clicked')
    this.setState({showPopover: true}) // 

  };

  projection = ($width, $height) => {
    return geoAlbersUsa()
      .scale($width * 1.1)
      .translate([$width / 2, $height / 2]);
  };

  path = () => {
    return d3.geoPath().projection(this.projection(1300, 1300 * 0.6));
  };

  getUSNamesX = d => {
    let path = this.path();
    let xCentroid = path.centroid(d)[0];

    if (d.properties.STUSPS === "FL") {
      xCentroid = xCentroid + 10;
    }
    return xCentroid || null;
  };

  getUSNamesY = d => {
    let path = this.path();
    let yCentroid = path.centroid(d)[1];

    if (d.properties.STUSPS === "FL") {
      yCentroid = yCentroid;
    }
    return yCentroid || null;
    //return !isNaN(path.centroid(d)[1]) ? yCentroid : null;
  };

  getStateLabel = abbrev => {
    let label;

    STATE_LABELS.forEach(l => {
      if (l.abbrev === abbrev) {
        label = l.label;
      }
    });
    return label;
  };

  getStateLabelClass = d => {
    let stateclass_name = this.getStateClass(d);

    if (typeof stateclass_name !== "undefined") {
      if (stateclass_name.includes("full")) {
        stateclass_name = "state-label-active";
      }
      return stateclass_name;
    }
  };

  getStateClass = d => {
    if (typeof this.props.stateData !== "undefined") {
      let sc = [];
      let stateAbbrev = d.properties.STUSPS;
      let state = this.props.stateData[d.properties.STUSPS];

      if (typeof state !== "undefined") {
        if (state.race === "Y") {
          if (typeof state.win != "undefined") {
            if (state.win != " ") {
              sc.push(stateAbbrev + " " + state.win + "full");
            } else {
              sc.push(stateAbbrev + " Noresult");
            }
          } else {
            sc.push(stateAbbrev);
          }
        } else if (state.race === "N") {
          sc.push(stateAbbrev + " Noelection");
        }
      }
      return sc.join().replace(",", " ");
    }
  };

  render() {
    const usMapData = this.props.usData;
    const usDistricts = this.props.usDistrictsData;
    const currentMap = this.props.currentMap;
    const $width = 1300;
    const $height = $width * 0.6;
    const LOADING = this.state.isReady;


    return (
      <div className="nat-map-wrap">
        <div className="map-wrapper">
        {showPopover &&
          <div>My Popover</div>
        }
          {!LOADING && (
            <div className="presgov-map ismap">
              <svg
                viewBox={"0 10 " + $width + " " + $height}
                className={"natMapWrap " + currentMap}
              >
                {usMapData && (
                  <React.Fragment>
                    <g className="state-g-tag">
                      <g id="states" className="zoom-g">
                        {usMapData.map((d, i) => (
                          <path
                            key={`path-${i}`}
                            d={geoPath().projection(
                              this.projection($width, $height)
                            )(d)}
                            className={"state " + this.getStateClass(d)}
                            stroke="#fff"
                            strokeWidth={0.5}
                            onClick={evt =>
                              this.mapClicks()
                            }
                          />
                        ))}
                      </g>
                    </g>
                    <g id="statenames">
                      <g className="zoom-g">
                        {usMapData.map((d, i) => (
                          <text
                            key={`text-${i}`}
                            x={this.getUSNamesX(d)}
                            y={this.getUSNamesY(d)}
                            textAnchor="middle"
                            className={
                              "state-label "
                            }
                          >
                            {d.properties.STUSPS}
                          </text>
                        ))}
                      </g>
                    </g>
                  </React.Fragment>
                )}
              </svg>
            </div>
          )}
        </div>
      </div>
    );
  }
}

最佳答案

点击后,您将执行 4 项昂贵的操作:

  1. this.path(),它正在初始化投影和路径!
  2. path.centroid(d)[0]
  3. this.path()
  4. path.centroid(d)[1]

首先,我将创建 projectionpath 作为成员变量,这样您就可以在每次点击时停止重新创建它们(两次)。其次,仅调用一次 path.centroid ,如下所示(所有代码未经测试):

getUSNamesXY = d => {

    let centroid = this.path.centroid(d); //path is member

    if (d.properties.STUSPS === "FL") {
      centroid[0] = centroid[0] + 10;
    }
    return centroid || null;
  };

还有:

<g className="zoom-g">
{usMapData.map((d, i) => (
  <text
    key={`text-${i}`}
    transform="translate(" + {this.getUSNamesXY(d)} + ")"
    textAnchor="middle"
    className={
      "state-label "
    }
  >
    {d.properties.STUSPS}
  </text>
))}
</g>

关于javascript - d3 - 使用 React 的单击事件由于质心坐标而响应缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52284552/

相关文章:

javascript - 如何获取asp :Table cell values using Javascript?

javascript - 有没有办法在我的 html 页面上执行 JavaScript/JQuery 函数指定的时间然后停止执行?

javascript - UIWebView:我可以在任何网页中禁用 javascript alert() 吗?

javascript - jQuery fullCalendar 在标题上显示未定义

javascript - D3 JS点击时制作多边形

javascript - 显示 :none/visibility:hidden in case javascript is disabled 的回退

css - 使用样式组件创建变体的方法

javascript - 尝试理解 Flux 架构

javascript - 在 D3.js 强制布局网络的阈值函数中链接笔划宽度

javascript - 单击时如何使某些元素突出显示?