d3圆环图弧检索错误的数据

时间:2017-03-11 13:24:19

标签: javascript html css d3.js svg

我有一个带有两个弧的d3圆环图,主弧边缘在鼠标悬停时向d对象检索错误的数据。休息弧中的所有区域显示日志中的正确数据。

彩色区域的值为70,另一个弧为30。彩色主弧边显示第二弧(30)的数据。

Fiddle

// data
var dataset = [{
    color: "#5FC5EA",
    value: 70
}, {
    color: "transparent",
    value: 30
}];

// size
var width = 460, z
height = 300,
radius = Math.min(width, height) / 2;

var pie = d3.layout.pie()
.sort(null).value(function(d) {
    return d.value;
});

// thin arc
var arc1 = d3.svg.arc()
.innerRadius(radius - 20)
.outerRadius(radius - 11);

// main arc
var arc = d3.svg.arc()
.innerRadius(radius - 16)
.outerRadius(radius - 17);

// set svg
var svg = d3.select("#d3-setup-donut").append("svg")
.attr("class",'donut-chart')
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
.on('mouseout', function() {
    d3.selectAll('.donut-tooltip').style('display','none');
});

// tooltip
var div = d3.select("body")
.append("div") 
.attr("class", "donut-tooltip");

// draw thinner arc
var path = svg.selectAll(".background")
.data(pie([{
    color: "#222427",
    value: 1
}]))
.enter().append("path")
.attr("class", "background")
.attr("fill", function(d, i) {
    return d.data.color;
})
.attr("d", arc1)
.on('click', function(d, i) {
    //
})
.on("mousemove",function(d, i) {
    var mouseVal = d3.mouse(this);
    div.style("display","none");
    div.html(d.data.label+" : "+d.value)
    .style("left", (d3.event.pageX-40) + "px")
    .style("top", (d3.event.pageY-35) + "px")
    .style("opacity", 1)
    .style("display","block");
})
.on("mouseout",function(){
    div.html(" ").style("display","none");
});

// draw main arc
var path = svg.selectAll(".foreground")
.data(pie(dataset))
.enter().append("path")
.attr("class", "foreground")
//.attr("stroke-linejoin", "round")
//.attr("stroke-linecap", "round")
.attr("stroke-width", "20")
.attr("stroke","none")
.attr("stroke", function(d, i) {
    return d.data.color;
})
.attr("fill", "none")
.attr("d", arc)
.on('click', function(d, i) {
    //
})
.on("mousemove",function(d, i) {
    console.log(d)
    var mouseVal = d3.mouse(this);
    div.style("display","none");
    div.html(d.data.label+" : "+d.value)
    .style("left", (d3.event.pageX-40) + "px")
    .style("top", (d3.event.pageY-35) + "px")
    .style("opacity", 1)
    .style("display","block");
})
.on("mouseout",function(){
    div.html(" ").style("display","none");
});

// draw inner text
svg.append("text")
.text('60%')
.attr("class", "donut-inner-val")
//.attr("x", radius/12 - 30)
//.attr("y", radius/12 - 10);

svg.append("text")
.text('in progress')
.attr("class", "donut-inner-text")
.attr("x", (radius/12) - 35)
.attr("y", (radius/12) + 10);

1 个答案:

答案 0 :(得分:3)

您的问题是由stroke-width属性引起的。会发生这样的情况:笔划宽度不仅仅是在弧的两侧添加像素,还会在其末尾添加像素。

我们可以在下面的演示中看到这一点,夸大笔划宽度并着色透明路径(我还更改了不透明度,因此您可以看到每个路径的结束位置):

// data
var dataset = [{
  color: "#5FC5EA",
  value: 70
}, {
  color: "red",
  value: 30
}];

// size
var width = 460,
  z
height = 300,
  radius = Math.min(width, height) / 2;

var pie = d3.layout.pie()
  .sort(null).value(function(d) {
    return d.value;
  });

// thin arc
var arc1 = d3.svg.arc()
  .innerRadius(radius - 20)
  .outerRadius(radius - 11);

