具有特定时区的 d3.js 中的时间轴

abk*_*srv 6 javascript charts datetime d3.js

我正在使用d3.time.scale()(参考此处)创建时间刻度并使用axis.tickValues([values])此处为参考)提供刻度值)。为 [values] 中提供的指定 Date 对象呈现刻度。
一切都很好,但刻度值表示总是在浏览器的当前时区。现在需要在特定时区(例如“亚洲/加尔各答”)中显示它。有没有办法实现这一目标?我看到的 max 选项用于格式化刻度,但不会用自定义值替换它们,这对这种情况没有帮助。

编辑:这可以使用像moment.js这样的外部库来实现,但如果可以避免这种情况,则是首选。

abk*_*srv 8

基于 Mark 的解决方案,这是一个不使用外部库的工作解决方案。在文本字段中输入时区 ID(例如 - Europe/Berlin)。

// Set the dimensions of the canvas / graph
var margin = {
    top: 30,
    right: 20,
    bottom: 100,
    left: 50
},
width = 600 - margin.left - margin.right,
    height = 270 - margin.top - margin.bottom;

var currentTZ = "local";

// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);

// Define the axes
var xAxis = d3.svg.axis().scale(x)
    .orient("bottom").ticks(10)
    .tickFormat(function (d) {

    if (currentTZ === "local") return d3.time.format('%X')(d);
    else {
        console.log(currentTZ);
        return d3.time.format('%X')(new Date(d.toLocaleString('en-US', {
            timeZone: currentTZ
        })));
    }
});

var yAxis = d3.svg.axis().scale(y)
    .orient("left").ticks(5);

// Define the line
var valueline = d3.svg.line()
    .x(function (d) {
    return x(d.date);
})
    .y(function (d) {
    return y(d.close);
});

// Adds the svg canvas
var svg = d3.select("body")
    .append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform",
    "translate(" + margin.left + "," + margin.top + ")");

var data = [{
    date: new Date(0),
    close: Math.random() * 100
}, {
    date: new Date(1800000),
    close: Math.random() * 100
}, {
    date: new Date(3600000),
    close: Math.random() * 100
}, {
    date: new Date(5400000),
    close: Math.random() * 100
}, {
    date: new Date(7200000),
    close: Math.random() * 100
}, {
    date: new Date(9000000),
    close: Math.random() * 100
}, {
    date: new Date(10800000),
    close: Math.random() * 100
}, {
    date: new Date(12600000),
    close: Math.random() * 100
}]

// Scale the range of the data
x.domain(d3.extent(data, function (d) {
    return d.date;
}));
y.domain([0, d3.max(data, function (d) {
    return d.close;
})]);

// Add the valueline path.
svg.append("path")
    .attr("class", "line")
    .attr("d", valueline(data));

// Add the X Axis
svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis)
    .selectAll("text")
    .style("text-anchor", "end")
    .attr("dx", "-.8em")
    .attr("dy", ".15em")
    .attr("transform", function (d) {
    return "rotate(-65)"
});

// Add the Y Axis
svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);

handleClick = function () {
    currentTZ = document.getElementById('timeZ').value;
    console.log(currentTZ)
    svg.selectAll("g.x.axis")
        .call(xAxis)
        .selectAll("text")
        .style("text-anchor", "end")
        .attr("dx", "-.8em")
        .attr("dy", ".15em")
        .attr("transform", function () {
        return "rotate(-65)"
    });
};
Run Code Online (Sandbox Code Playgroud)
 body {
     font: 12px Arial;
 }
 path {
     stroke: steelblue;
     stroke-width: 2;
     fill: none;
 }
 .axis path, .axis line {
     fill: none;
     stroke: grey;
     stroke-width: 1;
     shape-rendering: crispEdges;
 }
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<input name="Submit" type="submit" value="Change Time" onClick="handleClick()">
<input type="text" id="timeZ" value="local">
</form>
Run Code Online (Sandbox Code Playgroud)

  • 需要考虑的一件事是在某些浏览器(如 Safari)中不支持 `toLocaleString()`。 (2认同)

Mar*_*ark 6

时区真是令人头疼。但是如果你结合d3timezone,这个任务就变得非常简单了tickformatter

// create reference to current zone
var currentTZ = "local";

// Define the axes
var xAxis = d3.svg.axis().scale(x)
  .orient("bottom").ticks(10)
  .tickFormat(function(d){
      console.log('format');
      if (currentTZ === "local")
        return moment(d).format('hh:mm:ss');
      else
        return moment(d).tz(currentTZ).format('hh:mm:ss');
  });

  // when user picks a new zone, re-draw axis
  ...
  .append("select")
  .on('change', function(d){
    currentTZ = this.options[ this.selectedIndex ].text;
    svg.selectAll("g.x.axis")
      .call(xAxis);
  })
Run Code Online (Sandbox Code Playgroud)

这是一个完整的工作示例:

// create reference to current zone
var currentTZ = "local";

// Define the axes
var xAxis = d3.svg.axis().scale(x)
  .orient("bottom").ticks(10)
  .tickFormat(function(d){
      console.log('format');
      if (currentTZ === "local")
        return moment(d).format('hh:mm:ss');
      else
        return moment(d).tz(currentTZ).format('hh:mm:ss');
  });

  // when user picks a new zone, re-draw axis
  ...
  .append("select")
  .on('change', function(d){
    currentTZ = this.options[ this.selectedIndex ].text;
    svg.selectAll("g.x.axis")
      .call(xAxis);
  })
Run Code Online (Sandbox Code Playgroud)