d3.js: Порядковая шкала

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

var xScale = d3.scale.ordinal()
       .domain(xExtents)
       .range([padding, w - padding * 2]);

вот пример кода, извините за размещение всего javascript и HTML в одном месте.

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js"></script>
		<style type="text/css">
			
			.axis path,
			.axis line {
				fill: none;
				stroke: black;
				shape-rendering: crispEdges;
			}
			
			.axis text {
				font-family: sans-serif;
				font-size: 11px;
			}

			.y1 {
				fill: white;
				stroke: orange;
				stroke-width: 1.5px;
			}

			.y2 {
				fill: white;
				stroke: red;
				stroke-width: 1.5px;
			}

			.y3 {
				fill: white;
				stroke: steelblue;
				stroke-width: 1.5px;
			}

			.line {
			  fill: none;
			  stroke-width: 1.5px;
			}

			div.tooltip {
	            position: absolute;
	            text-align: center;
	            width: 50px;
	            height: 10px;
	            padding: 5px;
	            font: 10px sans-serif;
	            background: whiteSmoke;
	            border: solid 1px #aaa;
	            pointer-events: none;
	            box-shadow: 2px 2px 1px #888;
            }

            .legend {
	            padding: 5px;
	            font: 10px sans-serif;
	            background: yellow;
	            box-shadow: 2px 2px 1px #888;
            }

            .title {
            	font: 13px sans-serif;
            }

		</style>
	</head>
	<body>
		<script type="text/javascript">

    //Width and height
    var w = 500;
    var h = 300;
    var padding = 50;
      
          
    var dataset = [
        [ 
            {x: "USA", y: 0}, 
            {x: "UK", y: 0}, 
            {x: "BRAZIL", y: 2}, 
            {x: "KORIA", y: 0}, 
            {x: "JAPAN", y: 0}, 
            {x: "CHINA", y: 0}
        ],
        [
             {x: "USA", y: 3}, 
            {x: "UK", y: 4}, 
            {x: "BRAZIL", y: 1}, 
            {x: "KORIA", y: 3}, 
            {x: "JAPAN", y: 1}, 
            {x: "CHINA", y: 2}
        ],
        [
             {x: "USA", y: 2}, 
            {x: "UK", y: 0}, 
            {x: "BRAZIL", y: 2}, 
            {x: "KORIA", y: 3}, 
            {x: "JAPAN", y: 4}, 
            {x: "CHINA", y: 1}
        ]
    ];

    var color_hash = {  0 : ["apple", "green"],
					    1 : ["mango", "orange"],
					    2 : ["cherry", "red"]
					  }                      
    
    // Define axis ranges & scales        
    var yExtents = d3.extent(d3.merge(dataset), function (d) { return d.y; });
    var xExtents = d3.extent(d3.merge(dataset), function (d) { return d.x; });
         
	var xScale = d3.scale.ordinal()
	       .domain(xExtents)
	       .range([padding, w - padding * 2]);

	var yScale = d3.scale.linear()
	       .domain([0, yExtents[1]])
	       .range([h - padding, padding]);


	// Create SVG element
	var svg = d3.select("body")
	    .append("svg")
	    .attr("width", w)
	    .attr("height", h);


	// Define lines
	var line = d3.svg.line()
	       .x(function(d) { return x(d.x); })
	       .y(function(d) { return y(d.y1, d.y2, d.y3); });

	var pathContainers = svg.selectAll('g.line')
	.data(dataset);

	pathContainers.enter().append('g')
	.attr('class', 'line')
	.attr("style", function(d) {
		return "stroke: " + color_hash[dataset.indexOf(d)][1]; 
	});

	pathContainers.selectAll('path')
	.data(function (d) { return [d]; }) // continues the data from the pathContainer
	.enter().append('path')
	  .attr('d', d3.svg.line()
	    .x(function (d) { return xScale(d.x); })
	    .y(function (d) { return yScale(d.y); })
	  );

	// add circles
	pathContainers.selectAll('circle')
	.data(function (d) { return d; })
	.enter().append('circle')
	.attr('cx', function (d) { return xScale(d.x); })
	.attr('cy', function (d) { return yScale(d.y); })
	.attr('r', 3); 
	  
   	//Define X axis
	var xAxis = d3.svg.axis()
	        .scale(xScale)
	        .orient("bottom")
	        .ticks(5);

	//Define Y axis
	var yAxis = d3.svg.axis()
	        .scale(yScale)
	        .orient("left")
	        .ticks(5);

	//Add X axis
	svg.append("g")
	.attr("class", "axis")
	.attr("transform", "translate(0," + (h - padding) + ")")
	.call(xAxis);

	//Add Y axis
	svg.append("g")
	.attr("class", "axis")
	.attr("transform", "translate(" + padding + ",0)")
	.call(yAxis);

	// Add title	  
	svg.append("svg:text")
		   .attr("class", "title")
	   .attr("x", 20)
	   .attr("y", 20)
	   .text("Fruit Sold Per Hour");


	// add legend   
	var legend = svg.append("g")
	  .attr("class", "legend")
	  .attr("x", w - 65)
	  .attr("y", 25)
	  .attr("height", 100)
	  .attr("width", 100);

	legend.selectAll('g').data(dataset)
      .enter()
      .append('g')
      .each(function(d, i) {
        var g = d3.select(this);
        g.append("rect")
          .attr("x", w - 65)
          .attr("y", i*25)
          .attr("width", 10)
          .attr("height", 10)
          .style("fill", color_hash[String(i)][1]);
        
        g.append("text")
          .attr("x", w - 50)
          .attr("y", i * 25 + 8)
          .attr("height",30)
          .attr("width",100)
          .style("fill", color_hash[String(i)][1])
          .text(color_hash[String(i)][0]);

      });
		</script>
	</body>
