D3和JS的新功能,我正在开发一个Webapp,以显示有关美国总统初选候选人的各种财务数据。
我已经复制了一些代码来创建使其具有响应能力的函数,但我不知道如何根据窗口大小来确定高度,这意味着台式机上漂亮的横向图表会变得非常小手机上的图表。
手机被压缩
脚本附在下面,但是可能很难读。如果有人从描述和图片中了解了我的问题,并且对正确的方向提出了建议,我将万分感谢!
我的脚本:
var yLen = data.length;
// I snagged this f(x) from https://brendansudol.com/writing/responsive-d3
// not entirely sure how it works
function responsivefy(svg) {
// get container + svg aspect ratio
var container = d3.select(svg.node().parentNode),
width = parseInt(svg.style("width")),
height = parseInt(svg.style("height")),
aspect = width / height;
// add viewBox and preserveAspectRatio properties,
// and call resize so that svg resizes on inital page load
svg.attr("viewBox", "0 0 " + width + " " + height)
.attr("perserveAspectRatio", "xMinYMid")
.call(resize);
// to register multiple listeners for same event type,
// you need to add namespace, i.e., 'click.foo'
// necessary if you call invoke this function for multiple svgs
// api docs: https://github.com/mbostock/d3/wiki/Selections#on
d3.select(window).on("resize." + container.attr("id"), resize);
// get width of container and resize svg to fit it
function resize() {
var targetWidth = parseInt(container.style("width"));
svg.attr("width", targetWidth);
svg.attr("height", Math.round(targetWidth / aspect));
}
}
//set up svg using margin conventions
//we'll need plenty of room on the left for labels
var margin = {
top: 15,
right: 35,
bottom: 15,
left: 100
};
var width = 960 - margin.left - margin.right,
height = Math.min(300, (yLen*100)) - margin.top - margin.bottom;
var svg = d3.select("#{{contest.slug}}").append("svg")
.attr("id", "{{ contest.slug }}"+"-svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.call(responsivefy)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
var x = d3.scale.linear()
.range([0, width])
.domain([0, d3.max(data, function (d) {
return d.Amount;
})]);
var y = d3.scale.ordinal()
.rangeRoundBands([height, 0], .1)
.domain(data.map(function (d) {
return d.Candidate;
}));
//make y axis to show bar names
var yAxis = d3.svg.axis()
.scale(y)
//no tick marks
.tickSize(0)
.orient("left")
var gy = svg.append("g")
.attr("class", "y axis")
.call(yAxis)
//make x axis
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(1)
.ticks(10)
.orient("bottom");
var gx = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0,"+height+")")
.call(xAxis);
var bars = svg.selectAll(".bar")
.data(data)
.enter()
.append("g")
//append rects
bars.append("rect")
.attr("class", "bar")
.attr("y", function (d) {
return y(d.Candidate);
})
.attr("height", y.rangeBand())
.attr("x", 0)
.attr("width", function (d) {
return x(d.Amount);
})
.style("fill", "#23395d");
//add a value label to the right of each bar
bars.append("text")
.attr("class", "label")
//y position of the label is halfway down the bar
.attr("y", function (d) {
return y(d.Candidate) + y.rangeBand() / 2 + 4;
})
//x position is 3 pixels to the right of the bar
.attr("x", function (d) {
return x(d.Amount) + 3;
})
.text(function (d) {
return '$'+d.Amount;
});
//add an image to the left of each bar
bars.append("image")
.attr("class", "bar_image")
//y position of the image is halfway down the bar
.attr("y", function(d){
console.log(y(d.Candidate));
return y(d.Candidate)+margin["top"];
})
//x position to left of bar
.attr("x", function(d) {
return -100;
})
.attr('xlink:href', function(d){
return "/static/images/candidate_images/"+d.Candidate+".png";
})
.attr("height", (y.rangeBand() - (y.rangeBand() * .4)))
.attr("width", (y.rangeBand() - (y.rangeBand() * .4)))
console.log(y.rangeBand);
d3.select("#dem-2020-prim").classed("active", true).classed("in", true)