Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<style>
/*multi line chart*/
.chart-wrapper .inner-wrapper {
position: relative;
width: 100%;
}
.chart-wrapper .outer-box {
position: absolute;
top:15px;
bottom: 0;
left: 0;
right: 0;
}
.chart-wrapper .inner-box {
width: 100%;
height: 100%;
}
.chart-wrapper text {
font-family: 'Roboto', sans-serif;
font-size: 14px;
}
.chart-wrapper p {
font-size: 16px;
margin-top: 5px;
margin-bottom: 40px;
}
.chart-wrapper .axis path,
.chart-wrapper .axis line {
fill: none;
shape-rendering: crispEdges;
}
.chart-wrapper .axis path {
stroke-width: 1px;
}
.chart-wrapper .line {
fill: none;
stroke: steelblue;
stroke-width: 3.5px;
}
.chart-wrapper .legend {
display: flex;
padding: 10px 50px;
text-align: center;
}
.chart-wrapper .legend>div {
margin: 0px 25px 10px 0px;
flex-grow: 0;
}
.chart-wrapper .legend p {
display: inline;
font-size: 0.8em;
font-family: 'Roboto', sans-serif;
font-weight: 600;
}
.chart-wrapper .legend .series-marker {
height: 1em;
width: 1em;
border-radius: 35%;
background-color: crimson;
display: inline-block;
margin-right: 4px;
margin-bottom: -0.16rem;
}
.chart-wrapper .overlay {
fill: none;
pointer-events: all;
}
.chart-wrapper .focus circle {
fill: #fff;
stroke: crimson;
stroke-width: 3px;
fill-opacity: 15%;
}
.chart-wrapper .focus rect {
fill: lightblue;
opacity: 0.4;
border-radius: 2px;
}
.chart-wrapper .focus.line {
stroke: steelblue;
stroke-dasharray: 2, 5;
stroke-width: 2;
opacity: 0.5;
}
@media (max-width:500px) {
/*.chart-wrapper .line {
stroke-width: 2px;
}*/
.chart-wrapper .legend {
font-size: 14px;
}
}
/*line chart responsive css*/
.focus_animate{ position:absolute;
z-index:2;}
.focus_animate circle {
transition: all .7s ease-in-out;
animation: move 1s ease-in-out infinite;
fill:#f39c12;stroke-width:3;stroke:rgb(0,0,0);
}
</style>
</head>
<body>
<div class="chart-wrapper" id="chart-line1"></div>
<script>
var data = [{
"year": 1980,
"data1": 70,
"data2": 52,
"data3": 145,
"data4": 75
},
{
"year": 1981,
"data1": 77,
"data2": 51,
"data3": 156,
"data4": 80
},
{
"year": 1982,
"data1": 81,
"data2": 55,
"data3": 169,
"data4": 79
},
{
"year": 1983,
"data1": 78,
"data2": 55,
"data3": 171,
"data4": 91
},
{
"year": 1984,
"data1": 80,
"data2": 55,
"data3": 187,
"data4": 102
},
{
"year": 1985,
"data1": 79,
"data2": 53,
"data3": 199,
"data4": 103
},
{
"year": 1986,
"data1": 79,
"data2": 54,
"data3": 204,
"data4": 102
},
{
"year": 1987,
"data1": 78,
"data2": 53,
"data3": 218,
"data4": 104
},
{
"year": 1988,
"data1": 75,
"data2": 51,
"data3": 232,
"data4": 105
},
{
"year": 1989,
"data1": 78,
"data2": 48,
"data3": 233,
"data4": 106
},
{
"year": 1990,
"data1": 76,
"data2": 51,
"data3": 233,
"data4": 112
},
{
"year": 1991,
"data1": 73,
"data2": 55,
"data3": 232,
"data4": 111
},
{
"year": 1992,
"data1": 70,
"data2": 52,
"data3": 240,
"data4": 122
},
{
"year": 1993,
"data1": 69,
"data2": 50,
"data3": 256,
"data4": 122
},
{
"year": 1994,
"data1": 74,
"data2": 50,
"data3": 273,
"data4": 131
},
{
"year": 1995,
"data1": 71,
"data2": 51,
"data3": 286,
"data4": 128
},
{
"year": 1996,
"data1": 71,
"data2": 53,
"data3": 283,
"data4": 129
},
{
"year": 1997,
"data1": 76,
"data2": 51,
"data3": 292,
"data4": 126
},
{
"year": 1998,
"data1": 81,
"data2": 49,
"data3": 298,
"data4": 132
},
{
"year": 1999,
"data1": 80,
"data2": 53,
"data3": 313,
"data4": 142
},
{
"year": 2000,
"data1": 77,
"data2": 59,
"data3": 321,
"data4": 152
},
{
"year": 2001,
"data1": 82,
"data2": 63,
"data3": 338,
"data4": 162
},
{
"year": 2002,
"data1": 88,
"data2": 67,
"data3": 337,
"data4": 171
},
{
"year": 2003,
"data1": 90,
"data2": 69,
"data3": 338,
"data4": 177
},
{
"year": 2004,
"data1": 90,
"data2": 75,
"data3": 338,
"data4": 183
},
{
"year": 2005,
"data1": 92,
"data2": 80,
"data3": 351,
"data4": 180
},
{
"year": 2006,
"data1": 93,
"data2": 87,
"data3": 367,
"data4": 188
},
{
"year": 2007,
"data1": 91,
"data2": 91,
"data3": 375,
"data4": 186
},
{
"year": 2008,
"data1": 90,
"data2": 96,
"data3": 374,
"data4": 195
},
{
"year": 2009,
"data1": 97,
"data2": 97,
"data3": 385,
"data4": 207
},
{
"year": 2010,
"data1": 104,
"data2": 101,
"data3": 401,
"data4": 206
},
{
"year": 2011,
"data1": 111,
"data2": 106,
"data3": 403,
"data4": 205
},
{
"year": 2012,
"data1": 115,
"data2": 105,
"data3": 417,
"data4": 204
},
{
"year": 2013,
"data1": 117,
"data2": 108,
"data3": 420,
"data4": 211
},
{
"year": 2014,
"data1": 121,
"data2": 107,
"data3": 436,
"data4": 217
},
{
"year": 2015,
"data1": 121,
"data2": 104,
"data3": 449,
"data4": 216
}
];
function makeLineChart(dataset, xName, yObjs, axisLables) {
var chartObj = {};
var color = d3.scale.category10();
chartObj.xAxisLable = axisLables.xAxis;
chartObj.yAxisLable = axisLables.yAxis;
/*
yObjsects format:
{y1:{column:'',name:'name',color:'color'},y2}
*/
chartObj.data = dataset;
chartObj.margin = {
top: 15,
right: 60,
bottom: 30,
left: 50
};
chartObj.width = window.innerWidth - chartObj.margin.left - chartObj.margin.right;
chartObj.height = 420 - chartObj.margin.top - chartObj.margin.bottom;
// So we can pass the x and y as strings when creating the function
chartObj.xFunct = function (d) {
return d[xName]
};
// For each yObjs argument, create a yFunction
function getYFn(column) {
return function (d) {
return d[column];
};
}
// Object instead of array
chartObj.yFuncts = [];
for (var y in yObjs) {
yObjs[y].name = y;
yObjs[y].yFunct = getYFn(yObjs[y].column); //Need this list for the ymax function
chartObj.yFuncts.push(yObjs[y].yFunct);
}
//Formatter functions for the axes
chartObj.formatAsNumber = d3.format(".0f");
chartObj.formatAsDecimal = d3.format(".2f");
chartObj.formatAsCurrency = d3.format("$.2f");
chartObj.formatAsFloat = function (d) {
if (d % 1 !== 0) {
return d3.format(".2f")(d);
} else {
return d3.format(".0f")(d);
}
};
chartObj.xFormatter = chartObj.formatAsNumber;
chartObj.yFormatter = chartObj.formatAsFloat;
chartObj.bisectYear = d3.bisector(chartObj.xFunct).left; //< Can be overridden in definition
//Create scale functions
chartObj.xScale = d3.scale.linear().range([0, chartObj.width]).domain(d3.extent(chartObj.data, chartObj.xFunct)); //< Can be overridden in definition
// Get the max of every yFunct
chartObj.max = function (fn) {
return d3.max(chartObj.data, fn);
};
chartObj.yScale = d3.scale.linear().range([chartObj.height, 0]).domain([0, d3.max(chartObj.yFuncts.map(chartObj.max))]);
chartObj.formatAsYear = d3.format("");
//Create axis
chartObj.xAxis = d3.svg.axis().scale(chartObj.xScale)
.orient("bottom")
.tickFormat(chartObj.xFormatter)
// grid case
.innerTickSize(-chartObj.height)
.outerTickSize(0)
.tickPadding(10); //< Can be overridden in definition
chartObj.yAxis = d3.svg.axis().scale(chartObj.yScale)
.orient("left")
.tickFormat(chartObj.yFormatter)
// grid case
.innerTickSize(-chartObj.width).outerTickSize(0).tickPadding(10); //< Can be overridden in definition
// Build line building functions
function getYScaleFn(yObj) {
return function (d) {
return chartObj.yScale(yObjs[yObj].yFunct(d));
};
}
for (var yObj in yObjs) {
yObjs[yObj].line = d3.svg.line().interpolate("cardinal").x(function (d) {
return chartObj.xScale(chartObj.xFunct(d));
}).y(getYScaleFn(yObj));
}
chartObj.svg;
// Change chart size according to window size
chartObj.update_svg_size = function () {
chartObj.width = window.innerWidth - (chartObj.margin.left + chartObj.margin.right);
chartObj.height = parseInt(420, 10) - (chartObj.margin.top + chartObj.margin.bottom);
/* Update the range of the scale with new width/height */
chartObj.xScale.range([0, chartObj.width]);
chartObj.yScale.range([chartObj.height, 0]);
if (!chartObj.svg) {
return false;
}
/* Else Update the axis with the new scale */
chartObj.svg.select('.x.axis').attr("transform", "translate(0," + chartObj.height + ")").call(chartObj.xAxis);
chartObj.svg.select('.x.axis .label').attr("x", chartObj.width / 2);
chartObj.svg.select('.y.axis').call(chartObj.yAxis);
chartObj.svg.select('.y.axis .label').attr("x", -chartObj.height / 2);
/* Force D3 to recalculate and update the line */
for (var y in yObjs) {
yObjs[y].path.attr("d", yObjs[y].line);
}
d3.selectAll(".focus.line").attr("y2", chartObj.height);
chartObj.chartDiv.select('svg').attr("width", chartObj.width + (chartObj.margin.left + chartObj.margin.right)).attr("height", chartObj.height + (chartObj.margin.top + chartObj.margin.bottom));
chartObj.svg.select(".overlay").attr("width", chartObj.width).attr("height", chartObj.height);
return chartObj;
};
chartObj.bind = function (selector) {
chartObj.mainDiv = d3.select(selector);
// Add all the divs to make it centered and responsive
chartObj.mainDiv.append("div").attr("class", "inner-wrapper").append("div").attr("class", "outer-box").append("div").attr("class", "inner-box");
chartSelector = selector + " .inner-box";
chartObj.chartDiv = d3.select(chartSelector);
d3.select(window).on('resize.' + chartSelector, chartObj.update_svg_size);
chartObj.update_svg_size();
return chartObj;
};
// Render the chart
chartObj.render = function () {
//Create SVG element
chartObj.svg = chartObj.chartDiv.append("svg").attr("class", "chart-area").attr("width", chartObj.width + (chartObj.margin.left + chartObj.margin.right)).attr("height", chartObj.height + (chartObj.margin.top + chartObj.margin.bottom)).append(
"g").attr("transform", "translate(" + chartObj.margin.left + "," + chartObj.margin.top + ")");
// Draw Lines
for (var y in yObjs) {
yObjs[y].path = chartObj.svg.append("path").datum(chartObj.data).attr("class", "line").attr("d", yObjs[y].line).style("stroke", color(y)).attr("data-series", y).on("mouseover", function () {
focus.style("display", null);
}).on("mouseout", function () {
focus.transition().delay(700).style("display", "none");
}).on("mousemove", mousemove);
}
// Draw Axis
chartObj.svg.append("g").attr("class", "x axis").attr("transform", "translate(0," + chartObj.height + ")").call(chartObj.xAxis).append("text").attr("class", "label").attr("x", chartObj.width / 2).attr("y", 30).style("text-anchor", "middle")
.text(chartObj.xAxisLable);
chartObj.svg.append("g").attr("class", "y axis").call(chartObj.yAxis).append("text").attr("class", "label").attr("transform", "rotate(-90)").attr("y", -42).attr("x", -chartObj.height / 2).attr("dy", ".71em").style("text-anchor", "middle").text(
chartObj.yAxisLable);
//Draw tooltips
var focus = chartObj.svg.append("g").attr("class", "focus").style("display", "none");
for (var y in yObjs) {
yObjs[y].tooltip = focus.append("g");
yObjs[y].tooltip.append("circle").attr("r", 8);
yObjs[y].tooltip.append("rect").attr("x", 8).attr("y", "-10").attr("width", 40).attr("height", '20');
yObjs[y].tooltip.append("text").attr("x", 20).attr("dy", ".35em");
}
// Year label
focus.append("text").attr("class", "focus year").attr("x", 9).attr("y", 7);
// Focus line
focus.append("line").attr("class", "focus line").attr("y1", 0).attr("y2", chartObj.height);
//Draw legend
var legend = chartObj.mainDiv.append('div').attr("class", "legend");
for (var y in yObjs) {
series = legend.append('div');
series.append('div').attr("class", "series-marker").style("background-color", color(y));
series.append('p').text(y);
yObjs[y].legend = series;
}
// Overlay to capture hover
chartObj.svg.append("rect").attr("class", "overlay").attr("width", chartObj.width).attr("height", chartObj.height).on("mouseover", function () {
focus.style("display", null);
}).on("mouseout", function () {
focus.style("display", "none");
}).on("mousemove", mousemove);
return chartObj;
function mousemove() {
var x0 = chartObj.xScale.invert(d3.mouse(this)[0]),
i = chartObj.bisectYear(dataset, x0, 1),
d0 = chartObj.data[i - 1],
d1 = chartObj.data[i];
try {
var d = x0 - chartObj.xFunct(d0) > chartObj.xFunct(d1) - x0 ? d1 : d0;
} catch (e) {
return;
}
minY = chartObj.height;
for (var y in yObjs) {
yObjs[y].tooltip.attr("transform", "translate(" + chartObj.xScale(chartObj.xFunct(d)) + "," + chartObj.yScale(yObjs[y].yFunct(d)) + ")");
yObjs[y].tooltip.select("text").text(chartObj.yFormatter(yObjs[y].yFunct(d)));
minY = Math.min(minY, chartObj.yScale(yObjs[y].yFunct(d)));
}
focus.select(".focus.line").attr("transform", "translate(" + chartObj.xScale(chartObj.xFunct(d)) + ")").attr("y1", minY);
focus.select(".focus.year").text("Year: " + chartObj.xFormatter(chartObj.xFunct(d)));
}
};
return chartObj;
}
var data1 = data;
data1.forEach(function (d) {
d.year = +d.year;
d.data1 = +d.data1;
d.data2 = +d.data2;
d.data3 = +d.data3;
d.data4 = +d.data4;
});
var chart = makeLineChart(data1, 'year', {
'Data Name 1': {
column: 'data1'
},
'Data Name 2': {
column: 'data2'
},
'Data Name 3': {
column: 'data3'
},
'Data Name 4': {
column: 'data4'
}},
{
xAxis: 'x-axis label (own)',
yAxis: 'y-axis label (own)'
});
chart.bind("#chart-line1");
chart.render();
</script>
</body>
https://d3js.org/d3.v3.min.js
https://code.jquery.com/jquery-1.12.4.min.js