Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.js"></script>
<style>
body {
margin: 2em;
}
.tick line{
opacity: 0.2;
stroke: #9b9999;
}
.axis--x path {
stroke: gray;
stroke-width: 1.5px;
}
.svg-chart-line {
fill: none;
stroke: #007CC2;
stroke-width: 2.5px;
}
.svg-tooltip {
position: absolute;
width: 60px;
height: 20px;
left: 200px;
top: 100px;
text-align: center;
border-radius: 3px;
border: 1px solid #007CC2;
fill: #007CC2;
font-family: calibri helvetica sans-serif;
font-weight: bold;
pointer-events: none;
z-index: 19;
background-color: white;
box-shadow: 0 0 10px rgba(0,0,0,0.5);
}
</style>
</head>
<body>
<script>
var w = 900;
var h = 500;
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h)
var x = d3.scaleLinear().range([0, w - 80]);
var y = d3.scaleLinear().range([h - 80, 0]);
d3.json('data.json', function(error, data) {
if (error) {
console.log(error);
return;
}
x.domain(d3.extent(data, function(d) { return d.month; }));
y.domain([0, d3.max(data, function(d) { return d.revenue; })]);
var xAxis = d3.axisBottom(x).tickPadding(5).tickSizeInner(-(h - 80));
var yAxis = d3.axisLeft(y).tickPadding(5).tickSizeInner(-(w - 80));
var chartLine = d3.line()
.x(function(d) { return x(d.month); })
.y(function(d) { return y(d.revenue); });
var bisect = d3.bisector(function(d) {
return d.month;
}).left;
var tooltip = d3.select('body')
.append('div')
.attr('class', 'svg-tooltip')
.style('opacity', 0);
var marker = svg.append('circle')
.attr('cx', 0)
.attr('cy', 0)
.attr('r', 5)
.attr('class', 'svg-line-marker')
.style('stroke', '#000a19')
.style('fill', '#000a19')
.style('opacity', 0);
var markerLine = svg.append('line')
.classed("svg-line-marker-line", true)
.attr('x1', 0)
.attr('y1', 40)
.attr('x2', 0)
.attr('y2', h - 60)
.style('opacity', 0)
.style('stroke', '#000a19')
.style('stroke-width', '2');
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", w - 20)
.attr("height", h - 20);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(20,20)");
focus.append("path")
.datum(data)
.attr("class", "svg-chart-line")
.attr("d", chartLine);
focus.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0, "+(h - 80)+")" )
.call(xAxis);
focus.append('g')
.attr("class", "axis axis--y")
.call(yAxis);
var chartArea = svg.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', w)
.attr('height', h)
.style('fill', 'none')
.style('pointer-events', 'all');
chartArea
.on("mouseover", function() {
d3.select(".svg-line-marker")
.transition()
.duration(300)
.style("opacity", 20)
.style("stroke-width", 2);
d3.select(".svg-line-marker-line")
.transition().duration(300)
.style("opacity", 20).style("stroke-width", 2);
d3.select(".svg-tooltip")
.transition().duration(300)
.style("opacity", 20).style("stroke-width", 0.5);
})
.on("mouseout", function() {
d3.select(".svg-line-marker")
.transition().duration(300)
.style("opacity", 0).style("stroke-width", 0.5);
d3.select(".svg-line-marker-line")
.transition().duration(300)
.style("opacity", 0).style("stroke-width", 0.5);
d3.select(".svg-tooltip")
.transition().duration(300)
.style("opacity", 0).style("stroke-width", 0.5);
})
.on("mousemove", function() {
var mouse = d3.mouse(this);
var xPos = mouse[0];
var x0 = x.invert(xPos - 20);
var i = bisect(data, x0);
var d = data[i];
if (d) {
var xp = x(d.month) + 20;
var yp = y(d.revenue) + 20;
d3.select('.svg-tooltip').html(d.month + ": " +d.revenue);
d3.select('.svg-tooltip')
.style('left', (xp + 30) +'px')
.style('top', (yp - 3) +'px');
d3.select('.svg-line-marker')
.style('opacity', 20).attr('transform', 'translate('+xp+', '+yp+')');
d3.select('.svg-line-marker-line')
.attr('y1', yp)
.attr('x1', xp)
.attr('x2', xp);
}
});
});
</script>
</body>
https://d3js.org/d3.v4.js