沿 x 轴布局时间节点

Layout temporal nodes along x-axis

我写了一小段代码 (Jsfiddle),其中每个点代表 x 轴上的一个数据点。 x 轴的位置是根据日期+时间计算的。问题在于点在 x 轴上的分布方式:大的 space 未使用,并且点相互遮挡。虽然空间位置很重要只是为了显示它们的相对时间,但是,确切的距离在这里并不重要。你能给我建议任何解决方案或算法来处理这个问题吗?

var graphData = [
    {
        session: 1,
        children: [
            {id: 11, time: "2015-12-18 15:00:00", adjList: [{id: 21, w: 0.5}, {id: 24, w: 0.8}]},
            {id: 12, time: "2015-12-18 15:01:32", adjList: []},
            {id: 13, time: "2015-12-18 15:03:40", adjList: [{id: 32, w: 0.4}]},
            {id: 14, time: "2015-12-18 15:05:04", adjList: []}]
    },
    {
        session: 2,
        children: [
            {id: 21, time: "2015-12-18 08:55:00", adjList: []},
            {id: 22, time: "2015-12-18 08:59:10", adjList: [{id: 14, w: 0.6}]},
            {id: 23, time: "2015-12-18 09:02:00", adjList: [{id: 11, w: 0.2}]},
            {id: 24, time: "2015-12-18 09:06:45", adjList: [{id: 32, w: 0.7}]}]
    },
    {
        session: 3,
        children: [
            {id: 31, time: "2015-12-18 08:40:50", adjList: []},
            {id: 32, time: "2015-12-18 08:43:00", adjList: [{id: 24, w: 0.1}, {id: 13, w: 0.3}]}]
    },
    {
        session: 4,
        children: [
            {id: 41, time: "2015-12-18 16:00:00", adjList: [{id: 31, w: 0.01}]},
            {id: 42, time: "2015-12-18 16:09:12", adjList: [{id: 31, w: 0.15}]},
            {id: 43, time: "2015-12-18 16:09:55", adjList: [{id: 22, w: 0.95}]}]
    },
];


/*
 * SVG
 */
var margin = {top: 50, right: 50, bottom: 50, left: 50},
    width = 1000 + margin.left + margin.right,
    height = 200 + margin.top + margin.bottom,
    xPos = 500, yPos = 100;

var svg = d3.select("#fcgraph")
    .append("svg")
    .attr("x", xPos)
    .attr("y", yPos)
    .attr("width", width)
    .attr("height", height);
var svgGroup = svg.append("g")
    .attr("transform", "translate(" + 10 + "," + height / 2 + ")");


/*
 * Scale
 */
var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse;
var times = [];

graphData.forEach(function (d, i) {
    d.children.forEach(function (c, i) {
        times.push(parseDate(c.time));
    })
})

var x = d3.time.scale()
    .range([0, width]);

x.domain(d3.extent(times, function(d) {
    return d;
}));

// calc pos in x axis
var nodes = [];
graphData.forEach(function (d, i) {
    var session = d.session;
    d.children.forEach(function (c, i) {
        nodes.push({id: c.id, 
                    session: session, 
                    pos: {x: x(parseDate(c.time)), y: 50}
                   });
    }) // foreach
}) // foreach


/*
 * Draw the nodes.
 */

var nodeColor = d3.scale.category10();

var circle = svgGroup.selectAll(".circle")
    .data(nodes)
    .enter()
    .append("g")
    .attr("class", "circle");

circle.append("circle")
    .attr("cx", function (d) {
        return d.pos.x;
    })
    .attr("cy", function (d) {
        return d.pos.y;
    })
    .attr("r", 10)
    .style("fill", function (d) {
        return nodeColor(d.session);
    })
    .append("title").text(function (d) {
        return d.id;
    });

// Label
circle.append("text")
    .attr("x", function (d) {
        return d.pos.x;
    })
    .attr("y", function (d) {
        return d.pos.y;
    })
    .attr("font-size", "10px")
    .attr("fill", "white")
    .text(function (d) {
        return d.id;
    });

您可以尝试使用多线性(或多时间尺度)。

简单地构造一个新的多时间尺度:

var xMod = x.copy().range([0,width/4,width/2,width]);

xMod.domain([
    parseDate("2015-12-18 08:40:50"),
    parseDate("2015-12-18 10:00:00"),
    parseDate("2015-12-18 15:05:04"),
    parseDate("2015-12-18 16:09:55"),
     ]);

并且,使用它来映射值而不是 x。

来源:

http://bl.ocks.org/herrstucki/5403383