<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script data-require="[email protected]" data-semver="3.5.3" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
</head>
<body>
<script>
var myData = "date \t New York \t San Francisco \t Austin\n\
20111001 \t 63.4 \t 62.7 \t 72.2\n\
20111002 \t 58.0 \t 59.9 \t 67.7\n\
20111003 \t 53.3 \t 59.1 \t 69.4\n\
20111004 \t 55.7 \t 58.8 \t 68.0\n\
20111005 \t 64.2 \t 58.7 \t 72.4\n\
20111006 \t 58.8 \t 57.0 \t 77.0\n\
20111007 \t 57.9 \t 56.7 \t 82.3\n\
20111008 \t 61.8 \t 56.8 \t 78.9\n\
20111009 \t 69.3 \t 56.7 \t 68.8\n\
20111010 \t 71.2 \t 60.1 \t 68.7\n\
20111011 \t 68.7 \t 61.1 \t 70.3\n\
20111012 \t 61.8 \t 61.5 \t 75.3\n\
20111013 \t 63.0 \t 64.3 \t 76.6\n\
20111014 \t 66.9 \t 67.1 \t 66.6\n\
20111015 \t 61.7 \t 64.6 \t 68.0\n\
20111016 \t 61.8 \t 61.6 \t 70.6\n\
20111017 \t 62.8 \t 61.1 \t 71.1\n\
20111018 \t 60.8 \t 59.2 \t 70.0\n\
20111019 \t 62.1 \t 58.9 \t 61.6\n\
20111020 \t 65.1 \t 57.2 \t 57.4\n\
20111021 \t 55.6 \t 56.4 \t 64.3\n\
20111022 \t 54.4 \t 60.7 \t 72.4\n";
var margin = {
top: 20,
right: 80,
bottom: 30,
left: 50
},
width = 500 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y%m%d").parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category20();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.temperature);
});
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 = d3.tsv.parse(myData);
color.domain(d3.keys(data[0]).filter(function(key) {
return key !== "date";
}));
data.forEach(function(d) {
d.date = parseDate(d.date);
});
var cities = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
date: d.date,
temperature: +d[name]
};
})
};
});
x.domain(d3.extent(data, function(d) {
return d.date;
}));
y.domain([
d3.min(cities, function(c) {
return d3.min(c.values, function(v) {
return v.temperature;
});
}),
d3.max(cities, function(c) {
return d3.max(c.values, function(v) {
return v.temperature;
});
})
]);
var legend = svg.selectAll('g')
.data(cities)
.enter()
.append('g')
.attr('class', 'legend');
legend.append('rect')
.attr('x', width - 20)
.attr('y', function(d, i) {
return i * 20;
})
.attr('width', 10)
.attr('height', 10)
.style('fill', function(d) {
return color(d.name);
});
legend.append('text')
.attr('x', width - 8)
.attr('y', function(d, i) {
return (i * 20) + 9;
})
.text(function(d) {
return d.name;
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Temperature (ºF)");
var city = svg.selectAll(".city")
.data(cities)
.enter().append("g")
.attr("class", "city");
city.append("path")
.attr("class", "line")
.attr("d", function(d) {
return line(d.values);
})
.style("stroke", function(d) {
return color(d.name);
});
city.append("text")
.datum(function(d) {
return {
name: d.name,
value: d.values[d.values.length - 1]
};
})
.attr("transform", function(d) {
return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
})
.attr("x", 3)
.attr("dy", ".35em")
.text(function(d) {
return d.name;
});
// **************************************************************************************** //
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([cities])
.enter()
.append("g")
.attr("class", "mouse-per-line");
mousePerLine.selectAll('.mouse-per-line') // Rectangle
.data([cities])
.enter()
.append("rect")
.attr("width", width)
.attr("height", 90)
.style("padding", "5px")
.style("stroke", "#272525")
.style("fill", "#272525")
.style("stroke-width", "1px")
.style("opacity", "0")
.attr('x', 10)
.attr('y', -45);
mousePerLine.selectAll('.mouse-per-line') // Circle
.data(cities)
.enter()
.append("circle")
.attr("r", 5)
.style("stroke", function(d) {
return color(d.name);
})
.style("fill", function(d) {
return color(d.name);
})
.style("stroke-width", "1px")
.style("opacity", "0");
mousePerLine.selectAll('.mouse-per-line') // Text
.data(cities)
.enter()
.append("text")
.attr("transform", "translate(15,13)")
.style("fill", function(d) {
return color(d.name);
})
.style("font-weight", "bold")
.style("font-size", "10pt");
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 rect")
.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 rect")
.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("foo", function(d, i) {
var xDate = x.invert(mouse[0]);
var bisect;
var heights = [];
var xDateValue = /\w*.\s.\d.\d*.\d*.:\d*.:\d*/.exec(xDate);
// console.log(xDateValue);
d3.selectAll('circle')
.attr("transform", function(d, j) {
bisect = d3.bisector(function(d) {
return d.date;
}).right;
idx = bisect(d.values, xDate);
var beginning = 0,
end = lines[i].getTotalLength(),
target = null;
while (true) {
target = Math.floor((beginning + end)/2);
pos = lines[j].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
}
heights[j] = pos.y;
return "translate(" + mouse[0] + "," + pos.y + ")";
});
var avgheight = 0;
for (var z = 0; z < heights.length; z++) {
avgheight = avgheight + heights[z];
}
avgheight = avgheight/d.length;
d3.select(this).selectAll('rect')
.attr("transform", function(d, i) {
return "translate(" + mouse[0] + "," + avgheight + ")";
});
var rectangleText = "";
for (var t = 1; t < heights.length; t++) {
rectangleText = rectangleText + "<br/>" + y.invert(heights[t]).toFixed(2);
}
d3.select(this)
.selectAll('text').text(function(d, i) {
return xDateValue + " " + d.name + " " + y.invert(heights[i]).toFixed(2)
}).attr("transform", function(d, i) {
return "translate(" + mouse[0] + "," + (avgheight + 30 - (i * 25)) + ")";
}).attr("dx", '20px');
return "translate(" + mouse[0] + "," + pos.y + ")";
});
});
</script>
</body>
</html>
1
A
回答
1
下面是对现有代码的快速修改。它继续你的方法,并添加一个额外的text
元素日期:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script data-require="[email protected]" data-semver="3.5.3" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
</head>
<body>
<script>
var myData = "date \t New York \t San Francisco \t Austin\n\
20111001 \t 63.4 \t 62.7 \t 72.2\n\
20111002 \t 58.0 \t 59.9 \t 67.7\n\
20111003 \t 53.3 \t 59.1 \t 69.4\n\
20111004 \t 55.7 \t 58.8 \t 68.0\n\
20111005 \t 64.2 \t 58.7 \t 72.4\n\
20111006 \t 58.8 \t 57.0 \t 77.0\n\
20111007 \t 57.9 \t 56.7 \t 82.3\n\
20111008 \t 61.8 \t 56.8 \t 78.9\n\
20111009 \t 69.3 \t 56.7 \t 68.8\n\
20111010 \t 71.2 \t 60.1 \t 68.7\n\
20111011 \t 68.7 \t 61.1 \t 70.3\n\
20111012 \t 61.8 \t 61.5 \t 75.3\n\
20111013 \t 63.0 \t 64.3 \t 76.6\n\
20111014 \t 66.9 \t 67.1 \t 66.6\n\
20111015 \t 61.7 \t 64.6 \t 68.0\n\
20111016 \t 61.8 \t 61.6 \t 70.6\n\
20111017 \t 62.8 \t 61.1 \t 71.1\n\
20111018 \t 60.8 \t 59.2 \t 70.0\n\
20111019 \t 62.1 \t 58.9 \t 61.6\n\
20111020 \t 65.1 \t 57.2 \t 57.4\n\
20111021 \t 55.6 \t 56.4 \t 64.3\n\
20111022 \t 54.4 \t 60.7 \t 72.4\n";
var margin = {
top: 20,
right: 80,
bottom: 30,
left: 50
},
width = 500 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y%m%d").parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category20();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.temperature);
});
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 = d3.tsv.parse(myData);
color.domain(d3.keys(data[0]).filter(function(key) {
return key !== "date";
}));
data.forEach(function(d) {
d.date = parseDate(d.date);
});
var cities = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
date: d.date,
temperature: +d[name]
};
})
};
});
x.domain(d3.extent(data, function(d) {
return d.date;
}));
y.domain([
d3.min(cities, function(c) {
return d3.min(c.values, function(v) {
return v.temperature;
});
}),
d3.max(cities, function(c) {
return d3.max(c.values, function(v) {
return v.temperature;
});
})
]);
var legend = svg.selectAll('g')
.data(cities)
.enter()
.append('g')
.attr('class', 'legend');
legend.append('rect')
.attr('x', width - 20)
.attr('y', function(d, i) {
return i * 20;
})
.attr('width', 10)
.attr('height', 10)
.style('fill', function(d) {
return color(d.name);
});
legend.append('text')
.attr('x', width - 8)
.attr('y', function(d, i) {
return (i * 20) + 9;
})
.text(function(d) {
return d.name;
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Temperature (ºF)");
var city = svg.selectAll(".city")
.data(cities)
.enter().append("g")
.attr("class", "city");
city.append("path")
.attr("class", "line")
.attr("d", function(d) {
return line(d.values);
})
.style("stroke", function(d) {
return color(d.name);
});
city.append("text")
.datum(function(d) {
return {
name: d.name,
value: d.values[d.values.length - 1]
};
})
.attr("transform", function(d) {
return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
})
.attr("x", 3)
.attr("dy", ".35em")
.text(function(d) {
return d.name;
});
// **************************************************************************************** //
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([cities])
.enter()
.append("g")
.attr("class", "mouse-per-line");
mousePerLine.selectAll('.mouse-per-line') // Rectangle
.data([cities])
.enter()
.append("rect")
.attr("width", width)
.attr("height", 110)
.style("padding", "5px")
.style("stroke", "#272525")
.style("fill", "#272525")
.style("stroke-width", "1px")
.style("opacity", "0")
.attr('x', 10)
.attr('y', -45);
mousePerLine.selectAll('.mouse-per-line') // Circle
.data(cities)
.enter()
.append("circle")
.attr("r", 5)
.style("stroke", function(d) {
return color(d.name);
})
.style("fill", function(d) {
return color(d.name);
})
.style("stroke-width", "1px")
.style("opacity", "0");
mousePerLine.append("text")
.attr("class","DateText");
mousePerLine.selectAll('.mouse-per-line') // Text
.data(cities)
.enter()
.append("text")
.attr("class", "ValueText")
.attr("transform", "translate(15,13)")
.style("fill", function(d) {
return color(d.name);
})
.style("font-weight", "bold")
.style("font-size", "10pt");
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 rect")
.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 rect")
.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("foo", function(d, i) {
var xDate = x.invert(mouse[0]);
var bisect;
var heights = [];
var xDateValue = /\w*.\s.\d.\d*.\d*.:\d*.:\d*/.exec(xDate);
// console.log(xDateValue);
d3.selectAll('circle')
.attr("transform", function(d, j) {
bisect = d3.bisector(function(d) {
return d.date;
}).right;
idx = bisect(d.values, xDate);
var beginning = 0,
end = lines[i].getTotalLength(),
target = null;
while (true) {
target = Math.floor((beginning + end)/2);
pos = lines[j].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
}
heights[j] = pos.y;
return "translate(" + mouse[0] + "," + pos.y + ")";
});
var avgheight = 0;
for (var z = 0; z < heights.length; z++) {
avgheight = avgheight + heights[z];
}
avgheight = avgheight/d.length;
d3.select(this).selectAll('rect')
.attr("transform", function(d, i) {
return "translate(" + mouse[0] + "," + avgheight + ")";
});
var rectangleText = "";
for (var t = 1; t < heights.length; t++) {
rectangleText = rectangleText + "<br/>" + y.invert(heights[t]).toFixed(2);
}
d3.select(this)
.select(".DateText")
.attr("transform", function(d, i) {
return "translate(" + mouse[0] + "," + (avgheight - 25) + ")";
}).attr("dx", '20px')
.text(xDateValue)
.style("fill", "white");
d3.select(this)
.selectAll('.ValueText').text(function(d, i) {
return d.name + " " + y.invert(heights[i]).toFixed(2)
}).attr("transform", function(d, i) {
return "translate(" + mouse[0] + "," + (avgheight + 50 - (i * 25)) + ")";
}).attr("dx", '20px');
return "translate(" + mouse[0] + "," + pos.y + ")";
});
});
</script>
</body>
</html>
+0
太好了!非常感谢Mark。你救了我。我仔细检查了你的代码,附加了两个文本类并在不同的文本类中显示不同的数据是一种常识。从stackoverflow学习很多东西。 :) – Rach
0
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script data-require="[email protected]" data-semver="3.5.3" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
</head>
<body>
<script>
var myData = "date \t New York \t San Francisco \t Austin\n\
20111001 \t 63.4 \t 62.7 \t 72.2\n\
20111002 \t 58.0 \t 59.9 \t 67.7\n\
20111003 \t 53.3 \t 59.1 \t 69.4\n\
20111004 \t 55.7 \t 58.8 \t 68.0\n\
20111005 \t 64.2 \t 58.7 \t 72.4\n\
20111006 \t 58.8 \t 57.0 \t 77.0\n\
20111007 \t 57.9 \t 56.7 \t 82.3\n\
20111008 \t 61.8 \t 56.8 \t 78.9\n\
20111009 \t 69.3 \t 56.7 \t 68.8\n\
20111010 \t 71.2 \t 60.1 \t 68.7\n\
20111011 \t 68.7 \t 61.1 \t 70.3\n\
20111012 \t 61.8 \t 61.5 \t 75.3\n\
20111013 \t 63.0 \t 64.3 \t 76.6\n\
20111014 \t 66.9 \t 67.1 \t 66.6\n\
20111015 \t 61.7 \t 64.6 \t 68.0\n\
20111016 \t 61.8 \t 61.6 \t 70.6\n\
20111017 \t 62.8 \t 61.1 \t 71.1\n\
20111018 \t 60.8 \t 59.2 \t 70.0\n\
20111019 \t 62.1 \t 58.9 \t 61.6\n\
20111020 \t 65.1 \t 57.2 \t 57.4\n\
20111021 \t 55.6 \t 56.4 \t 64.3\n\
20111022 \t 54.4 \t 60.7 \t 72.4\n";
var margin = {
top: 20,
right: 80,
bottom: 30,
left: 50
},
width = 500 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y%m%d").parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category20();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.temperature);
});
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 = d3.tsv.parse(myData);
color.domain(d3.keys(data[0]).filter(function(key) {
return key !== "date";
}));
data.forEach(function(d) {
d.date = parseDate(d.date);
});
var cities = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
date: d.date,
temperature: +d[name]
};
})
};
});
x.domain(d3.extent(data, function(d) {
return d.date;
}));
y.domain([
d3.min(cities, function(c) {
return d3.min(c.values, function(v) {
return v.temperature;
});
}),
d3.max(cities, function(c) {
return d3.max(c.values, function(v) {
return v.temperature;
});
})
]);
var legend = svg.selectAll('g')
.data(cities)
.enter()
.append('g')
.attr('class', 'legend');
legend.append('rect')
.attr('x', width - 20)
.attr('y', function(d, i) {
return i * 20;
})
.attr('width', 10)
.attr('height', 10)
.style('fill', function(d) {
return color(d.name);
});
legend.append('text')
.attr('x', width - 8)
.attr('y', function(d, i) {
return (i * 20) + 9;
})
.text(function(d) {
return d.name;
});
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Temperature (ºF)");
var city = svg.selectAll(".city")
.data(cities)
.enter().append("g")
.attr("class", "city");
city.append("path")
.attr("class", "line")
.attr("d", function(d) {
return line(d.values);
})
.style("stroke", function(d) {
return color(d.name);
});
city.append("text")
.datum(function(d) {
return {
name: d.name,
value: d.values[d.values.length - 1]
};
})
.attr("transform", function(d) {
return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")";
})
.attr("x", 3)
.attr("dy", ".35em")
.text(function(d) {
return d.name;
});
// **************************************************************************************** //
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([cities])
.enter()
.append("g")
.attr("class", "mouse-per-line");
mousePerLine.selectAll('.mouse-per-line') // Rectangle
.data([cities])
.enter()
.append("rect")
.attr("width", width/2)
.attr("height", height/3)
.style("padding", "5px")
.style("stroke", "#272525")
.style("fill", "#272525")
.style("stroke-width", "1px")
.style("opacity", "0")
.attr('x', 10)
.attr('y', -45);
mousePerLine.selectAll('.innerRect')
.data(cities)
.enter()
.append("rect")
.attr("width", 10)
.attr("height", 10)
.style("fill", "none")
.attr("class", "innerRect");
mousePerLine.selectAll('.mouse-per-line') // Circle
.data(cities)
.enter()
.append("circle")
.attr("r", 5)
.style("stroke", function(d) {
return color(d.name);
})
.style("fill", function(d) {
return color(d.name);
})
.style("stroke-width", "1px")
.style("opacity", "0");
mousePerLine.append("text")
.attr("class", "DateText");
mousePerLine.selectAll('.mouse-per-line') // Text
.data(cities)
.enter()
.append("text")
.attr("class", "ValueText")
// .attr("transform", "translate(15,13)")
.style("fill", function(d) {
return color(d.name);
})
.style("font-weight", "bold")
.style("font-size", "10pt");
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 rect")
.style("opacity", "0");
d3.selectAll(".mouse-per-line innerRect")
.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 hover show line, circles and text
d3.select(".mouse-line")
.style("opacity", "1");
d3.selectAll(".mouse-per-line rect")
.style("opacity", "1");
d3.selectAll(".mouse-per-line innerRect")
.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);
console.log(mouse);
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("foo", function(d, i) {
var xDate = x.invert(mouse[0]);
var bisect;
var heights = [];
var xDateValue = /\w*.\s.\d.\d*.\d*.:\d*.:\d*/.exec(xDate);
// console.log(xDateValue);
d3.selectAll('circle')
.attr("transform", function(d, j) {
bisect = d3.bisector(function(d) {
return d.date;
}).right;
idx = bisect(d.values, xDate);
var beginning = 0,
end = lines[i].getTotalLength(),
target = null;
while (true) {
target = Math.floor((beginning + end)/2);
pos = lines[j].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
}
heights[j] = pos.y;
return "translate(" + mouse[0] + "," + pos.y + ")";
});
var avgheight = 0;
for (var z = 0; z < heights.length; z++) {
avgheight = avgheight + heights[z];
}
avgheight = avgheight/d.length;
d3.select(this)
.select('rect')
.attr("transform", function(d, i) {
return "translate(" + mouse[0] + "," + avgheight + ")";
});
var rectangleText = "";
for (var t = 1; t < heights.length; t++) {
rectangleText = rectangleText + "<br/>" + y.invert(heights[t]).toFixed(2);
}
d3.select(this)
.selectAll('.innerRect')
.attr("transform", function(d, i) {
return "translate(" + (mouse[0] + 15) + "," + (avgheight + 40 - (i * 20)) + ")";
})
.attr('width', 10)
.attr('height', 10)
.attr("dx", '20px')
.attr("dy", '0px')
.style('fill', function(d) {
return color(d.name);
});
d3.select(this)
.select(".DateText")
.text(xDateValue)
.attr("transform", function(d, i) {
return "translate(" + mouse[0] + "," + (avgheight - 25) + ")";
})
.attr("dx", '20px')
.style("fill", "white")
.style("font-weight", "bold")
.style("font-size", "10pt");
d3.select(this)
.selectAll('.ValueText')
.text(function(d, i) {
return d.name + " " + y.invert(heights[i]).toFixed(2)
})
.attr("transform", function(d, i) {
return "translate(" + (mouse[0] + 17) + "," + (avgheight + 50 - (i * 20)) + ")";
})
.attr("dx", '20px');
return "translate(" + mouse[0] + "," + pos.y + ")";
});
});
</script>
</body>
</html>
下面是使用D3为 “鼠标悬停” 动画的完整解决方案这个多线图。感谢所有的帮助和支持。希望这可以帮助。
相关问题
- 1. D3 x轴不显示所有数据
- 2. d3矩形不显示
- 3. D3 v4条形图X轴负值
- 4. d3.js:突出显示的x轴标记的列/条形图
- 5. 使用checkMouse()移动矩形沿X轴()
- 6. D3酒吧char x轴线不显示
- 7. 无法在NVD3显示所有x轴刻度值
- 8. Android的图形库 - 图表不显示所有的X轴值
- 9. 用D3显示一个只显示唯一值的列表
- 10. 显示SSRS中X轴的所有值
- 11. Graphview不显示所有的x轴值
- 12. D3矩形插值
- 13. d3时间格式x轴显示相同的值
- 14. ZedGraph x轴图形上的矩形顶
- 15. d3.js nvd3在x轴上的日期:只显示一些日期
- 16. D3轴不显示
- 17. C# - 使用可定制的矩形创建X轴和Y轴
- 18. 只显示一次左值
- 19. 图表没有显示y轴和x轴上的所有值
- 20. 显示数据在矩形圆上的使用点击d3.js
- 21. AngularJS只有一次显示
- 22. D3:tickformat方法,只显示一年
- 23. 什么规模,用于表示年只在X轴D3 JS
- 24. D3条形图左对齐x轴
- 25. Jqplot只显示几个x轴刻度
- 26. Python绘图x轴显示只选项
- 27. 如何使用d3 .ticks在条形图中显示原始y轴值
- 28. D3 - X轴中的不必要的值
- 29. 使用D3.js绘制矩形矩阵
- 30. D3.js在x轴上的样式值创建了图形
你好,请帮助我。我被卡住了。 – Rach