重用Axis Scale覆盖设置域

问题描述

我在一页上有多个图,所有图都应该具有相同的大小,所以我想为每个图复制粘贴很多代码,重新使用通用设置可能是个好主意:

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...

但随后我用相同的结果建立了多个图形:

How it looks like


//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一样被覆盖。

应该看起来像这样:

Desired Result

这可能不是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_YGraph2_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>