代码之家  ›  专栏  ›  技术社区  ›  Jimmy

在D3 X轴图形上放置自定义标签

  •  1
  • Jimmy  · 技术社区  · 7 年前

    我正在用我的图表进步,它似乎大部分工作。然而,我很难把我的数据值放在x轴上。在这种情况下,应该有3个x轴标签(test1、test2、test3)。

    // Data
    var dataset = [{
        name: "test1",
        y: 0.1
      },
      {
        name: "test2",
        y: 0.6
      },
      {
        name: "test3",
        y: 0.9
      }
    ];
    

    它似乎只是通过有多少个条目(0,1,2)来标记它,而不是使用名称。我试图改变的是:

    var line = d3.line()
      .x(function(d, i) {
        return xScale(i);
    

    var line = d3.line()
      .x(function(d, i) {
        return xScale(d.name);
    

    不幸的是,这没有工作,我不知道我可以尝试下一步。这里是完整的代码,如果这有帮助。

    http://jsfiddle.net/spadez/cfz3g4w2/

    1 回复  |  直到 7 年前
        1
  •  1
  •   Mark    7 年前

    你的x数据使用了错误的刻度。你有离散的数据,想要一个 ordinal scale .

    var xScale = d3.scalePoint()
      .domain(dataset.map(d => d.name)) // input is an array of names
      .range([0, width]); // output
    

    运行代码:

    // Data
    var dataset = [{
        name: "test1",
        y: 0.1
      },
      {
        name: "test2",
        y: 0.6
      },
      {
        name: "test3",
        y: 0.9
      }
    ];
    
    // Count number of datapoints
    var n = Object.keys(dataset).length;
    
    // Find max of the data points for Y axis
    var mymax = Math.max.apply(Math, dataset.map(function(o) {
      return o.y;
    }));
    
    // 2. Use the margin convention practice 
    var margin = {
        top: 50,
        right: 50,
        bottom: 50,
        left: 50
      },
      width = window.innerWidth - margin.left - margin.right;
    height = window.innerHeight - margin.top - margin.bottom;
    
    
    // 5. X scale will use the index of our data
    var xScale = d3.scalePoint()
      .domain(dataset.map(d => d.name)) // input
      .range([0, width]); // output
    
    // 6. Y scale will use the randomly generate number 
    var yScale = d3.scaleLinear()
      .domain([0, mymax]) // input 
      .range([height, 0]); // output 
    
    // 7. d3's line generator
    var line = d3.line()
      .x(function(d, i) {
        return xScale(d.name);
      }) // set the x values for the line generator
      .y(function(d) {
        return yScale(d.y);
      }) // set the y values for the line generator 
      .curve(d3.curveMonotoneX) // apply smoothing to the line
    
    // 1. Add the SVG to the page and employ #2
    var svg = d3.select("body").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
    // 3. Call the x axis in a group tag
    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(xScale)); // Create an axis component with d3.axisBottom
    
    // 4. Call the y axis in a group tag
    svg.append("g")
      .attr("class", "y axis")
      .call(d3.axisLeft(yScale)); // Create an axis component with d3.axisLeft
    
    // 9. Append the path, bind the data, and call the line generator 
    svg.append("path")
      .datum(dataset) // 10. Binds data to the line 
      .attr("class", "line") // Assign a class for styling 
      .attr("d", line); // 11. Calls the line generator 
    
    // 12. Appends a circle for each datapoint 
    svg.selectAll(".dot")
      .data(dataset)
      .enter().append("circle") // Uses the enter().append() method
      .attr("class", "dot") // Assign a class for styling
      .attr("cx", function(d, i) {
        return xScale(d.name)
      })
      .attr("cy", function(d) {
        return yScale(d.y)
      })
      .attr("r", 5)
      .on("mouseover", function(a, b, c) {
        console.log(a)
        this.attr('class', 'focus')
      })
      .on("mouseout", function() {})
      .on("mousemove", mousemove);
    
    var focus = svg.append("g")
      .attr("class", "focus")
      .style("display", "none");
    
    focus.append("circle")
      .attr("r", 4.5);
    
    focus.append("text")
      .attr("x", 9)
      .attr("dy", ".35em");
    
    svg.append("rect")
      .attr("class", "overlay")
      .attr("width", width)
      .attr("height", height)
      .on("mouseover", function() {
        focus.style("display", null);
      })
      .on("mouseout", function() {
        focus.style("display", "none");
      })
      .on("mousemove", mousemove);
    
    function mousemove() {
      var x0 = x.invert(d3.mouse(this)[0]),
        i = bisectDate(data, x0, 1),
        d0 = data[i - 1],
        d1 = data[i],
        d = x0 - d0.date > d1.date - x0 ? d1 : d0;
      focus.attr("transform", "translate(" + x(d.date) + "," + y(d.close) + ")");
      focus.select("text").text(d);
    }
    .line {
      fill: none;
      stroke: #ffab00;
      stroke-width: 3;
    }
    
    .overlay {
      fill: none;
      pointer-events: all;
    }
    
    /* Style the dots by assigning a fill and stroke */
    
    .dot {
      fill: #ffab00;
      stroke: #fff;
    }
    
    .focus circle {
      fill: none;
      stroke: steelblue;
    }
    <!-- Load in the d3 library -->
    <script src="https://d3js.org/d3.v5.min.js"></script>