问题描述
我在一页上有多个图,所有图都应该具有相同的大小,所以我想为每个图复制粘贴很多代码,重新使用通用设置可能是个好主意:
var xAxisScaleTime = d3.scaleTime().range([0,graph_width ]);
var xAxisScaleLinear = d3.scaleLinear().range([0,graphwidth ]);
var yAxisScaleLin = d3.scaleLinear().range( [ graph_height,0]);
var yAxisScaleLog = d3.scaleLog().range( [ graph_height,0]);
//etc...
每个图的域可能不同。所以我像这样设置它们:
// Most Graphs will share the same Time-Domain
var GraphT_X = xAxisScaleTime.domain([ starttime,endtime]);
// Graphs have different Domains for Y
var Graph1_Y = yAxisScaleLin.domain([[ Graph_1_min,Graph_1_max]);
var Graph2_Y = yAxisScaleLin.domain([[ Graph_2_min,Graph_2_max]);
//etc...
但随后我用相同的结果建立了多个图形:
//For the sake of short code I skipped ViewBox,widht,height,classes,etc. here
var Graph_1 = d3.select("#Graph1")
.append("svg")
.append("g");
// add the X Axis Graph_1
Graph_1.append("g")
.call( d3.axisBottom( GraphT_X )
.ticks(d3.timeDay)
.tickFormat(d3.timeFormat("%d.%m")));
// add the Y Axis Graph_1
Graph_1.append("g")
.call( d3.axisLeft(Graph1_Y) // <--- Using first Y-Axis here
.ticks(5,".0f"));
var Graph_2 = d3.select("#Graph2")
.append("svg")
.append("g");
// add the X Axis Graph_1
Graph_2.append("g")
.call( d3.axisBottom( GraphT_X )
.ticks(d3.timeDay)
.tickFormat(d3.timeFormat("%d.%m")));
// add the Y Axis Graph_2
Graph_2.append("g")
.call( d3.axisLeft( Graph2_Y ) // <--- Using different/second Y-Axis here
.ticks(8,".0f"));
这看起来既干净又漂亮。但是浏览器始终呈现相同的图,就像Graph1_Y
被定义为Graph2_Y
一样被覆盖。
这可能不是D3中的错误,而是一些javascript继承。
有人知道如何在重用yAxisScaleLin
之类的比例变量的同时解决此问题吗?
由于定义Axis相同范围的10倍以上并不像我想要的代码那样不清楚。
解决方法
这看起来既干净又漂亮。但是浏览器始终呈现相同的图,就好像在定义Graph2_Y时Graph1_Y被覆盖
这正是您在这里所做的:
// Graphs have different Domains for Y
var Graph1_Y = yAxisScaleLin.domain([[ Graph_1_min,Graph_1_max]);
var Graph2_Y = yAxisScaleLin.domain([[ Graph_2_min,Graph_2_max]);
yAxisScaleLin.domain([values])
既修改又返回自身:yAxisScaleLin
-它不返回新的比例尺对象。因此,Graph1_Y
和Graph2_Y
都是相同比例对象的引用。
可能的解决方案
如果.domain()返回一个新的比例尺,而不是调用它的比例尺,那么您的代码将起作用。但是,有一种方法可以让您根据现有的比例尺返回新的比例尺对象:
var graph1_Y = yAxisCaleLin.copy().domain(...
scale.copy()
方法返回调用它的比例尺的副本,包括其所有属性的副本。然后,您可以将域设置为新值。
var scale = d3.scaleLinear().range([0,1]);
var a = scale.copy().domain([0,1]);
var b = scale.copy().domain([2,3]);
console.log(a.domain().toString());
console.log(b.domain().toString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>