这是您的 JS 小提琴的增强版,演示:http: //jsfiddle.net/robschmuecker/c8txLxo9/
它获取您拥有的数据,然后对其进行解析以获取年份集合,以便我们每年只插入一个 dom 元素而不是几个。然后我们可以有条件地添加具有多个年份的事件。它也有一个基于日期的轴,并且是可缩放的。
var dataset = [
["2006", 1],
["2009", 1],
["2004", 1],
["2004", 2],
["2004", 3],
["2012", 1],
["2008", 1],
["2004", 2],
["2000", 1],
["2006", 2],
["2007", 1],
["2001", 1]
];
//console.log(dataset, dataset.length);
var yearEvents = [];
// Firstly get all the events together for each year in the dataset
dataset.forEach(function (value) {
var yearString = value[0] + "";
if (typeof yearEvents[yearString] == 'undefined') yearEvents[yearString] = [];
yearEvents[yearString].push(value[1]);
});
var newDataset = [];
yearEvents.forEach(function (year, key) {
newDataset.push([key + "", year]);
});
//console.log('yearEvents', newDataset);
var w = 500;
var h = 300;
var padding = 20;
var circleRadius = 10;
var parseDate = d3.time.format("%Y").parse;
var mindate = parseDate("2000"),
maxdate = parseDate("2015");
var xScale = d3.time.scale()
.domain([mindate, maxdate])
.range([padding, w - padding * 2]);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function (d) {
return d[1];
})])
.range([5, 5]);
// Define the axis
var xAxis = d3.svg.axis().scale(xScale).tickSize(-h).tickSubdivide(true);
// Define the zoom function for the zoomable tree
function zoom() {
svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
// define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents
var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", zoom);
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h)
.call(zoomListener);
// Append a group which holds all nodes and which the zoom Listener can act upon.
var svgGroup = svg.append("g");
svgGroup.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);
var circleGroups = svgGroup.selectAll('g.circle')
.data(newDataset)
.enter()
.append('g')
.attr("transform", function (d) {
return "translate(" + xScale(parseDate(d[0])) + "," + (h - padding - (circleRadius * 3)) + ")";
});
var circles = circleGroups.append("circle").attr("r", circleRadius);
// Append the year value to the circles. change `display` property to `block` in CSS to show them.
var circleTexts = circleGroups.append('text')
.attr("class", "circle-year")
//make their horizontal position offest by half of their font-size.
.attr("dy", function () {
return "0.25em"
})
.attr("text-anchor", "middle")
.text(function (d) {
return d[0];
});
// Now add text to the ones with more than one event
circleGroups.each(function (d, i) {
//console.log(this, d, i);
var me = this;
//see if it has more than one event and if so loop through them all and add the new text elements with their height separation based on their index
if (d[1].length > 1) {
d[1].forEach(function (event, index) {
d3.select(me).append('text')
.attr("dy", function () {
return -((circleRadius * index) * 2 + padding);
})
.attr("text-anchor", "middle")
.text(function (d) {
return event;
});
});
}
});