D3 添加饼图防止条形图的可排序性
D3 adding pie chart prevents sortability of bar chart
我已经成功创建了一个排序条形图。但是当我向页面添加饼图时,我发现条形图不再排序。
每个都使用单独的数据,分别称为 'data' 和 'data1',并且它们分别是单独的 svg 附加到单独的 div 中,id 分别为 'bar_chart' 和 'pie。
当我注释掉饼图时,条形图再次正确排序。
jsFiddle-Complete and here is the same code only without the pie chart jsFiddle-no-pie-chart
工作的 jsFiddle 有完整的代码。
<!DOCTYPE html>
<body>
<div>
<form id="form">
<input type="radio" name="stack" value="val1">blue (val1)
<br>
<input type="radio" name="stack" value="val2">white (val2)
<br>
<input type="radio" name="stack" value="val3">green (val3)
<br>
</form>
</div>
<div id="bar_chart">
</div>
<div id="pie">
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var data = [.........]
var data2 = [........]
data.forEach(function(d) {
d.value = +d.value;
});
var margin = {
top: 50,
right: 50,
bottom: 100,
left: 80
},
width = 1500 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var x = d3.scaleBand()
.domain(data.map(function(d) {
return d.name
}))
.range([0, width / 4]);
var y1 = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.val1
})])
.range([height, 0]);
var y2 = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.val2
})])
.range([height, 0]);
var y3 = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.val3
})])
.range([height, 0]);
var svg = d3.select("#bar_chart")
.data(data)
.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 + ")");
var xAxis = d3.axisBottom(x)
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "axis")
.call(d3.axisLeft(y1)
.ticks(7));
var tooltip = d3.select("#info")
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden");
var rects = svg.selectAll('rect')
.data(data);
//********* Bar Chart 1 ****************
var newRects1 = rects.enter();
newRects1.append('rect')
.attr('x', function(d, i) {
return x(d.name);
})
.attr('opacity', 0.85)
.attr('width', 40)
.attr("transform", "translate(" + 27 + ",0)")
.style('fill', 'blue')
.style('stroke', 'gray')
.attr('class', 'bar')
.attr('y', function(d, i) {
return y1(d.val1);
})
.attr('height', function(d, i) {
return height - y1(d.val1)
});
//********* Bar Chart 2 ****************
.........
.........
d3.selectAll("input[name='stack']").on("change", change);
function change() {
var x0 = x.domain(data.sort(this.value == "val1" ?
(function(a, b) {
return b.val1 - a.val1;
}) : ((this.value == "val2") ?
(function(a, b) {
return b.val2 - a.val2;
}) : (function(a, b) {
return b.val3 - a.val3;
}))).map(function(d) {
return d.name;
}))
.copy();
svg.selectAll(".bar")
.sort(function(a, b) {
// console.log("transition name001")
return x0(a.name) - x0(b.name);
});
var transition = svg.transition().duration(750),
delay = function(d, i) {
// console.log("transition name002")
return i * 50;
};
transition.selectAll(".bar")
.delay(delay)
.attr("x", function(d) {
// console.log("transition name003")
return x0(d.name);
});
transition.select(".x.axis")
.call(xAxis)
.selectAll("g")
.delay(delay);
}
//******** PIE CHART **********
var width = 300,
height = 300,
radius = Math.min(width, height) / 2;
var color = ["#2C93E8", "#838690", "#F56C4E", "#A60F2B", "#648C85", "#B3F2C9", "#528C18", "#C3F25C"];
// Generate an array object on categories as a category
var category_count = d3.nest()
.key(function(d) {
return d.category;
})
.rollup(function(leaves) {
return leaves.length;
})
.entries(data2);
var category_arcs = d3.pie()
.value(function(d) {
return d.value;
})
(category_count);
var pie = d3.pie()
.value(function(d) {
return d.category;
})(category_arcs);
var arc = d3.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var labelArc = d3.arc()
.outerRadius(radius - 10)
.innerRadius(radius - 150);
var svg = d3.select("#pie")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); // Moving the center point. 1/2 the width and 1/2 the height
var g = svg.selectAll("arc")
.data(category_arcs)
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d, i) {
return color[i];
});
g.append("text")
.attr("transform", function(d) {
return "translate(" + labelArc.centroid(d) + ")";
})
.text(function(d) {
return d.data.key + " = " + d.value;
})
.style("fill", "black");
g.append("text")
.attr("transform", "translate(" + (0 - (radius / 2)) + "," + (0 - radius + 10) + ")")
.text("Count occurences of each category")
.style("fill", "black");
</script>
在饼图的第 305 行:
var svg = d3.select("#pie")
这会覆盖您在 change()
函数中使用的 svg。您需要将其更改为 pie_svg
或其他唯一名称。
我已经成功创建了一个排序条形图。但是当我向页面添加饼图时,我发现条形图不再排序。
每个都使用单独的数据,分别称为 'data' 和 'data1',并且它们分别是单独的 svg 附加到单独的 div 中,id 分别为 'bar_chart' 和 'pie。
当我注释掉饼图时,条形图再次正确排序。
jsFiddle-Complete and here is the same code only without the pie chart jsFiddle-no-pie-chart
工作的 jsFiddle 有完整的代码。
<!DOCTYPE html>
<body>
<div>
<form id="form">
<input type="radio" name="stack" value="val1">blue (val1)
<br>
<input type="radio" name="stack" value="val2">white (val2)
<br>
<input type="radio" name="stack" value="val3">green (val3)
<br>
</form>
</div>
<div id="bar_chart">
</div>
<div id="pie">
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var data = [.........]
var data2 = [........]
data.forEach(function(d) {
d.value = +d.value;
});
var margin = {
top: 50,
right: 50,
bottom: 100,
left: 80
},
width = 1500 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var x = d3.scaleBand()
.domain(data.map(function(d) {
return d.name
}))
.range([0, width / 4]);
var y1 = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.val1
})])
.range([height, 0]);
var y2 = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.val2
})])
.range([height, 0]);
var y3 = d3.scaleLinear()
.domain([0, d3.max(data, function(d) {
return d.val3
})])
.range([height, 0]);
var svg = d3.select("#bar_chart")
.data(data)
.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 + ")");
var xAxis = d3.axisBottom(x)
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "axis")
.call(d3.axisLeft(y1)
.ticks(7));
var tooltip = d3.select("#info")
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden");
var rects = svg.selectAll('rect')
.data(data);
//********* Bar Chart 1 ****************
var newRects1 = rects.enter();
newRects1.append('rect')
.attr('x', function(d, i) {
return x(d.name);
})
.attr('opacity', 0.85)
.attr('width', 40)
.attr("transform", "translate(" + 27 + ",0)")
.style('fill', 'blue')
.style('stroke', 'gray')
.attr('class', 'bar')
.attr('y', function(d, i) {
return y1(d.val1);
})
.attr('height', function(d, i) {
return height - y1(d.val1)
});
//********* Bar Chart 2 ****************
.........
.........
d3.selectAll("input[name='stack']").on("change", change);
function change() {
var x0 = x.domain(data.sort(this.value == "val1" ?
(function(a, b) {
return b.val1 - a.val1;
}) : ((this.value == "val2") ?
(function(a, b) {
return b.val2 - a.val2;
}) : (function(a, b) {
return b.val3 - a.val3;
}))).map(function(d) {
return d.name;
}))
.copy();
svg.selectAll(".bar")
.sort(function(a, b) {
// console.log("transition name001")
return x0(a.name) - x0(b.name);
});
var transition = svg.transition().duration(750),
delay = function(d, i) {
// console.log("transition name002")
return i * 50;
};
transition.selectAll(".bar")
.delay(delay)
.attr("x", function(d) {
// console.log("transition name003")
return x0(d.name);
});
transition.select(".x.axis")
.call(xAxis)
.selectAll("g")
.delay(delay);
}
//******** PIE CHART **********
var width = 300,
height = 300,
radius = Math.min(width, height) / 2;
var color = ["#2C93E8", "#838690", "#F56C4E", "#A60F2B", "#648C85", "#B3F2C9", "#528C18", "#C3F25C"];
// Generate an array object on categories as a category
var category_count = d3.nest()
.key(function(d) {
return d.category;
})
.rollup(function(leaves) {
return leaves.length;
})
.entries(data2);
var category_arcs = d3.pie()
.value(function(d) {
return d.value;
})
(category_count);
var pie = d3.pie()
.value(function(d) {
return d.category;
})(category_arcs);
var arc = d3.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var labelArc = d3.arc()
.outerRadius(radius - 10)
.innerRadius(radius - 150);
var svg = d3.select("#pie")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); // Moving the center point. 1/2 the width and 1/2 the height
var g = svg.selectAll("arc")
.data(category_arcs)
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d, i) {
return color[i];
});
g.append("text")
.attr("transform", function(d) {
return "translate(" + labelArc.centroid(d) + ")";
})
.text(function(d) {
return d.data.key + " = " + d.value;
})
.style("fill", "black");
g.append("text")
.attr("transform", "translate(" + (0 - (radius / 2)) + "," + (0 - radius + 10) + ")")
.text("Count occurences of each category")
.style("fill", "black");
</script>
在饼图的第 305 行:
var svg = d3.select("#pie")
这会覆盖您在 change()
函数中使用的 svg。您需要将其更改为 pie_svg
或其他唯一名称。