javascript - 为什么我的条形图的前两个文本标签没有显示?

标签 javascript d3.js

我已经实现了一个基本上工作正常的条形图。但是,在条形图上放置标签时,我注意到前两个条形图的标签未显示在它们各自的矩形上方。附加 <text>我绑定(bind)与 <rect> 相同的数据集的元素元素。

g.selectAll("text")       
      .data(dataset)  // same dataset for the texts as for the bars     
      .enter()       
      .append("text")  
        // ...more styling...

但是,虽然显示了所有条形,但缺少前两个矩形的标签。看看下面的演示,它显示了问题:

const dataset=[
  {
    "Month": "2013_09",
    "Count": 1
  },
  {
    "Month": "2013_10",
    "Count": 291
  },
  {
    "Month": "2013_11",
    "Count": 763
  },
  {
    "Month": "2013_12",
    "Count": 853
  }
];
	dataset.forEach(d=>d.Count=+d.Count);
	let margin={top:10,right:10,bottom:90,left:40}; 
	let width= 600-margin.left-margin.right;
	let height= 400-margin.top-margin.bottom;
	
	const svg = d3.select(".div1")                 
	.append("svg")  
	.attr("width", width+margin.left+margin.right)       
	.attr("height", height+margin.top+margin.bottom)   
	.attr("style", "outline: thin solid red;") 
	
	let g=svg.append("g")
		.attr("transform","translate(" +margin.left+ ", " +margin.top+ ")");

	g.append("text")
	  	.attr("class","x label")
	  	.attr("x", width/2)
	  	.attr("y", height+76)
	  	.attr("font-size","20px")
	  	.attr("text-anchor","middle")
	  	.text("Month")

	 g.append("text")
	  	.attr("class","y label")
	  	.attr("x", -height/2+50)
	  	.attr("y", -40)
	  	.attr("font-size","20px")
	  	.attr("text-anchor","end")
	  	.text("")
	  	.attr("transform","rotate(-90)")
	  
	let x = d3.scaleBand() 
				.domain(dataset.map(d=>d.Month)) 
            .range([0, width]) 
				.paddingInner(0.3)
				.paddingOuter(1)
	  
	
	let y = d3.scaleLinear() 
            .domain([0, d3.max(dataset,d=>d.Count)+80]) 
            .range([height, 0]);
	 
	g.selectAll("text")       
      .data(dataset)       
      .enter()       
      .append("text")  
	   .attr("font-size","11px")
	  	.attr("text-anchor","middle")
      .text((d) => d.Count)
		.attr("y",d=>y(d.Count)-3)
	   .attr("x",(d)=>x(d.Month)+4);
	 
	 
	let leftAxis=d3.axisLeft(y)
		.ticks(8)
		.tickFormat(d=>d);
	g.append("g")
			.attr("class","left axis")
	  	  	.attr("transform","translate(0,0)")
			.call(leftAxis)
	 
	let rects=g.selectAll("rect")       
		.data(dataset)      
		.enter()     
		.append("rect") 
		.attr("y",d=>y(d.Count)) 
		.attr("x",d=>x(d.Month))
		.attr("width",x.bandwidth) 
		.attr("height",d=>height-y(d.Count)) 
		.attr("fill","blue") 

	let bottomAxis=d3.axisBottom(x);
	  g.append("g")
	  		.attr("class", "x axis")
	  		.attr("transform","translate(0,"+height+")")
	  		.call(bottomAxis)
	  		.selectAll("text")
	  		.attr("y","10")
	  		.attr("x","-5")
	  		.attr("text-anchor","end")
	  		.attr("transform","rotate(-40)");

  
<script src="https://d3js.org/d3.v5.js"></script>

<div class="div1" ></div>

最佳答案

以下将标签附加到条形图的部分没有像您预期的那样工作:

g.selectAll("text")       
  .data(dataset)       
  .enter()       
  .append("text")  

其实你之前已经追加了<text> g 的元素元素,即轴的标签。以上选择将选择那些文本作为前两个元素。绑定(bind)数据时,这些元素已经存在,因此不属于输入选择的一部分。事实上,如果您使用浏览器的开发人员工具来检查,例如Month 标签你会发现一个 __data__该元素上的属性表明数据已绑定(bind)到现有文本元素,这显然不是您想要的。

基本上有两种解决方法:

  1. 将轴的标签附加到另一组。这为轴、条和标签创建了不同的 DOM 子树,这在分离方面可能是一件好事。选择一个子树中的文本将找到另一个子树中包含的文本。

  2. 在为数据连接创建选择时使用更具体的选择器字符串。或者,使用 g.selectAll(null)因为条上还没有标签。看看Selecting null: what is the reason behind 'selectAll(null)' in D3.js?解释为什么这是首选方式。