</html>


person Abdul Rehman    schedule 05.12.2015    source источник
comment
что возвращает xExtents?   -  person Tarun Dugar    schedule 05.12.2015
comment
о, так что я должен использовать, чтобы вернуть все значения?   -  person Abdul Rehman    schedule 05.12.2015
comment
нет, я имею в виду, что содержит xExtents? Какова его ценность?   -  person Tarun Dugar    schedule 05.12.2015
comment
он держит США и Китай.   -  person Abdul Rehman    schedule 05.12.2015


Ответы (2)


Если вы хотите отобразить разные категории по оси x (в вашем случае есть пять стран с соответствующими данными), настройка шкалы x должна использовать rangeBands или rangeRoundBands для порядковых данных. (см. ordinal.rangeBands и ordinal.rangeRoundBands в официальных документах API).

var xScale = d3.scale.ordinal()
   .domain(xExtents)
   .rangeRoundBands([padding, w - padding * 2], 0.1);

range часто используется с линейным типом данных. Надеюсь это поможет.

person fengshuo    schedule 05.12.2015

Первая проблема:

Используйте это https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js

Вместо этого http://mbostock.github.com/d3/d3.js

Вторая проблема:

d3.extent(d3.merge(dataset), function (d) { return d.x; }

вернется ["BRAZIL", "USA"]

Вам нужны все уникальные страны.

var countries = d3.merge(dataset).map(function(d){return d.x});
countries = d3.set(countries).values();//unique countries


var xScale = d3.scale.ordinal()
       .domain(countries)
       .rangeBands([padding, w - padding * 2], 1);

это вернет ["USA", "UK", "BRAZIL", "KORIA", "JAPAN", "CHINA"]

Последняя проблема:

var xScale = d3.scale.ordinal()
       .domain(countries)
       .rangeBands([padding, w - padding * 2], 1);//with ordinals we give range bands

Рабочий код здесь

Надеюсь это поможет!

person Cyril Cherian    schedule 05.12.2015