问题
I have this multi-line plot with D3:
But as you can see, the beginning of the y-axis labels are cut off - anybody know how I can properly display the full label?
And if you have any advice on how to rotate the x-axis labels by 90 degrees, that would help too.
Here is the complete code which generates the plot:
<!DOCTYPE html>
<html lang='en'>
<head>
<link href='http://getbootstrap.com/dist/css/bootstrap.min.css' rel='stylesheet'>
<link href='http://getbootstrap.com/examples/justified-nav/justified-nav.css' rel='stylesheet'>
<script src='http://d3js.org/d3.v3.min.js' charset='utf-8'></script>
<style>
.axis path {
fill: none;
stroke: #777;
shape-rendering: crispEdges;
}
.axis text {
font-family: Lato;
font-size: 13px;
}
</style>
</head>
<body>
<div class='container'>
<div class='jumbotron'>
<svg id='visualisation'></svg>
<script>
var heapTotal = JSON.parse('[{"x":1501478175044,"y":18911232},{"x":1501478177048,"y":19959808}]');
var heapUsed = JSON.parse('[{"x":1501478175044,"y":10492112},{"x":1501478177048,"y":10904080}]');
var rss = JSON.parse('[{"x":1501478175044,"y":35622912},{"x":1501478177048,"y":36134912}]');
const values = heapTotal.concat(heapUsed).concat(rss).reduce(function (prev, curr) {
console.log('curr => ', curr);
return {
xMin: Math.min(prev.xMin, curr.x),
xMax: Math.max(prev.xMax, curr.x),
yMin: Math.min(prev.yMin, curr.y),
yMax: Math.max(prev.yMax, curr.y),
}
}, {
xMin: Number.MAX_SAFE_INTEGER,
xMax: -1,
yMin: Number.MAX_SAFE_INTEGER,
yMax: -1
});
console.log('values => ', values);
var vis = d3.select('#visualisation'),
WIDTH = 1200,
HEIGHT = 800,
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
},
xScale = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([values.xMin - 50, values.xMax + 50]),
yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([values.yMin - 50, values.yMax + 50]),
xAxis = d3.svg.axis()
.scale(xScale),
yAxis = d3.svg.axis()
.scale(yScale)
.orient('left');
vis.attr("width", WIDTH)
.attr("height", HEIGHT);
vis.append('svg:g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + (HEIGHT - MARGINS.bottom) + ')')
.call(xAxis);
vis.append('svg:g')
.attr('class', 'y axis')
.attr('transform', 'translate(' + (MARGINS.left) + ',0)')
.call(yAxis);
var lineGen = d3.svg.line()
.x(function (d) {
return xScale(d.x);
})
.y(function (d) {
return yScale(d.y);
})
.interpolate('basis');
vis.append('svg:path')
.attr('d', lineGen(heapUsed))
.attr('stroke', 'green')
.attr('stroke-width', 2)
.attr('fill', 'none');
vis.append('svg:path')
.attr('d', lineGen(heapTotal))
.attr('stroke', 'blue')
.attr('stroke-width', 2)
.attr('fill', 'none');
vis.append('svg:path')
.attr('d', lineGen(rss))
.attr('stroke', 'red')
.attr('stroke-width', 2)
.attr('fill', 'none');
</script>
</div>
</div>
</body>
</html>
回答1:
One easy css way is to give some padding to the svg element. It will keep the map in better shape.
METHOD 1: just change the left margin value in the script:
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50 // change this to something larger like 100
},
Method 2: Using CSS
var heapTotal = JSON.parse(
'[{"x":1501478175044,"y":18911232},{"x":1501478177048,"y":19959808}]'
);
var heapUsed = JSON.parse(
'[{"x":1501478175044,"y":10492112},{"x":1501478177048,"y":10904080}]'
);
var rss = JSON.parse(
'[{"x":1501478175044,"y":35622912},{"x":1501478177048,"y":36134912}]'
);
const values = heapTotal.concat(heapUsed).concat(rss).reduce(function(
prev,
curr
) {
console.log("curr => ", curr);
return {
xMin: Math.min(prev.xMin, curr.x),
xMax: Math.max(prev.xMax, curr.x),
yMin: Math.min(prev.yMin, curr.y),
yMax: Math.max(prev.yMax, curr.y)
};
}, {
xMin: Number.MAX_SAFE_INTEGER,
xMax: -1,
yMin: Number.MAX_SAFE_INTEGER,
yMax: -1
});
console.log("values => ", values);
var vis = d3.select("#visualisation"),
WIDTH = 1200,
HEIGHT = 800,
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
},
xScale = d3.scale
.linear()
.range([MARGINS.left, WIDTH - MARGINS.right])
.domain([values.xMin - 50, values.xMax + 50]),
yScale = d3.scale
.linear()
.range([HEIGHT - MARGINS.top, MARGINS.bottom])
.domain([values.yMin - 50, values.yMax + 50]),
xAxis = d3.svg.axis().scale(xScale),
yAxis = d3.svg.axis().scale(yScale).orient("left");
vis.attr("width", WIDTH).attr("height", HEIGHT);
vis
.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
.call(xAxis);
vis
.append("svg:g")
.attr("class", "y axis")
.attr("transform", "translate(" + MARGINS.left + ",0)")
.call(yAxis);
var lineGen = d3.svg
.line()
.x(function(d) {
return xScale(d.x);
})
.y(function(d) {
return yScale(d.y);
})
.interpolate("basis");
vis
.append("svg:path")
.attr("d", lineGen(heapUsed))
.attr("stroke", "green")
.attr("stroke-width", 2)
.attr("fill", "none");
vis
.append("svg:path")
.attr("d", lineGen(heapTotal))
.attr("stroke", "blue")
.attr("stroke-width", 2)
.attr("fill", "none");
vis
.append("svg:path")
.attr("d", lineGen(rss))
.attr("stroke", "red")
.attr("stroke-width", 2)
.attr("fill", "none");
#visualisation{
padding: 0px 20px;
}
.axis path {
fill: none;
stroke: #777;
shape-rendering: crispEdges;
}
.axis text {
font-family: Lato;
font-size: 13px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg id='visualisation'></svg>
回答2:
The file is set up nicely to make this pretty easy. You can just change the left margin. Something like 75 seems to work to keep you axis labels from clipping.:
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 75
},
The class jumbotron is adding a margin to the whole div, which you might need to change move the chart if this pushes everything over to far to the right.
来源:https://stackoverflow.com/questions/45408077/y-axis-labels-are-cut-off-on-d3-plot