Published
Edited
Sep 11, 2018
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// line chart with params
lineChart = (height, data, xAxisColumn, yAxisColumn, dateFormatter, lineColor ) => {
const margin = ({top: 10, right: 40, bottom: 20, left: 40})
const svg = d3.select(DOM.svg(width, height));
const x = d3.scaleTime()
.domain(d3.extent(data, d => d[xAxisColumn]))
.range([margin.left, width - margin.right])
// It doesn't starts at 0....
const y = d3.scaleLinear()
.domain( [d3.min(data, d => d[yAxisColumn]), d3.max(data, d => d[yAxisColumn]) ] ).nice()
.range([height - margin.bottom, margin.top])
const xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x).ticks(width / 45).tickSizeOuter(0))
const yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y).ticks(8, ".0f"))
.call(g => g.select(".domain").remove())
.call(g => g.select(".tick:last-of-type text").clone()
.attr("x", 3)
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text(data.y))
// line generator
const line = d3.line()
.defined(d => !isNaN(d[yAxisColumn] ) )
//.defined(d => ( d[yAxisColumn] > 20000 ) )
.x(d => x(d[xAxisColumn]))
.y(d => y(d[yAxisColumn]))
svg.append("text")
.attr("x", (width / 2))
.attr("y", margin.top + 5)
.attr("text-anchor", "middle")
.style("font-size", "12px")
.style("text-decoration", "none")
.style("font-family", "Arial, Helvetica, sans-serif")
.style("text-transform", "lowercase")
.text(yAxisColumn);

svg.append("g")
.call(xAxis);

svg.append("g")
.call(yAxis);
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke",lineColor)
.attr("stroke-width", 1.5)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("d", line);
///////////////////////////////////////////////////////
var focusColor = "#2874A6"
var focus = svg.append("g")
.attr("class", "focus")
.style("display", "none");

focus.append("line")
.attr("class", "x-hover-line hover-line")
.attr("y1", 0)
.attr("y2", height)
.style("stroke", focusColor)
.style("stroke-width", "0.5px")
.style("stroke-dasharray", "3,3");

focus.append("circle")
.attr("r", 3.0)
.attr("fill", focusColor);

focus.append("text")
.attr("x", 10)
.attr("dy", ".45em")
.attr("fill", focusColor)
.style("font-size", "12px")
.style("font-family", "Arial, Helvetica, sans-serif")
.style("text-shadow", "2px 2px 1px #E5E8E8");

svg.append("rect")
.attr("transform", "translate(" +0 + "," + 0+ ")")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all")
.on("mouseover", () => { focus.style("display", null); })
.on("mouseout", () => { focus.style("display", "none"); })
.on("mousemove", mousemove);

const bisectDate = d3.bisector(function(d) { return d[xAxisColumn]; }).left
function mousemove() {
var x0 = x.invert(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1),
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0[xAxisColumn] > d1[xAxisColumn] - x0 ? d1 : d0;
focus.attr("transform", "translate(" + x(d[xAxisColumn]) + "," + y(d[yAxisColumn]) + ")");
focus.select("text").text( () => { return dateFormatter(d1[xAxisColumn]) + " : "+ numberFormat(d[yAxisColumn]) ; });
focus.select(".x-hover-line").attr("y2", height - y(d[yAxisColumn]) - margin.bottom );
}

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more