修复显示的轴比例范围
Posted
技术标签:
【中文标题】修复显示的轴比例范围【英文标题】:Fixing the axis-scale range that is presented 【发布时间】:2020-10-06 12:18:15 【问题描述】:我的值是我在时间序列中呈现的总分钟数。虽然分钟用于绘图,但我想更改轴刻度标签以显示此数据最接近的小时数。我解决这个问题的方法是添加一个.tickFormat()
,将分钟转换为小时,然后返回d3.timeFormat()
,小时格式和一个新日期设置为0
,设置小时。虽然轴刻度标签很接近,但它们不正确。似乎有轻微的偏移、值的重复和比例不是从 0 开始(从 12 开始)。我应该使用不同的函数调用来更正比例吗?
这是有问题的代码:
svg.append("g")
.call(d3.axisLeft()
.scale(y)
.tickFormat((d, i) =>
var hours = Math.floor(d / 60);
console.log(hours)
console.log(new Date(0).setMinutes(hours))
return d3.timeFormat("%I")( new Date(0).setHours(hours))
));
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
<style>
div.tooltip
position: absolute;
text-align: center;
width: 100px;
height: 30px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
</style>
<script>
var data = [
"x": "2020-04-26", "y": 461.0, "label": "7:41" ,
"x": "2020-04-27", "y": 421.0, "label": "7:01" ,
"x": "2020-04-28", "y": 519.0, "label": "8:39" ,
"x": "2020-04-29", "y": 502.0, "label": "8:22" ,
"x": "2020-04-30", "y": 511.0, "label": "8:31" ,
"x": "2020-05-01", "y": 513.0, "label": "8:33" ,
"x": "2020-05-02", "y": 496.0, "label": "8:16" ,
"x": "2020-05-03", "y": 480.0, "label": "8:00" ,
"x": "2020-05-04", "y": 364.0, "label": "6:04" ,
"x": "2020-05-05", "y": 498.0, "label": "8:18" ,
"x": "2020-05-06", "y": 467.0, "label": "7:47" ,
"x": "2020-05-07", "y": 477.0, "label": "7:57" ,
"x": "2020-05-08", "y": 431.0, "label": "7:11" ,
"x": "2020-05-09", "y": 419.0, "label": "6:59" ,
"x": "2020-05-10", "y": 471.0, "label": "7:51" ,
"x": "2020-05-11", "y": 391.0, "label": "6:31" ,
"x": "2020-05-12", "y": 481.0, "label": "8:01" ,
"x": "2020-05-13", "y": 494.0, "label": "8:14" ,
"x": "2020-05-14", "y": 506.0, "label": "8:26" ,
"x": "2020-05-15", "y": 464.0, "label": "7:44" ,
"x": "2020-05-16", "y": 474.0, "label": "7:54" ,
"x": "2020-05-17", "y": 383.0, "label": "6:23" ,
"x": "2020-05-18", "y": 385.0, "label": "6:25" ,
"x": "2020-05-19", "y": 470.0, "label": "7:50" ,
"x": "2020-05-20", "y": 465.0, "label": "7:45" ,
"x": "2020-05-21", "y": 574.0, "label": "9:34" ,
"x": "2020-05-22", "y": 473.0, "label": "7:53" ,
"x": "2020-05-23", "y": 431.0, "label": "7:11" ,
"x": "2020-05-24", "y": 497.0, "label": "8:17" ,
"x": "2020-05-26", "y": 482.0, "label": "8:02" ,
"x": "2020-05-27", "y": 492.0, "label": "8:12" ,
"x": "2020-05-28", "y": 494.0, "label": "8:14" ,
"x": "2020-05-29", "y": 469.0, "label": "7:49" ,
"x": "2020-05-30", "y": 395.0, "label": "6:35" ,
"x": "2020-05-31", "y": 427.0, "label": "7:07" ,
"x": "2020-06-01", "y": 346.0, "label": "5:46" ,
"x": "2020-06-02", "y": 416.0, "label": "6:56" ,
"x": "2020-06-03", "y": 461.0, "label": "7:41" ,
"x": "2020-06-04", "y": 486.0, "label": "8:06" ,
"x": "2020-06-05", "y": 451.0, "label": "7:31" ,
"x": "2020-06-06", "y": 533.0, "label": "8:53" ,
"x": "2020-06-08", "y": 462.0, "label": "7:42" ,
"x": "2020-06-09", "y": 461.0, "label": "7:41" ,
"x": "2020-06-10", "y": 477.0, "label": "7:57" ,
"x": "2020-06-11", "y": 458.0, "label": "7:38" ,
"x": "2020-06-12", "y": 484.0, "label": "8:04" ,
"x": "2020-06-13", "y": 389.0, "label": "6:29" ,
"x": "2020-06-15", "y": 472.0, "label": "7:52" ,
"x": "2020-06-16", "y": 462.0, "label": "7:42" ,
"x": "2020-06-17", "y": 486.0, "label": "8:06" ,
"x": "2020-06-18", "y": 489.0, "label": "8:09" ,
"x": "2020-06-19", "y": 483.0, "label": "8:03" ,
"x": "2020-06-20", "y": 426.0, "label": "7:06" ,
"x": "2020-06-21", "y": 453.0, "label": "7:33" ,
"x": "2020-06-22", "y": 489.0, "label": "8:09" ,
"x": "2020-06-23", "y": 467.0, "label": "7:47" ,
"x": "2020-06-24", "y": 474.0, "label": "7:54" ,
"x": "2020-06-25", "y": 451.0, "label": "7:31" ,
"x": "2020-06-26", "y": 450.0, "label": "7:30" ,
"x": "2020-06-27", "y": 470.0, "label": "7:50" ,
"x": "2020-06-29", "y": 247.0, "label": "4:07" ,
"x": "2020-06-30", "y": 502.0, "label": "8:22" ,
"x": "2020-07-01", "y": 464.0, "label": "7:44"
]
// D3 date parser
for (var i=0; i < data.length; i++)
var parser = d3.timeParse("%Y-%m-%d")
data[i].date = parser(data[i].x);
var margin = top: 10, right: 30, bottom: 30, left: 60
var width = 800 - margin.left - margin.right;
var height = 800 - margin.top - margin.bottom;
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var svg = d3.select("#my_dataviz")
.append("svg")
.attr( 'preserveAspectRatio',"xMinYMin meet")
.attr("viewBox", "0 0 " + (width + margin.left + margin.right) + " " + (height + margin.top + margin.bottom))
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // translate(margin left, margin top)
var x = d3.scaleTime()
.domain([d3.min(data, function(d) return d.date ), d3.max(data, function(d) return d.date )])
.range([0, width]);
svg.append("g")
.attr("transform", "translate(" + 0 + "," + height + ")")
.call(d3.axisBottom(x));
// text label for the x axis
svg.append("text")
.attr("transform",
"translate(" + (width/2) + " ," + (height + margin.top + 20) + ")")
.style("text-anchor", "middle")
.text("Date");
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) return +d.y )])
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft()
.scale(y)
.tickFormat((d, i) =>
var hours = Math.floor(d / 60);
console.log(hours)
console.log(new Date(0).setMinutes(hours))
return d3.timeFormat("%I")( new Date(0).setHours(hours))
));
// text label for the y axis
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Time Asleep (Minutes)");
// Add line path
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d) return x(d.date) )
.y(function(d) return y(d.y) )
);
// Add the scatterplot (data points)
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 3)
// Add tooltip on hover
.on("mouseover", function(d)
div.transition()
.duration(200)
.style("opacity", .9);
div.html(d.x + "<br/>" + d.label)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 30) + "px")
)
// Remove tooltip after hover
.on("mouseout", function(d)
div.transition()
.duration(500)
.style("opacity", 0);
)
.transition()
.delay(function(d,i) return (i*3))
.duration(2000)
.attr("cx", function(d) return x(d.date) )
.attr("cy", function(d) return y(d.y) );
</script>
【问题讨论】:
【参考方案1】:虽然您的数据是时间,但它不是日期。强迫它成为一个约会会给你带来许多令人讨厌的并发症。我刚刚超越了 d3 和 Date 逻辑,得到了一个更简单的解决方案:
var data = [
"x": "2020-04-26",
"y": 461.0,
"label": "7:41"
,
"x": "2020-04-27",
"y": 421.0,
"label": "7:01"
,
"x": "2020-04-28",
"y": 519.0,
"label": "8:39"
,
"x": "2020-04-29",
"y": 502.0,
"label": "8:22"
,
"x": "2020-04-30",
"y": 511.0,
"label": "8:31"
,
"x": "2020-05-01",
"y": 513.0,
"label": "8:33"
,
"x": "2020-05-02",
"y": 496.0,
"label": "8:16"
,
"x": "2020-05-03",
"y": 480.0,
"label": "8:00"
,
"x": "2020-05-04",
"y": 364.0,
"label": "6:04"
,
"x": "2020-05-05",
"y": 498.0,
"label": "8:18"
,
"x": "2020-05-06",
"y": 467.0,
"label": "7:47"
,
"x": "2020-05-07",
"y": 477.0,
"label": "7:57"
,
"x": "2020-05-08",
"y": 431.0,
"label": "7:11"
,
"x": "2020-05-09",
"y": 419.0,
"label": "6:59"
,
"x": "2020-05-10",
"y": 471.0,
"label": "7:51"
,
"x": "2020-05-11",
"y": 391.0,
"label": "6:31"
,
"x": "2020-05-12",
"y": 481.0,
"label": "8:01"
,
"x": "2020-05-13",
"y": 494.0,
"label": "8:14"
,
"x": "2020-05-14",
"y": 506.0,
"label": "8:26"
,
"x": "2020-05-15",
"y": 464.0,
"label": "7:44"
,
"x": "2020-05-16",
"y": 474.0,
"label": "7:54"
,
"x": "2020-05-17",
"y": 383.0,
"label": "6:23"
,
"x": "2020-05-18",
"y": 385.0,
"label": "6:25"
,
"x": "2020-05-19",
"y": 470.0,
"label": "7:50"
,
"x": "2020-05-20",
"y": 465.0,
"label": "7:45"
,
"x": "2020-05-21",
"y": 574.0,
"label": "9:34"
,
"x": "2020-05-22",
"y": 473.0,
"label": "7:53"
,
"x": "2020-05-23",
"y": 431.0,
"label": "7:11"
,
"x": "2020-05-24",
"y": 497.0,
"label": "8:17"
,
"x": "2020-05-26",
"y": 482.0,
"label": "8:02"
,
"x": "2020-05-27",
"y": 492.0,
"label": "8:12"
,
"x": "2020-05-28",
"y": 494.0,
"label": "8:14"
,
"x": "2020-05-29",
"y": 469.0,
"label": "7:49"
,
"x": "2020-05-30",
"y": 395.0,
"label": "6:35"
,
"x": "2020-05-31",
"y": 427.0,
"label": "7:07"
,
"x": "2020-06-01",
"y": 346.0,
"label": "5:46"
,
"x": "2020-06-02",
"y": 416.0,
"label": "6:56"
,
"x": "2020-06-03",
"y": 461.0,
"label": "7:41"
,
"x": "2020-06-04",
"y": 486.0,
"label": "8:06"
,
"x": "2020-06-05",
"y": 451.0,
"label": "7:31"
,
"x": "2020-06-06",
"y": 533.0,
"label": "8:53"
,
"x": "2020-06-08",
"y": 462.0,
"label": "7:42"
,
"x": "2020-06-09",
"y": 461.0,
"label": "7:41"
,
"x": "2020-06-10",
"y": 477.0,
"label": "7:57"
,
"x": "2020-06-11",
"y": 458.0,
"label": "7:38"
,
"x": "2020-06-12",
"y": 484.0,
"label": "8:04"
,
"x": "2020-06-13",
"y": 389.0,
"label": "6:29"
,
"x": "2020-06-15",
"y": 472.0,
"label": "7:52"
,
"x": "2020-06-16",
"y": 462.0,
"label": "7:42"
,
"x": "2020-06-17",
"y": 486.0,
"label": "8:06"
,
"x": "2020-06-18",
"y": 489.0,
"label": "8:09"
,
"x": "2020-06-19",
"y": 483.0,
"label": "8:03"
,
"x": "2020-06-20",
"y": 426.0,
"label": "7:06"
,
"x": "2020-06-21",
"y": 453.0,
"label": "7:33"
,
"x": "2020-06-22",
"y": 489.0,
"label": "8:09"
,
"x": "2020-06-23",
"y": 467.0,
"label": "7:47"
,
"x": "2020-06-24",
"y": 474.0,
"label": "7:54"
,
"x": "2020-06-25",
"y": 451.0,
"label": "7:31"
,
"x": "2020-06-26",
"y": 450.0,
"label": "7:30"
,
"x": "2020-06-27",
"y": 470.0,
"label": "7:50"
,
"x": "2020-06-29",
"y": 247.0,
"label": "4:07"
,
"x": "2020-06-30",
"y": 502.0,
"label": "8:22"
,
"x": "2020-07-01",
"y": 464.0,
"label": "7:44"
]
// D3 date parser
for (var i = 0; i < data.length; i++)
var parser = d3.timeParse("%Y-%m-%d")
data[i].date = parser(data[i].x);
var margin =
top: 10,
right: 30,
bottom: 30,
left: 60
var width = 800 - margin.left - margin.right;
var height = 800 - margin.top - margin.bottom;
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var svg = d3.select("#my_dataviz")
.append("svg")
.attr('preserveAspectRatio', "xMinYMin meet")
.attr("viewBox", "0 0 " + (width + margin.left + margin.right) + " " + (height + margin.top + margin.bottom))
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // translate(margin left, margin top)
var x = d3.scaleTime()
.domain([d3.min(data, function(d)
return d.date
), d3.max(data, function(d)
return d.date
)])
.range([0, width]);
svg.append("g")
.attr("transform", "translate(" + 0 + "," + height + ")")
.call(d3.axisBottom(x));
// text label for the x axis
svg.append("text")
.attr("transform",
"translate(" + (width / 2) + " ," + (height + margin.top + 20) + ")")
.style("text-anchor", "middle")
.text("Date");
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d)
return +d.y
)])
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft()
.scale(y)
.tickFormat((d, i) =>
var hours = Math.floor(d / 60);
var minutes = d - hours * 60;
return hours.toString().padStart(2, 0) + ":" + minutes.toString().padStart(2, 0).padStart(2, 0);
));
// text label for the y axis
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x", 0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Time Asleep (Minutes)");
// Add line path
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d)
return x(d.date)
)
.y(function(d)
return y(d.y)
)
);
// Add the scatterplot (data points)
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 3)
// Add tooltip on hover
.on("mouseover", function(d)
div.transition()
.duration(200)
.style("opacity", .9);
div.html(d.x + "<br/>" + d.label)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 30) + "px")
)
// Remove tooltip after hover
.on("mouseout", function(d)
div.transition()
.duration(500)
.style("opacity", 0);
)
.transition()
.delay(function(d, i)
return (i * 3)
)
.duration(2000)
.attr("cx", function(d)
return x(d.date)
)
.attr("cy", function(d)
return y(d.y)
);
div.tooltip
position: absolute;
text-align: center;
width: 100px;
height: 30px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
<meta charset="utf-8">
<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>
<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>
【讨论】:
这很有意义。比我预期的要容易得多。谢谢!以上是关于修复显示的轴比例范围的主要内容,如果未能解决你的问题,请参考以下文章
ArcGIS10全图功能,比例尺很小,如何调整全图功能下的比例尺缩放范围
R语言ggplot2可视化分面图(faceting): ggplot2可视化分面图(facet_wrap)并设置不同的分面使用不同的坐标轴数值范围以及不同的轴标签断点间隔breaks