Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
.svg-plot-area {
fill: none;
}
body {
margin: 2em;
}
.tick line {
opacity: 0.4;
stroke: #9b9999;
}
.axis--x path {
stroke: gray;
stroke-width: 1.5px;
}
.axis--x {
text-anchor: right;
}
.axis--x path {
stroke: gray;
stroke-width: 1.5px;
}
.svg-chart-line {
fill: none;
stroke: #007CC2;
stroke-width: 2.5px;
}
svg {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<script>
var w = 960;
var h = 500;
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h)
var parseDate = d3.timeParse('%d.%m.%Y');
var x = d3.scaleTime().range([40, w - 80]).nice();
var y = d3.scaleLinear().range([h - 80, 40]).nice();
var chartLine = d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.price); });
var markerLine = appendMarkerLine(svg, h - 80);
var marker = appendMarker(svg);
d3.json('data.json', function(error, json) {
if (error) throw error
var data = [];
for(var i = 0; i < json.length; i++) {
data.push(parseType(json[i]));
}
var bisect = d3.bisector(function(d) { return d.date; }).left;
var plotArea = svg.append('g')
.attr('class', 'svg-plot-area')
.attr('id', 'plot-area-main');
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.price; })]);
var xAxis = d3.axisBottom(x).tickSizeInner(-(h - 120)).tickFormat(d3.timeFormat('%x')).tickPadding(7);
var yAxis = d3.axisLeft(y).tickSizeInner(-(w - 120)).tickPadding(7);
plotArea.append('path')
.datum(data)
.attr('class', 'svg-chart-line')
.attr('d', chartLine);
plotArea.append('g')
.attr('class', 'axis axis--x')
.attr('transform', 'translate(0, '+ (h - 80) +')')
.call(xAxis);
plotArea.append('g')
.attr('class', 'axis axis--y')
.attr('transform', 'translate(40, 0)')
.call(yAxis);
plotArea.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', w)
.attr('height', h)
.style('fill', 'none')
.style('pointer-events', 'all')
.on('mouseover', function() {
marker.transition().duration(300).style('opacity', 20);
markerLine.transition().duration(300).style('opacity', 20);
})
.on('mouseout', function() {
marker.transition().duration(300).style('opacity', 0);
markerLine.transition().duration(300).style('opacity', 0);
})
.on('mousemove', function() {
var mouse = d3.mouse(this);
var xPos = mouse[0] - 20;
var x0 = x.invert(xPos);
i = bisect(data, x0);
var d = data[i];
if (d) {
var xp = x(d.date);
var yp = y(d.price);
marker.attr('transform', 'translate('+xp+', '+yp+')');
markerLine.attr('x1', xp).attr('x2', xp).attr('y1', yp);
}
});
});
function appendMarker(g) {
var circle = g.append('circle')
.classed('svg-marker', true)
.attr('cx', 0)
.attr('cy', 0)
.attr('r', 5)
.style('opacity', 0)
.style('fill', 'maroon');
return circle;
}
function appendMarkerLine(g, y2) {
var line = g.append('line')
.classed('svg-marker-line', true)
.attr('x1', 0)
.attr('x2', 0)
.attr('y1', 0)
.attr('y2', y2)
.style('opacity', 0)
.style('stroke', 'darkgray');
return line;
}
function parseType(d) {
return {
"price": d.price,
"date": parseDate(d.date)
};
}
</script>
</body>
https://d3js.org/d3.v4.min.js