我使用带有工具提示的D3.js创建了一个多线图表。在这个图表中一切正常,但我想为图表中的所有图表添加样式到工具提示但不能这样做。
var margin = {
top: 20,
right: 30,
bottom: 30,
left: 40
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var z = d3.scale.category20c();
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 parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ");
var data = [{
data: [
["2016-01-20T05:31:17.000Z", 95.9, {}],
["2016-01-20T05:31:47.000Z", 95.9, {}],
["2016-01-20T05:32:17.000Z", 95.4, {}],
["2016-01-20T05:32:47.000Z", 96.1, {}],
["2016-01-20T05:33:17.000Z", 95.7, {}],
["2016-01-20T05:33:47.000Z", 95.9, {}],
["2016-01-20T05:34:17.000Z", 95.5, {}],
["2016-01-20T05:34:47.000Z", 95.9, {}],
["2016-01-20T05:35:17.000Z", 95.8, {}],
["2016-01-20T05:35:47.000Z", 95.9, {}],
["2016-01-20T05:36:17.000Z", 95.7, {}],
["2016-01-20T05:36:47.000Z", 95.7, {}],
["2016-01-20T05:37:17.000Z", 95.9, {}],
["2016-01-20T05:37:47.000Z", 95.5, {}],
["2016-01-20T05:38:17.000Z", 95.4, {}],
["2016-01-20T05:38:47.000Z", 95.8, {}],
["2016-01-20T05:39:17.000Z", 96.0, {}],
["2016-01-20T05:39:47.000Z", 96.1, {}],
["2016-01-20T05:40:17.000Z", 95.8, {}],
["2016-01-20T05:40:47.000Z", 96.0, {}],
["2016-01-20T05:41:17.000Z", 95.9, {}],
["2016-01-20T05:41:47.000Z", 94.9, {}],
["2016-01-20T05:42:17.000Z", 95.8, {}],
["2016-01-20T05:42:47.000Z", 95.9, {}],
["2016-01-20T05:43:17.000Z", 95.8, {}],
["2016-01-20T05:43:47.000Z", 96.0, {}],
["2016-01-20T05:44:17.000Z", 95.7, {}],
["2016-01-20T05:44:47.000Z", 96.0, {}],
["2016-01-20T05:45:17.000Z", 95.9, {}],
["2016-01-20T05:45:47.000Z", 96.0, {}],
["2016-01-20T05:46:17.000Z", 95.8, {}],
["2016-01-20T05:46:47.000Z", 96.0, {}],
["2016-01-20T05:47:17.000Z", 95.7, {}],
["2016-01-20T05:47:47.000Z", 96.2, {}],
["2016-01-20T05:48:17.000Z", 95.8, {}],
["2016-01-20T05:48:47.000Z", 95.9, {}],
["2016-01-20T05:49:17.000Z", 95.7, {}],
["2016-01-20T05:49:47.000Z", 95.9, {}],
["2016-01-20T05:50:18.000Z", 95.7, {}],
["2016-01-20T05:50:48.000Z", 95.8, {}],
["2016-01-20T05:51:18.000Z", 95.7, {}],
["2016-01-20T05:51:48.000Z", 95.9, {}],
["2016-01-20T05:52:18.000Z", 95.5, {}],
["2016-01-20T05:52:48.000Z", 95.9, {}],
["2016-01-20T05:53:18.000Z", 95.8, {}],
["2016-01-20T05:53:48.000Z", 95.9, {}],
["2016-01-20T05:54:18.000Z", 95.7, {}],
["2016-01-20T05:54:48.000Z", 95.9, {}],
["2016-01-20T05:55:18.000Z", 95.8, {}],
["2016-01-20T05:55:48.000Z", 95.8, {}],
["2016-01-20T05:56:18.000Z", 95.6, {}],
["2016-01-20T05:56:48.000Z", 95.7, {}],
["2016-01-20T05:57:18.000Z", 95.7, {}],
["2016-01-20T05:57:48.000Z", 95.8, {}],
["2016-01-20T05:58:18.000Z", 95.7, {}],
["2016-01-20T05:58:48.000Z", 95.7, {}],
["2016-01-20T05:59:18.000Z", 95.6, {}],
["2016-01-20T05:59:48.000Z", 95.8, {}],
["2016-01-20T06:00:18.000Z", 95.7, {}],
["2016-01-20T06:00:48.000Z", 95.7, {}],
["2016-01-20T06:01:18.000Z", 95.6, {}],
["2016-01-20T06:01:48.000Z", 95.7, {}],
["2016-01-20T06:02:18.000Z", 95.8, {}],
["2016-01-20T06:02:48.000Z", 95.8, {}],
["2016-01-20T06:03:18.000Z", 95.8, {}],
["2016-01-20T06:03:48.000Z", 95.8, {}],
["2016-01-20T06:04:18.000Z", 95.8, {}],
["2016-01-20T06:04:48.000Z", 95.8, {}],
["2016-01-20T06:05:18.000Z", 95.7, {}],
["2016-01-20T06:05:48.000Z", 95.7, {}]
],
label: "a"
}, {
data: [
["2016-01-20T05:31:17.000Z", 90.9, {}],
["2016-01-20T05:31:47.000Z", 91.9, {}],
["2016-01-20T05:32:17.000Z", 92.4, {}],
["2016-01-20T05:32:47.000Z", 90.1, {}],
["2016-01-20T05:33:17.000Z", 89.7, {}],
["2016-01-20T05:33:47.000Z", 91.9, {}],
["2016-01-20T05:34:17.000Z", 85.5, {}],
["2016-01-20T05:34:47.000Z", 93.9, {}],
["2016-01-20T05:35:17.000Z", 94.8, {}],
["2016-01-20T05:35:47.000Z", 93.9, {}],
["2016-01-20T05:36:17.000Z", 92.7, {}],
["2016-01-20T05:36:47.000Z", 95.7, {}],
["2016-01-20T05:37:17.000Z", 92.9, {}],
["2016-01-20T05:37:47.000Z", 93.5, {}],
["2016-01-20T05:38:17.000Z", 93.4, {}],
["2016-01-20T05:38:47.000Z", 93.8, {}],
["2016-01-20T05:39:17.000Z", 93.0, {}],
["2016-01-20T05:39:47.000Z", 93.1, {}],
["2016-01-20T05:40:17.000Z", 93.8, {}],
["2016-01-20T05:40:47.000Z", 93.0, {}],
["2016-01-20T05:41:17.000Z", 93.9, {}],
["2016-01-20T05:41:47.000Z", 93.9, {}],
["2016-01-20T05:42:17.000Z", 92.8, {}],
["2016-01-20T05:42:47.000Z", 92.9, {}],
["2016-01-20T05:43:17.000Z", 93.8, {}],
["2016-01-20T05:43:47.000Z", 93.0, {}],
["2016-01-20T05:44:17.000Z", 93.7, {}],
["2016-01-20T05:44:47.000Z", 93.0, {}],
["2016-01-20T05:45:17.000Z", 93.9, {}],
["2016-01-20T05:45:47.000Z", 93.0, {}],
["2016-01-20T05:46:17.000Z", 93.8, {}],
["2016-01-20T05:46:47.000Z", 96.0, {}],
["2016-01-20T05:47:17.000Z", 92.7, {}],
["2016-01-20T05:47:47.000Z", 92.2, {}],
["2016-01-20T05:48:17.000Z", 92.8, {}],
["2016-01-20T05:48:47.000Z", 92.9, {}],
["2016-01-20T05:49:17.000Z", 92.7, {}],
["2016-01-20T05:49:47.000Z", 92.9, {}],
["2016-01-20T05:50:18.000Z", 93.7, {}],
["2016-01-20T05:50:48.000Z", 93.8, {}],
["2016-01-20T05:51:18.000Z", 92.7, {}],
["2016-01-20T05:51:48.000Z", 92.9, {}],
["2016-01-20T05:52:18.000Z", 92.5, {}],
["2016-01-20T05:52:48.000Z", 94.9, {}],
["2016-01-20T05:53:18.000Z", 94.8, {}],
["2016-01-20T05:53:48.000Z", 94.9, {}],
["2016-01-20T05:54:18.000Z", 94.7, {}],
["2016-01-20T05:54:48.000Z", 94.9, {}],
["2016-01-20T05:55:18.000Z", 94.8, {}],
["2016-01-20T05:55:48.000Z", 93.8, {}],
["2016-01-20T05:56:18.000Z", 94.6, {}],
["2016-01-20T05:56:48.000Z", 94.7, {}],
["2016-01-20T05:57:18.000Z", 93.7, {}],
["2016-01-20T05:57:48.000Z", 93.8, {}],
["2016-01-20T05:58:18.000Z", 93.7, {}],
["2016-01-20T05:58:48.000Z", 93.7, {}],
["2016-01-20T05:59:18.000Z", 93.6, {}],
["2016-01-20T05:59:48.000Z", 93.8, {}],
["2016-01-20T06:00:18.000Z", 93.7, {}],
["2016-01-20T06:00:48.000Z", 93.7, {}],
["2016-01-20T06:01:18.000Z", 93.6, {}],
["2016-01-20T06:01:48.000Z", 94.7, {}],
["2016-01-20T06:02:18.000Z", 94.8, {}],
["2016-01-20T06:02:48.000Z", 94.8, {}],
["2016-01-20T06:03:18.000Z", 94.8, {}],
["2016-01-20T06:03:48.000Z", 94.8, {}],
["2016-01-20T06:04:18.000Z", 94.8, {}],
["2016-01-20T06:04:48.000Z", 94.8, {}],
["2016-01-20T06:05:18.000Z", 94.7, {}],
["2016-01-20T06:05:48.000Z", 94.7, {}]
],
label: "b"
}]
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("monotone")
.x(function(d) {
return x(parseDate.parse(d[0]));
})
.y(function(d) {
return y(d[1]);
});
var ary = [];
data.forEach(function(d) {
ary.push(d.data);
});
x.domain(d3.extent(d3.merge(ary), function(d) {
return parseDate.parse(d[0]);
}));
y.domain([
d3.min(data, function(c) {
return d3.min(c.data, function(v) {
return v[1];
});
}),
d3.max(data, function(c) {
return d3.max(c.data, function(v) {
return v[1];
});
})
]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
var series = svg.selectAll(".series")
.data(data)
.enter().append("g")
.attr("class", "series");
series.append("path")
.attr("class", "line")
.attr("d", function(d) {
return line(d.data);
})
.style("stroke", function(d, i) {
return z(i);
});
series.append("text")
.datum(function(d) {
return {
label: d.label,
data: d.data[d.data.length - 1]
};
})
.attr("transform", function(d) {
return "translate(" + x(parseDate.parse(d.data[0])) + "," + y(d.data[1]) + ")";
})
.attr("x", 3)
.attr("dy", ".35em");
var mouseG = svg.append("g")
.attr("class", "mouse-over-effects");
mouseG.append("path") // this is the black vertical line to follow mouse
.attr("class", "mouse-line")
.style("stroke", "black")
.style("stroke-width", "1px")
.style("opacity", "0");
var lines = document.getElementsByClassName('line');
var mousePerLine = mouseG.selectAll('.mouse-per-line')
.data(data)
.enter()
.append("g")
.attr("class", "mouse-per-line");
mousePerLine.append("circle")
.attr("r", 7)
.style("stroke", function(d, i) {
return z(i);
})
.style("fill", "none")
.style("stroke-width", "1px")
.style("opacity", "0");
mousePerLine.append("text")
.attr("transform", "translate(10,3)");
mouseG.append('svg:rect') // append a rect to catch mouse movements on canvas
.attr('width', width) // can't catch mouse events on a g element
.attr('height', height)
.attr('fill', 'none')
.attr('pointer-events', 'all')
.on('mouseout', function() { // on mouse out hide line, circles and text
d3.select(".mouse-line")
.style("opacity", "0");
d3.selectAll(".mouse-per-line circle")
.style("opacity", "0");
d3.selectAll(".mouse-per-line text")
.style("opacity", "0");
})
.on('mouseover', function() { // on mouse in show line, circles and text
d3.select(".mouse-line")
.style("opacity", "1");
d3.selectAll(".mouse-per-line circle")
.style("opacity", "1");
d3.selectAll(".mouse-per-line text")
.style("opacity", "1");
})
.on('mousemove', function() { // mouse moving over canvas
var mouse = d3.mouse(this);
d3.select(".mouse-line")
.attr("d", function() {
var d = "M" + mouse[0] + "," + height;
d += " " + mouse[0] + "," + 0;
return d;
});
d3.selectAll(".mouse-per-line")
.attr("transform", function(d, i) {
console.log(width / mouse[0])
var xDate = x.invert(mouse[0]),
bisect = d3.bisector(function(d) {
return d[0];
}).right;
var idx = bisect(d.data, xDate);
var beginning = 0,
end = lines[i].getTotalLength(),
target = null;
while (true) {
target = Math.floor((beginning + end) / 2);
var pos = lines[i].getPointAtLength(target);
if ((target === end || target === beginning) && pos.x !== mouse[0]) {
break;
}
if (pos.x > mouse[0]) end = target;
else if (pos.x < mouse[0]) beginning = target;
else break; //position found
}
d3.select(this).select('text')
.text(y.invert(pos.y).toFixed(2));
return "translate(" + mouse[0] + "," + pos.y + ")";
});
});
&#13;
text.inner-circle {
font-weight: 400;
font-size: 12px;
text-transform: uppercase;
}
text.inner-text {
font-weight: 400;
font-size: 36px;
font-family: 'Metric Regular', 'Metric';
text-align: center;
font-style: normal;
text-transform: uppercase;
}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 2;
shape-rendering: crispEdges;
}
.grid .tick {
stroke: lightgrey;
stroke-opacity: 0.7;
shape-rendering: crispEdges;
}
.grid path {
stroke-width: 0;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
我想在每个图表行的顶部添加一个带有x和y值的小白框。请帮帮我。
答案 0 :(得分:1)
你可以这样做:
首先制作一个id为x-text的文本,y-text将其附加到组中,如下所示(因为你想显示 x和y值)。
mousePerLine.append("text").attr("id", "x-text")
.attr("transform", "translate(10,3)");
mousePerLine.append("text").attr("id", "y-text")
.attr("transform", "translate(10,23)");
接下来,您可以在鼠标移动中显示上面创建的文本中的值,如下所示:
//for y text on tooltip
d3.select(this).select('#y-text')
.text("y: " + y.invert(pos.y).toFixed(2));
//make date in the format %H:%M:%S for x tooltip
d3.select(this).select('#x-text')
.text("x: " + d3.time.format("%X")(xDate));
接下来在工具提示周围创建一个矩形用于样式化:
mousePerLine.append("rect")
.attr("x", 0)
.attr("y", -10)
.attr("width", 70)//width of rectangle
.attr("height", 35)//height of rectangle
.style("stroke", function(d, i) {
return z(i);
})
.attr("class", "tooltip-container")//add class for styling rectangle
.style("fill", "red")//give color red to it.
.style("opacity", "0")
.style("stroke-width", "1px");
工作代码here