why the last tick doesn't have values - D3.js

家住魔仙堡 提交于 2021-01-28 20:06:07

问题


The last ticks in x-axis and y-axis don't have values drawn next to them. I cannot figure out why these values are missing.

This is the JS code :

var xAxisScale = d3.scale.linear()
         .domain([0, d3.max(data, function(d) { return d.x; })])
       .range([padding, containerWidth - padding * 2]);

    var xAxis = d3.svg.axis().scale(xAxisScale).orient("bottom");

    var xGuide = chartContainer.append('g')
      .attr("class", "xAxis")
      .call(xAxis)
      .attr('transform', 'translate(0 ,' + (containerHeight -padding) + ')');


    /* Code for adding y axis in chart
     * 
     * */
    var yAxisScale = d3.scale.linear()
      .domain([0, d3.max(data, function(d){return d.y})])
      .range([containerHeight-padding, padding ]);

    var yAxis = d3.svg.axis().scale(yAxisScale).orient("left");

    var yGuide = chartContainer.append('g')
      .attr("class", "yAxis")
      .call(yAxis)
      .attr('transform', 'translate('+padding + ',0)');

This is my live demo.


回答1:


This can be done by overriding the default behavior for determining tick values using axis.tickValues():

var yAxis = d3.svg.axis().scale(yAxisScale).orient("left")
  .tickValues(yAxisScale.ticks().concat(yAxisScale.domain()));

This still resorts to the automatically generated tick values by calling yAxisScale.ticks() which is the default behavior for D3's axes. These values are then supplemented with the outer bounds of your data values, i.e. the array returned by yAxisScale.ticks(). To set just the upper bound, if would be sufficient to specify yAxisScale.domain()[1], although it won't hurt having duplicate values in the array provided to .tickValues().

Doing it this way frees you from any hardcoding of tick values.

Have a look at this working example:

var padding = 70;

    	//Width and height
    	var containerWidth = 1000;
    	var containerHeight = 500;
    	var data = [{
    	  "x": 82,
    	  "y": 1730
    	}, {
    	  "x": 533,
    	  "y": 16385
    	}, {
    	  "x": 41,
    	  "y": 783
    	}, {
    	  "x": 20.5,
    	  "y": 5873
    	}, {
    	  "x": 553.5,
    	  "y": 25200
    	}, {
    	  "x": 61.5,
    	  "y": 30000
    	}, {
    	  "x": 184.5,
    	  "y": 2853
    	}, {
    	  "x": 1476,
    	  "y": 83775
    	}];
    	//Create scale functions
			var xScale = d3.scale.linear()
				
								 
    	var chartContainer = d3.select("body")
    	  .append("svg")
    	  .attr("class", "chartContainer")
    	  .attr("width", containerWidth)
    	  .attr("height", containerHeight);

    	$(".chartContainer").css({
    	  "background-color": "",
    	  "position": "absolute",
    	  "top": 50,
    	  "left": 15
    	});
      
								 
    	var xAxisScale = d3.scale.linear()
  			 .domain([0, d3.max(data, function(d) { return d.x; })])
    	   .range([padding, containerWidth - padding * 2]);

    	var xAxis = d3.svg.axis().scale(xAxisScale).orient("bottom")
    	  .tickValues(xAxisScale.ticks().concat(xAxisScale.domain()));
 
    	var xGuide = chartContainer.append('g')
    	  .attr("class", "xAxis")
    	  .call(xAxis)
    	  .attr('transform', 'translate(0 ,' + (containerHeight -padding) + ')');

xGuide.selectAll('path')
	  		.style({ fill: 'none', stroke: "#000"});
	  	xGuide.selectAll('line')
	  		.style({ stroke: "#000"});
    	/* Code for adding y axis in chart
    	 * 
    	 * */
    	var yAxisScale = d3.scale.linear()
    	  .domain([0, d3.max(data, function(d){return d.y})])
    	  .range([containerHeight-padding, padding ]);

    	var yAxis = d3.svg.axis().scale(yAxisScale).orient("left")
    	  .tickValues(yAxisScale.ticks().concat(yAxisScale.domain()[1]));

    	var yGuide = chartContainer.append('g')
    	  .attr("class", "yAxis")
    	  .call(yAxis)
    	  .attr('transform', 'translate('+padding + ',0)');

    	chartContainer.selectAll("circle")
    	  .data(data)
    	  .enter()
    	  .append("circle")
    	  .attr("cx", function(d) {
    	    return xAxisScale(d.x);
    	  })
    	  .attr("cy", function(d) {
    	    return yAxisScale(d.y);
    	  })
    	  .attr("r", 4)
    	  .attr("fill", "red")
    	  .attr({
    	    "z-index": "9999"
    	  });
    	  
    	  yGuide.selectAll('path')
	  		.style({ fill: 'none', stroke: "#000"});
	  	yGuide.selectAll('line')
	  		.style({ stroke: "#000"});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>



回答2:


Add .nice() to line 69 of your live demo. will solve the issue. See graph below for the end result.

For more details and explanation, please refer to this closed issue on the d3-scale library. mbostock commented on it on Dec 6, 2016 and provided the solution.




回答3:


You are using d3's automatic tick generator which makes a best guess on how best to draw your axes given the data in the chart.

You have two options for overriding this:

  1. Setting a number of tick values to show. For example:

    var xAxis = d3.svg.axis() .scale(xAxisScale) .orient("bottom") .ticks(10);

  2. Passing a tick values array to explicitly tell d3 what values you want on your x or y axis; like this:

    var xAxis = d3.svg.axis() .scale(xAxisScale) .orient("bottom") .tickValues([0, 100, 200, 300, 400]);

If you want to get rid of the ticks that are missing values (in your case, the outer ticks) just set .outerTickSize(0) on the x or y-axis.

You should also probably read up on the d3's axes API here.



来源:https://stackoverflow.com/questions/35314835/why-the-last-tick-doesnt-have-values-d3-js

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!