Araç ipuçlarıyla D3.js kullanarak çok satırlı bir grafik hazırladım. Her şey bu grafikte iyi çalışıyor ancak grafikteki tüm grafikler için araç ipuçlarına stil eklemek istiyorum ancak bunu yapamıyorum. Çok satırlı D3.js çizgi grafik biçiminde araç ipucunu şekillendirme
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 + ")";
});
});
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;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Çözüm için teşekkür ederim ama bana bir şey daha yardımcı olabilir misiniz? Fare hareket ettiğinde satırı kaldırmak istiyorum ve aynı zamanda grafik kesiştiğinde veya birbirine yaklaştığında, benzer şekilde araç ipucunu konumlandırmak istiyorum, bu durumda, araç ipucu dikdörtgenleri birbiriyle kesişmemeli ve otomatik olarak hizalanmalarını değiştirmemelidir. mümkün mü? – nikunj2512
@ nikunj2512, araç ipucunun kesiştiğini algılamak için bir algo almak zor, bu zor bir çağrıdır .. :( – Cyril