// main arc
var arc = d3.svg.arc()
  .innerRadius(radius - 16)
  .outerRadius(radius - 17);

// set svg
var svg = d3.select("#d3-setup-donut").append("svg")
  .attr("class", 'donut-chart')
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
  .on('mouseout', function() {
    d3.selectAll('.donut-tooltip').style('display', 'none');
  });

// tooltip
var div = d3.select("body")
  .append("div")
  .attr("class", "donut-tooltip");

// draw thinner arc
var path = svg.selectAll(".background")
  .data(pie([{
    color: "#222427",
    value: 1
  }]))
  .enter().append("path")
  .attr("class", "background")
  .attr("fill", function(d, i) {
    return d.data.color;
  })
  .attr("d", arc1)
  .on('click', function(d, i) {
    //
  })
  .on("mousemove", function(d, i) {
    var mouseVal = d3.mouse(this);
    div.style("display", "none");
    div.html(d.data.label + " : " + d.value)
      .style("left", (d3.event.pageX - 40) + "px")
      .style("top", (d3.event.pageY - 35) + "px")
      .style("opacity", 1)
      .style("display", "block");
  })
  .on("mouseout", function() {
    div.html(" ").style("display", "none");
  });

// draw main arc
var path = svg.selectAll(".foreground")
  .data(pie(dataset))
  .enter().append("path")
  .attr("class", "foreground")
  //.attr("stroke-linejoin", "round")
  //.attr("stroke-linecap", "round")
  .attr("stroke-width", (d,i)=>60 - i*10)
  .attr("opacity", (d,i)=> 1 - i*0.2)
  .attr("stroke", "none")
  .attr("stroke", function(d, i) {
    return d.data.color;
  })
  .attr("fill", "none")
  .attr("d", arc)
  .on('click', function(d, i) {
    //
  })
  .on("mousemove", function(d, i) {
    var mouseVal = d3.mouse(this);
    div.style("display", "none");
    div.html(d.data.label + " : " + d.value)
      .style("left", (d3.event.pageX - 40) + "px")
      .style("top", (d3.event.pageY - 55) + "px")
      .style("opacity", 1)
      .style("display", "block");
  })
  .on("mouseout", function() {
    div.html(" ").style("display", "none");
  });

// draw inner text
svg.append("text")
  .text('60%')
  .attr("class", "donut-inner-val")
  //.attr("x", radius/12 - 30)
  //.attr("y", radius/12 - 10);

svg.append("text")
  .text('in progress')
  .attr("class", "donut-inner-text")
  .attr("x", (radius / 12) - 35)
  .attr("y", (radius / 12) + 10);