每种方法都能够自行解决您的问题。尽管如此,您可能需要考虑使用包含这两种方法的组合解决方案,因为这将使您的生活更轻松,因为它会为您的 SVG 创建更简洁的代码。

旁注:这适用于 <rect>表示条形的元素,因为在进行该选择之前不存在任何矩形。尽管如此,选择您确定不存在的元素的首选和最惯用的方法是使用 d3.selectAll(null) .

下面的演示展示了如何实现 2. 使其工作:

const dataset=[
  {
    "Month": "2013_09",
    "Count": 1
  },
  {
    "Month": "2013_10",
    "Count": 291
  },
  {
    "Month": "2013_11",
    "Count": 763
  },
  {
    "Month": "2013_12",
    "Count": 853
  }
];
	dataset.forEach(d=>d.Count=+d.Count);
	let margin={top:10,right:10,bottom:90,left:40}; 
	let width= 600-margin.left-margin.right;
	let height= 400-margin.top-margin.bottom;
	
	const svg = d3.select(".div1")                 
	.append("svg")  
	.attr("width", width+margin.left+margin.right)       
	.attr("height", height+margin.top+margin.bottom)   
	.attr("style", "outline: thin solid red;") 
	
	let g=svg.append("g")
		.attr("transform","translate(" +margin.left+ ", " +margin.top+ ")");

	g.append("text")
	  	.attr("class","x label")
	  	.attr("x", width/2)
	  	.attr("y", height+76)
	  	.attr("font-size","20px")
	  	.attr("text-anchor","middle")
	  	.text("Month")

	 g.append("text")
	  	.attr("class","y label")
	  	.attr("x", -height/2+50)
	  	.attr("y", -40)
	  	.attr("font-size","20px")
	  	.attr("text-anchor","end")
	  	.text("")
	  	.attr("transform","rotate(-90)")
	  
	let x = d3.scaleBand() 
				.domain(dataset.map(d=>d.Month)) 
            .range([0, width]) 
				.paddingInner(0.3)
				.paddingOuter(1)
	  
	
	let y = d3.scaleLinear() 
            .domain([0, d3.max(dataset,d=>d.Count)+80]) 
            .range([height, 0]);
	 
	g.selectAll(null)       
      .data(dataset)       
      .enter()       
      .append("text")  
	   .attr("font-size","11px")
	  	.attr("text-anchor","middle")
      .text((d) => d.Count)
		.attr("y",d=>y(d.Count)-3)
	   .attr("x",(d)=>x(d.Month)+4);
	 
	 
	let leftAxis=d3.axisLeft(y)
		.ticks(8)
		.tickFormat(d=>d);
	g.append("g")
			.attr("class","left axis")
	  	  	.attr("transform","translate(0,0)")
			.call(leftAxis)
	 
	let rects=g.selectAll(null)       
		.data(dataset)      
		.enter()     
		.append("rect") 
		.attr("y",d=>y(d.Count)) 
		.attr("x",d=>x(d.Month))
		.attr("width",x.bandwidth) 
		.attr("height",d=>height-y(d.Count)) 
		.attr("fill","blue") 

	let bottomAxis=d3.axisBottom(x);
	  g.append("g")
	  		.attr("class", "x axis")
	  		.attr("transform","translate(0,"+height+")")
	  		.call(bottomAxis)
	  		.selectAll("text")
	  		.attr("y","10")
	  		.attr("x","-5")
	  		.attr("text-anchor","end")
	  		.attr("transform","rotate(-40)");

 
<script src="https://d3js.org/d3.v5.js"></script>

<div class="div1" ></div>

关于javascript - 为什么我的条形图的前两个文本标签没有显示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57908130/

相关文章:

javascript - 调用按键 :Value pair in Google Apps Script is returning "Undefined" instead of the value

javascript - 遍历页面上的所有 <div> 标签

javascript - D3 - 更新时元素的正确数量,但值错误

javascript - 使用 JavaScript 从外部图像获取颜色

javascript - 将图表放置在左上角

javascript - 如何在 Amazon S3 上托管的网站内绘制数据图表

d3.js — 从二维数组创建 HTML 表但排除第一个内部数组?

JavaScript 方括号作为变量值

javascript - 如何在Init方法中调用函数?

javascript - 提交 MVC 后禁用 BootstrapButton