用scale拖动圆线性初始位置

时间:2019-01-16 15:02:23

标签: javascript reactjs typescript d3.js

我无法在图表中拖动圆圈。这是现场演示https://codesandbox.io/s/71loxoq65j

我的图表

echo number_format("150",2);

还有我正在调用图表的组件

import { event, select, Selection } from "d3-selection";
import { scaleLinear, ScaleLinear } from "d3-scale";
import { Axis, axisBottom, axisLeft } from "d3-axis";
import { line, Line } from "d3-shape";
import { drag } from "d3-drag";

interface IMargin {
  left: number;
  right: number;
  top: number;
  bottom: number;
}

interface IConfig {
  height: number;
  margin: IMargin;
  target: SVGSVGElement;
  width: number;
}

interface ISample {
  x: number;
  y: number;
}

export default class Trigger {
  private chart: Selection<SVGGElement, {}, null, undefined>;
  private xScale: ScaleLinear<number, number>;
  private yScale: ScaleLinear<number, number>;
  private xAxis: Axis<number>;
  private xAxisGroup: Selection<SVGGElement, {}, null, undefined>;
  private yAxis: Axis<number>;
  private yAxisGroup: Selection<SVGGElement, {}, null, undefined>;

  constructor(config: IConfig) {
    const w = config.width - config.margin.left - config.margin.right;
    const h = config.height - config.margin.top - config.margin.bottom;

    // create global chart object
    this.chart = select(config.target)
      .attr("width", config.width)
      .attr("height", config.height)
      .append("g")
      .attr(
        "transform",
        `translate(${config.margin.left}, ${config.margin.top})`
      );

    // create x scale function
    this.xScale = scaleLinear()
      .domain([0, 100])
      .range([0, w]);

    // create y scale function
    this.yScale = scaleLinear()
      .domain([0, 100])
      .range([h, 0]);

    // create x axis function
    this.xAxis = (axisBottom(this.xScale) as Axis<number>).ticks(5);

    // create y axis function
    this.yAxis = (axisLeft(this.yScale) as Axis<number>).ticks(5);

    // append x axis to chart and call xAxis function
    this.xAxisGroup = this.chart
      .append("g")
      .attr("class", "x axis")
      .attr("transform", `translate(0, ${h})`)
      .call(this.xAxis);

    // append y axis to chart and call yAxis function
    this.yAxisGroup = this.chart
      .append("g")
      .attr("class", "y axis")
      .call(this.yAxis);

    // add x axis description
    this.chart
      .append("text")
      .attr("x", w / 2)
      .attr("y", h + config.margin.bottom)
      .style("text-anchor", "middle")
      .text("foo");

    // add y axis description
    this.chart
      .append("text")
      .attr("x", -h / 2)
      .attr("y", -config.margin.left)
      .attr("transform", "rotate(-90)")
      .attr("text-anchor", "middle")
      .attr("alignment-baseline", "hanging")
      .text("bar");
  }

  public yellow(data: ISample[]) {
    // draw circles
    this.chart
      .selectAll("circle")
      .data(data)
      .enter()
      .append("circle")
      .attr("cx", d => this.xScale(d.x))
      .attr("cy", d => this.yScale(d.y))
      .attr("r", 8)
      .attr("fill", "orange")
      .attr("class", "circle")
      .call(
        drag().on("drag", function(d) {
          select(this).attr("cx", (d.x = event.x));
        })
      );
  }
}

您可以看到第一次拖动的初始位置是错误的。它总是从import * as React from "react"; import { render } from "react-dom"; import Chart from "./chart"; import "./styles.css"; const Trigger = () => { const chart: React.MutableRefObject<Chart | null> = React.useRef(null); const chartRef = React.useRef(null); const [start, setStart] = React.useState(20); const [end, setEnd] = React.useState(50); // run on did mount but never again React.useEffect(() => { chart.current = new Chart({ height: 320, margin: { bottom: 40, left: 50, right: 20, top: 10 }, target: chartRef.current!, width: 640 }); const yellow = [{ x: start, y: 50 }, { x: end, y: 50 }]; chart.current.yellow(yellow); }, []); return ( <div> <svg ref={chartRef} /> </div> ); }; const rootElement = document.getElementById("root"); render(<Trigger />, rootElement); 开始。圆圈跳到左侧。之后,一切都很好,并且可以按预期工作。我尝试遵循这个简单的示例https://bl.ocks.org/mbostock/22994cc97fefaeede0d861e6815a847e,但它没有任何规模。

我在做什么错了?

最好的问候, 米尔科

1 个答案:

答案 0 :(得分:1)

您需要将鼠标位置转换为图表的g

import { event, select, Selection, mouse } from "d3-selection";


  public yellow(data: ISample[]) {
    // draw circles
    var that = this;
    this.chart
      .selectAll("circle")
      .data(data)
      .enter()
      .append("circle")
      .attr("cx", d => this.xScale(d.x))
      .attr("cy", d => this.yScale(d.y))
      .attr("r", 8)
      .attr("fill", "orange")
      .attr("class", "circle")
      .call(
        drag().on("drag", function(d) {
          select(this).attr("cx", (d.x = mouse(that.chart.node())[0]));
        })
      );
  }