Javascript 选择时d3堆栈条形图的边框
正在尝试为d3堆栈条形图中的选定条形图实现边框。在这里,第一个酒吧的上边框在第二个酒吧后面一点。如何避免这种情况Javascript 选择时d3堆栈条形图的边框,javascript,html,css,d3.js,svg,Javascript,Html,Css,D3.js,Svg,正在尝试为d3堆栈条形图中的选定条形图实现边框。在这里,第一个酒吧的上边框在第二个酒吧后面一点。如何避免这种情况 var svg, height, width, margin, parentWidth, parentHeight; // container size parentWidth = 700; parentHeight = 500; margin = {top: 50, right: 20, bottom: 35, left: 30}; width = parentWidth - m
var svg, height, width, margin, parentWidth, parentHeight;
// container size
parentWidth = 700;
parentHeight = 500;
margin = {top: 50, right: 20, bottom: 35, left: 30};
width = parentWidth - margin.left - margin.right;
height = parentHeight - margin.top - margin.bottom;
var selectedSection = window.sessionStorage.getItem('selectedSection');
// data
var dataset = [{"label":"DEC","Set Up":{"count":12,"id":1,"label":"Set Up","year":"2016","graphType":"setup"},"Not Set Up":{"count":12,"id":0,"label":"Not Set Up","year":"2016","graphType":"setup"}},{"label":"JAN","Set Up":{"count":6,"id":1,"label":"Set Up","year":"2017","graphType":"setup"},"Not Set Up":{"count":21,"id":0,"label":"Not Set Up","year":"2017","graphType":"setup"}},{"label":"FEB","Set Up":{"count":1,"id":1,"label":"Set Up","year":"2017","graphType":"setup"},"Not Set Up":{"count":2,"id":0,"label":"Not Set Up","year":"2017","graphType":"setup"}},{"label":"MAR","Set Up":{"count":0,"id":1,"label":"Set Up","year":"2017","graphType":"setup"},"Not Set Up":{"count":0,"id":0,"label":"Not Set Up","year":"2017","graphType":"setup"}},{"label":"APR","Set Up":{"count":0,"id":1,"label":"Set Up","year":"2017","graphType":"setup"},"Not Set Up":{"count":0,"id":0,"label":"Not Set Up","year":"2017","graphType":"setup"}}];
// x cord
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], 0.2);
// color helper
var colorRange = d3.scale.category20();
var color = d3.scale.ordinal()
.range(colorRange.range());
// x axis
var xAxis = d3.svg.axis()
.scale(x)
.orient('bottom');
var colors = ['#50BEE9', '#30738C'];
// Set SVG
svg = d3.select('#chart')
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom )
.attr('class', 'setup')
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
color.domain(d3.keys(dataset[0]).filter(function(key) { return key !== 'label'; }));
dataset.forEach(function(d) {
var y0 = 0;
d.values = color.domain().map(function(name) {
return {
name: name,
y0: y0,
y1: y0 += +d[name].count,
patientStatus:d[name].id,
graphType:d[name].graphType,
fromDate:{
month:d.label,
year:d[name].year
},
toDate:{
month:d.label,
year:d[name].year
}
};
});
d.total = d.values[d.values.length - 1].y1;
});
var y = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) {
return d.total;
})])
.range([height, 0]);
var ticks = y.ticks(),
lastTick = ticks[ticks.length-1];
var newLastTick = lastTick + (ticks[1] - ticks[0]);
if (lastTick<y.domain()[1]){
ticks.push(lastTick + (ticks[1] - ticks[0]));
}
// adjust domain for further value
y.domain([y.domain()[0], newLastTick]);
// y axis
var yAxis = d3.svg.axis()
.scale(y)
.orient('left')
.tickSize(-width, 0, 0)
.tickFormat(d3.format('d'))
.tickValues(ticks);
x.domain(dataset.map(function(d) { return d.label; }));
y.domain([0, d3.max(dataset, function(d) { return d.total; })]);
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
svg.append('g')
.attr('class', 'y axis')
.call(yAxis);
var bar = svg.selectAll('.label')
.data(dataset)
.enter().append('g')
.attr('class', 'g')
.attr('id', function(d, i) {
return i;
})
.attr('transform', function(d) { return 'translate(' + x(d.label) + ',0)'; });
var barEnter = bar.selectAll('rect')
.data(function(d) { return d.values; })
.enter();
barEnter.append('rect')
.attr('width', x.rangeBand())
.attr('y', function(d) {
return y(d.y1);
})
.attr('class', function(d, i){
return 'bar';
})
.attr('height', function(d) { return y(d.y0) - y(d.y1); })
.style('fill', function(d,i) { return colors[i]; })
.on('click', function(d, i) {
d3.selectAll('.bar').classed('selected', false);
d3.select(this)
.classed('bar selected', true);
});
barEnter.append('text')
.text(function(d) {
var calcH = y(d.y0) - y(d.y1);
var inText = (d.y1-d.y0);
if(calcH >= 20) {
return inText;
} else {
return '';
}
})
.attr('class','inner-text')
.attr('y', function(d) { return y(d.y1)+(y(d.y0) - y(d.y1))/2 + 5; })
.attr('x', function(){
return (x.rangeBand()/2) - 10;
});
svg
.select('.y')
.selectAll('.tick')
.filter(function (d) {
return d % 1 !== 0;
})
.style('display','none');
svg
.select('.y')
.selectAll('.tick')
.filter(function (d) {
return d === 0;
})
.select('text')
.style('display','none');
var svg、高度、宽度、边距、parentWidth、parentHeight;
//容器大小
parentWidth=700;
父母身高=500;
边距={顶部:50,右侧:20,底部:35,左侧:30};
宽度=parentWidth-margin.left-margin.right;
高度=父高度-margin.top-margin.bottom;
var selectedSection=window.sessionStorage.getItem('selectedSection');
//资料
var数据集=[{“标签”:“DEC”,“设置”:“计数”:12,“id”:1,“标签”:“设置”,“年份”:“2016”,“图形类型”:“设置”},“未设置”:“计数”:12,“id”:0,“标签”:“未设置”,“年份”:“2016”,“图形类型”:“设置”},{“标签”:“一月”,“设置”:“计数”:6,“id”:1,“标签”:“设置”,“年份”:“2017”,“图形类型”:“设置”},“未设置”:“计数”:21,“id”:0,“标签”:“未设置”,“年份”:“2017年”,“图形类型”:“设置”},{“标签”:“2月”,“设置”:{“计数”:1,“id”:1,“标签”:“设置”,“年份”:“2017年”,“图形类型”:“设置”},“未设置”:{“计数”:2,“id”:0,“标签”:“未设置”,“年份”:“2017年”,“图形类型”:“设置”},{“标签”:“MAR“:”未设置“,”年份“:”2017“,”图形类型“:”设置“},{”标签“:”APR“,”设置“,”标签“:”设置“,”年份“:”2017“,”图形类型“:”设置“}”,未设置“{”计数“:”0,“id“:”标签“:”未设置“,”年份“:”2017“,”图形类型“:”设置“}”;
//x线
var x=d3.scale.ordinal()
.rangeRoundBands([0,宽度],0.2);
//颜色助手
var colorRange=d3.scale.category20();
var color=d3.scale.ordinal()
.range(colorRange.range());
//x轴
var xAxis=d3.svg.axis()
.比例(x)
.orient(“底部”);
变量颜色=['#50BEE9','#30738C'];
//设置SVG
svg=d3。选择(“#图表”)
.append('svg')
.attr('width',width+margin.left+margin.right)
.attr('height',height+margin.top+margin.bottom)
.attr('class','setup')
.append('g')
.attr('transform','translate('+margin.left+','+margin.top+'));
color.domain(d3.keys(数据集[0]).filter(函数(键){return key!=='label';}));
dataset.forEach(函数(d){
var y0=0;
d、 values=color.domain().map(函数(名称){
返回{
姓名:姓名,,
y0:y0,
y1:y0+=+d[名称]。计数,
patientStatus:d[name].id,
graphType:d[名称]。graphType,
起始日期:{
月份:d.label,
年份:d[姓名]。年份
},
今天:{
月份:d.label,
年份:d[姓名]。年份
}
};
});
d、 总计=d.values[d.values.length-1].y1;
});
变量y=d3.scale.linear()
.domain([0,d3.max(数据集,函数(d){
返回d.total;
})])
.范围([高度,0]);
var ticks=y.ticks(),
lastTick=ticks[ticks.length-1];
var newLastTick=lastTick+(ticks[1]-ticks[0]);
如果(lastTick=20){
返回inText;
}否则{
返回“”;
}
})
.attr('class','internal-text')
.attr('y',函数(d){返回y(d.y1)+(y(d.y0)-y(d.y1))/2+5;})
.attr('x',function(){
返回(x.rangeBand()/2)-10;
});
svg
.select(“.y”)
.selectAll(“.tick”)
.filter(函数(d){
返回d%1!==0;
})
.style('display','none');
svg
.select(“.y”)
.selectAll(“.tick”)
.filter(函数(d){
返回d==0;
})
.选择('文本')
.style('display','none');
在SVG中,就像真正的画家将墨水放在白色画布上一样,最后绘制的元素保持在顶部 现在,您看到的是预期的行为,因为每个堆叠的条(矩形)位于不同的
元素中,当然,这些组在SVG结构中具有给定的顺序
解决方案只涉及一行:
d3.select(this.parentNode).raise();
这一行所做的是选择单击矩形的组并将其升高(即,在DOM树中将其向下移动),以便该组位于所有其他组的顶部。根据API:
按顺序重新插入每个选定元素,作为其父元素的最后一个子元素。(强调矿山)
“向下移动”、“站在顶端”和“成为最后一个孩子”可能有点混乱,似乎相互矛盾,但下面是解释。鉴于此SVG结构:
<svg>
<foo></foo>
<bar></bar>
<baz></baz>
</svg>
,作为最后一个元素,是绘制在SVG顶部的元素。因此,提升一个元素意味着在SVG树结构中向下移动它,但从视觉上来说,向上移动它
这是你最新的小提琴:
PS:我增加了笔划宽度,只是为了清楚地表明单击的矩形现在位于顶部。标记:
<div id='stacked-bar'></div>
Css:
这是正常的行为,因为在SVG中,最后一个绘制的人保持在顶部。如果您使用的是D3 v4.x,这一问题只需一行就可以解决…@GerardoFurtado您能为D3 v4中的修复提供一个提琴吗?不,这是一个很大的工作。既然您有兴趣解决这个问题,您应该使用v4创建小提琴。之后,我向您展示了解决方案。我用D3V4创建了一个小提琴。请帮我解决问题,还有邦蒂。
var initStackedBarChart = {
draw: function(config) {
me = this,
domEle = config.element,
stackKey = config.key,
data = config.data,
margin = {top: 20, right: 20, bottom: 30, left: 50},
parseDate = d3.timeParse("%m/%Y"),
width = 550 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom,
xScale = d3.scaleBand().range([0, width]).padding(0.1),
yScale = d3.scaleLinear().range([height, 0]),
color = d3.scaleOrdinal(d3.schemeCategory20),
xAxis = d3.axisBottom(xScale).tickFormat(d3.timeFormat("%b")),
yAxis = d3.axisLeft(yScale),
svg = d3.select("#"+domEle).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top+10 + margin.bottom+10)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var stack = d3.stack()
.keys(stackKey)
.order(d3.stackOrderNone)
.offset(d3.stackOffsetNone);
var layers= stack(data);
data.sort(function(a, b) { return b.total - a.total; });
xScale.domain(data.map(function(d) { return parseDate(d.date); }));
yScale.domain([0, d3.max(layers[layers.length - 1], function(d) { return d[0] + d[1]; }) ]).nice();
var layer = svg.selectAll(".layer")
.data(layers)
.enter().append("g")
.attr("class", "layer")
.style("fill", function(d, i) { return color(i); });
layer.selectAll("rect")
.data(function(d) { return d; })
.enter().append("rect")
.attr('class', 'bar')
.attr("x", function(d) { return xScale(parseDate(d.data.date)); })
.attr("y", function(d) { return yScale(d[1]); })
.attr("height", function(d) { return yScale(d[0]) - yScale(d[1]) -1; })
.attr("width", xScale.bandwidth())
.on('click', function(d, i) {
d3.selectAll('.bar').classed('selected', false);
d3.select(this).classed('selected', true);
});
svg.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + (height+5) + ")")
.call(xAxis);
svg.append("g")
.attr("class", "axis axis--y")
.attr("transform", "translate(0,0)")
.call(yAxis);
}
}
var data = [
{"date":"4/1854","total":45,"disease":12,"wounds":14,"other":25},
{"date":"5/1854","total":23,"disease":12,"wounds":0,"other":9},
{"date":"6/1854","total":38,"disease":11,"wounds":0,"other":6},
{"date":"7/1854","total":26,"disease":11,"wounds":8,"other":7}
];
var key = ["wounds", "other", "disease"];
initStackedBarChart.draw({
data: data,
key: key,
element: 'stacked-bar'
});
.axis text {
font: 10px sans-serif;
}
.axis line,
.axis path {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis--x path {
display: none;
}
.path-line {
fill: none;
stroke: yellow;
stroke-width: 1.5px;
}
svg {
background: #f0f0f0;
}
.selected{
stroke:#333;
stroke-width:2;
}