$pale-blue: #f6f8fe;
$dark-two:#253644;
$pale-grey: #f0f4f7;
$font-roman:'Helvetica LT W01 Roman';
$font-light:'Helvetica LT W01 Light';
$font-bold:'Helvetica LT W01 Bold';
body {
  background-color:#25333F;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}

.donut-inner-val{
		text-anchor:middle;
		font-family: $font-light;
		font-size: 24px;
		fill:$pale-blue;
	}
	.donut-inner-text {
		font-family: $font-light;
		font-size: 10px;
		fill:$pale-blue;
	}
	.background {
		z-index:1;
	}
	.foreground {
		z-index:2;
	}
	.foreground, .background {
		cursor:pointer;
	}
  .donut-tooltip{
	line-height: 1;
	font-weight: normal;
	padding: 10px 5px;
	background: #ccc;
	border-color:#ccc;
	//opacity:.5;
	color: #333;
	border-radius: 2px;
	font-size:11px;
	position: absolute;	
	text-align: center;		
	height: 28px;			
	opacity:0;	
	z-index:99999;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="d3-setup-donut" style="margin:30px auto;"></div>

如您所见,红色路径与蓝色路径重叠。

解决方案:更改内半径和外半径,并使用fill绘制路径,而不是stroke

// data
var dataset = [{
  color: "#5FC5EA",
  value: 70
}, {
  color: "transparent",
  value: 30
}];

// size
var width = 460,
  z
height = 300,
  radius = Math.min(width, height) / 2;

var pie = d3.layout.pie()
  .sort(null).value(function(d) {
    return d.value;
  });

// thin arc
var arc1 = d3.svg.arc()
  .innerRadius(radius - 20)
  .outerRadius(radius - 11);

// main arc
var arc = d3.svg.arc()
  .innerRadius(radius - 30)
  .outerRadius(radius);

// set svg
var svg = d3.select("#d3-setup-donut").append("svg")
  .attr("class", 'donut-chart')
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
  .on('mouseout', function() {
    d3.selectAll('.donut-tooltip').style('display', 'none');
  });

// tooltip
var div = d3.select("body")
  .append("div")
  .attr("class", "donut-tooltip");

// draw thinner arc
var path = svg.selectAll(".background")
  .data(pie([{
    color: "#222427",
    value: 1
  }]))
  .enter().append("path")
  .attr("class", "background")
  .attr("fill", function(d, i) {
    return d.data.color;
  })
  .attr("d", arc1)
  .on('click', function(d, i) {
    //
  })
  .on("mousemove", function(d, i) {
    var mouseVal = d3.mouse(this);
    div.style("display", "none");
    div.html(d.data.label + " : " + d.value)
      .style("left", (d3.event.pageX - 40) + "px")
      .style("top", (d3.event.pageY - 35) + "px")
      .style("opacity", 1)
      .style("display", "block");
  })
  .on("mouseout", function() {
    div.html(" ").style("display", "none");
  });

// draw main arc
var path = svg.selectAll(".foreground")
  .data(pie(dataset))
  .enter().append("path")
  .attr("class", "foreground")
  //.attr("stroke-linejoin", "round")
  //.attr("stroke-linecap", "round")
  .attr("stroke-width", "1")
  .attr("stroke", "none")
  .attr("fill", function(d, i) {
    return d.data.color;
  })
  .attr("d", arc)
  .on('click', function(d, i) {
    //
  })
  .on("mousemove", function(d, i) {
    var mouseVal = d3.mouse(this);
    div.style("display", "none");
    div.html(d.data.label + " : " + d.value)
      .style("left", (d3.event.pageX - 40) + "px")
      .style("top", (d3.event.pageY - 55) + "px")
      .style("opacity", 1)
      .style("display", "block");
  })
  .on("mouseout", function() {
    div.html(" ").style("display", "none");
  });

// draw inner text
svg.append("text")
  .text('60%')
  .attr("class", "donut-inner-val")
  //.attr("x", radius/12 - 30)
  //.attr("y", radius/12 - 10);

svg.append("text")
  .text('in progress')
  .attr("class", "donut-inner-text")
  .attr("x", (radius / 12) - 35)
  .attr("y", (radius / 12) + 10);
$pale-blue: #f6f8fe;
$dark-two:#253644;
$pale-grey: #f0f4f7;
$font-roman:'Helvetica LT W01 Roman';
$font-light:'Helvetica LT W01 Light';
$font-bold:'Helvetica LT W01 Bold';
body {
  background-color:#25333F;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}

.donut-inner-val{
		text-anchor:middle;
		font-family: $font-light;
		font-size: 24px;
		fill:$pale-blue;
	}
	.donut-inner-text {
		font-family: $font-light;
		font-size: 10px;
		fill:$pale-blue;
	}
	.background {
		z-index:1;
	}
	.foreground {
		z-index:2;
	}
	.foreground, .background {
		cursor:pointer;
	}
  .donut-tooltip{
	line-height: 1;
	font-weight: normal;
	padding: 10px 5px;
	background: #ccc;
	border-color:#ccc;
	//opacity:.5;
	color: #333;
	border-radius: 2px;
	font-size:11px;
	position: absolute;	
	text-align: center;		
	height: 28px;			
	opacity:0;	
	z-index:99999;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="d3-setup-donut" style="margin:30px auto;"></div>

这是相同的代码,但将透明路径绘制为红色。现在,您可以看到它以正确的结束角度结束:

// data
var dataset = [{
  color: "#5FC5EA",
  value: 70
}, {
  color: "red",
  value: 30
}];

// size
var width = 460,
  z
height = 300,
  radius = Math.min(width, height) / 2;

var pie = d3.layout.pie()
  .sort(null).value(function(d) {
    return d.value;
  });

// thin arc
var arc1 = d3.svg.arc()
  .innerRadius(radius - 20)
  .outerRadius(radius - 11);

// main arc
var arc = d3.svg.arc()
  .innerRadius(radius - 30)
  .outerRadius(radius);

// set svg
var svg = d3.select("#d3-setup-donut").append("svg")
  .attr("class", 'donut-chart')
  .attr("width", width)
  .attr("height", height)
  .append("g")
  .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
  .on('mouseout', function() {
    d3.selectAll('.donut-tooltip').style('display', 'none');
  });

// tooltip
var div = d3.select("body")
  .append("div")
  .attr("class", "donut-tooltip");

// draw thinner arc
var path = svg.selectAll(".background")
  .data(pie([{
    color: "#222427",
    value: 1
  }]))
  .enter().append("path")
  .attr("class", "background")
  .attr("fill", function(d, i) {
    return d.data.color;
  })
  .attr("d", arc1)
  .on('click', function(d, i) {
    //
  })
  .on("mousemove", function(d, i) {
    var mouseVal = d3.mouse(this);
    div.style("display", "none");
    div.html(d.data.label + " : " + d.value)
      .style("left", (d3.event.pageX - 40) + "px")
      .style("top", (d3.event.pageY - 35) + "px")
      .style("opacity", 1)
      .style("display", "block");
  })
  .on("mouseout", function() {
    div.html(" ").style("display", "none");
  });

// draw main arc
var path = svg.selectAll(".foreground")
  .data(pie(dataset))
  .enter().append("path")
  .attr("class", "foreground")
  //.attr("stroke-linejoin", "round")
  //.attr("stroke-linecap", "round")
  .attr("stroke-width", "1")
  .attr("stroke", "none")
  .attr("fill", function(d, i) {
    return d.data.color;
  })
  .attr("d", arc)
  .on('click', function(d, i) {
    //
  })
  .on("mousemove", function(d, i) {
    var mouseVal = d3.mouse(this);
    div.style("display", "none");
    div.html(d.data.label + " : " + d.value)
      .style("left", (d3.event.pageX - 40) + "px")
      .style("top", (d3.event.pageY - 55) + "px")
      .style("opacity", 1)
      .style("display", "block");
  })
  .on("mouseout", function() {
    div.html(" ").style("display", "none");
  });

// draw inner text
svg.append("text")
  .text('60%')
  .attr("class", "donut-inner-val")
  //.attr("x", radius/12 - 30)
  //.attr("y", radius/12 - 10);

svg.append("text")
  .text('in progress')
  .attr("class", "donut-inner-text")
  .attr("x", (radius / 12) - 35)
  .attr("y", (radius / 12) + 10);
$pale-blue: #f6f8fe;
$dark-two:#253644;
$pale-grey: #f0f4f7;
$font-roman:'Helvetica LT W01 Roman';
$font-light:'Helvetica LT W01 Light';
$font-bold:'Helvetica LT W01 Bold';
body {
  background-color:#25333F;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}

.donut-inner-val{
		text-anchor:middle;
		font-family: $font-light;
		font-size: 24px;
		fill:$pale-blue;
	}
	.donut-inner-text {
		font-family: $font-light;
		font-size: 10px;
		fill:$pale-blue;
	}
	.background {
		z-index:1;
	}
	.foreground {
		z-index:2;
	}
	.foreground, .background {
		cursor:pointer;
	}
  .donut-tooltip{
	line-height: 1;
	font-weight: normal;
	padding: 10px 5px;
	background: #ccc;
	border-color:#ccc;
	//opacity:.5;
	color: #333;
	border-radius: 2px;
	font-size:11px;
	position: absolute;	
	text-align: center;		
	height: 28px;			
	opacity:0;	
	z-index:99999;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="d3-setup-donut" style="margin:30px auto;"></div>