D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
skimlik
Full window
Github gist
LineChart with marker
Built with
blockbuilder.org
<!DOCTYPE html> <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