Created
March 24, 2019 07:13
-
-
Save paitonic/84c2a59424256748212ebffe92ec097b to your computer and use it in GitHub Desktop.
svg-charts.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>SVG Charts</title> | |
</head> | |
<body> | |
<div id="svg-bar"></div> | |
<div id="svg-area"></div> | |
<div id="svg-line"></div> | |
<script src="svg-charts.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// See Feature Scaling formula at https://en.wikipedia.org/wiki/Normalization_(statistics) | |
// Also, here is good explanation why it's needed http://chimera.labs.oreilly.com/books/1230000000345/ch07.html#_apples_and_pixels | |
function rescale(val, minValue, maxValue, fromRange, toRange) { | |
return fromRange + ((val - minValue) * (toRange - fromRange)) / (maxValue - minValue); | |
} | |
function move(x, y) { | |
return 'M' + x + ',' + y; | |
} | |
function line(x, y) { | |
return 'L' + x + ',' + y; | |
} | |
// generates path for a line chart. | |
var lineChart = function(data, dimensions, options, containerId) { | |
var totalDataPoints = data.length, | |
maxValue = Math.max.apply(null, data), | |
minValue = Math.min.apply(null, data), | |
path = move(scaleX(0), scaleY(data[0])); | |
for (var i = 1, max = data.length; i < max; i += 1) { | |
path += line(scaleX(i), scaleY(data[i])); | |
} | |
function scaleX(valueIdx) { | |
return valueIdx * (dimensions.width / (totalDataPoints-1)); | |
} | |
function scaleY(val) { | |
if (minValue === maxValue) { | |
return 0; | |
} | |
console.log(rescale(val, minValue, maxValue, 0, dimensions.height)) | |
return dimensions.height - rescale(val, minValue, maxValue, 0, dimensions.height); | |
} | |
// dom | |
var svgLineChart = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); | |
svgLineChart.setAttribute('height', dimensions.height); | |
svgLineChart.setAttribute('width', dimensions.width); | |
line = document.createElementNS('http://www.w3.org/2000/svg', 'path'); | |
line.setAttribute('d', path); | |
line.setAttribute('fill', 'none'); | |
line.setAttribute('stroke', '#7CB5EC'); | |
svgLineChart.appendChild(line); | |
var container = document.getElementById(containerId); | |
container.appendChild(svgLineChart); | |
} | |
// lineChart([1, 2, 3, 4, 5], {height: 250, width: 250}, {}, 'svg-line'); | |
// lineChart([5, 4, 3, 2, 1], {height: 250, width: 250}, {}, 'svg-line'); | |
lineChart([2, 4, 1, 5, 3], {height: 250, width: 250}, {}, 'svg-line'); | |
// lineChart([5, 5, 5, 5, 5], {height: 250, width: 250}, {}, 'svg-line'); | |
var areaChart = function(data, dimensions, options, containerId) { | |
var totalDataPoints = data.length, | |
maxValue = Math.max.apply(null, data), | |
minValue = Math.min.apply(null, data), | |
path = 'M' + '0' + ',' + dimensions.height; // move to the beginning of the chart | |
// connect left and right bottom edges so that its possible to create | |
// an area effect on chart by setting fill="#color" attribute on <path> | |
var pathEnding = 'L' + String(dimensions.width) + ',' + String(dimensions.height) + 'Z'; | |
data.forEach(function(val, idx) { | |
path += 'L' + scaleX(idx) + ',' + scaleY(val); | |
}) | |
function scaleX(valueIdx) { | |
return valueIdx * (dimensions.width / (totalDataPoints-1)); | |
} | |
function scaleY(val) { | |
if (minValue === maxValue) { | |
return 0; | |
} | |
console.log(rescale(val, minValue, maxValue, 0, dimensions.height)) | |
return dimensions.height - rescale(val, minValue, maxValue, 0, dimensions.height); | |
} | |
// dom | |
var svgAreaChart = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); | |
svgAreaChart.setAttribute('height', dimensions.height); | |
svgAreaChart.setAttribute('width', dimensions.width); | |
area = document.createElementNS('http://www.w3.org/2000/svg', 'path'); | |
area.setAttribute('d', path + pathEnding); | |
area.setAttribute('fill', '#CCD5DE'); | |
area.setAttribute('stroke', '#7CB5EC'); | |
line = document.createElementNS('http://www.w3.org/2000/svg', 'path'); | |
line.setAttribute('d', path); | |
line.setAttribute('fill', 'none'); | |
line.setAttribute('stroke', '#7CB5EC'); | |
svgAreaChart.appendChild(area); | |
svgAreaChart.appendChild(line); | |
var container = document.getElementById(containerId); | |
container.appendChild(svgAreaChart); | |
} | |
// areaChart([5, 5, 5, 5, 5], {height: 250, width: 250}, {}, 'svg-line-area'); | |
// areaChart([1, 2, 3, 4, 5], {height: 250, width: 250}, {}, 'svg-area'); | |
areaChart([2, 4, 1, 5, 3], {height: 250, width: 250}, {}, 'svg-line'); | |
var barChart = function(data, dimensions, containerId) { | |
var totalDataPoints = data.length, | |
maxValue = Math.max.apply(null, data), | |
barHeight, | |
barRightMargin = 1, | |
barWidth = Math.round((dimensions.width / totalDataPoints) - (barRightMargin * (totalDataPoints-1) / totalDataPoints)), | |
barX = 0, | |
barY, | |
rectangles = []; | |
data.forEach(function(val, idx) { | |
barHeight = val / maxValue * dimensions.height; | |
barY = dimensions.height - barHeight; | |
rectangles.push({x: barX, y: barY, width: barWidth, height: barHeight}); | |
barX = barX + barWidth + barRightMargin; | |
}); | |
rectangles.forEach(function(rectangle) { | |
console.log('<rect x="' + rectangle.x + '" y="' + rectangle.y + '" width="' + rectangle.width + '" height="' + rectangle.height + '"/>'); | |
}); | |
// dom | |
var svgContainer = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); | |
svgContainer.setAttribute('height', dimensions.height); | |
svgContainer.setAttribute('width', dimensions.width); | |
var rect; | |
rectangles.forEach(function(rectangle) { | |
rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); | |
rect.setAttribute('x', rectangle.x); | |
rect.setAttribute('y', rectangle.y); | |
rect.setAttribute('width', rectangle.width); | |
rect.setAttribute('height', rectangle.height); | |
svgContainer.appendChild(rect); | |
}); | |
var container = document.getElementById(containerId); | |
container.appendChild(svgContainer); | |
return rectangles; | |
} | |
barChart([1, 2, 3, 4, 5], {height: 250, width: 250}, 'svg-bar'); | |
// barChart([1, 1, 1, 1, 1], {height: 250, width: 250}, 'svg-bar'); | |
// barChart([5, 1, 2, 4, 3], {height: 250, width: 250}, 'svg-bar'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment