<!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