Last active
August 2, 2021 00:22
-
-
Save alexp1917/48b47109a4d854e5e3f559df5d9a31ae to your computer and use it in GitHub Desktop.
d3 on Node.js example
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
node_modules/ |
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
// the alternative is to downgrade to a very old version | |
// then understanding the code below is not necessary | |
// but this works so lets use it for now | |
module.exports = new Promise(async resolve => { | |
var d3 = await import('d3'); | |
var d3Scale = await import('d3-scale'); | |
// for (var e of Object.keys(d3Scale)) { | |
var d3ScaleObj = { scale: {}, }; | |
for (var e in (d3Scale)) { | |
if (e.startsWith('scale')) { | |
var letter = e.substring('scale'.length, 'scale'.length + 1).toLowerCase() | |
var rest = e.substring('scale'.length + 1); | |
d3ScaleObj.scale[letter + rest] = d3Scale[e]; | |
} | |
} | |
resolve({ | |
...d3ScaleObj, | |
...d3, | |
}) | |
}) | |
// testing | |
// module.exports.then(d3 => console.log('scale', d3.scale)) | |
// setTimeout(function() {}, 10000); |
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
// https://gist.github.com/kunnix/148eadcfde3e978a1ad1d3ec9e2a7265 | |
// Instructions: | |
// npm install --save d3 jsdom | |
const fs = require('fs'); | |
const d3 = import('d3'); | |
const jsdom = require('jsdom'); | |
const { JSDOM } = jsdom; | |
async function main() { | |
const fakeDom = new JSDOM('<!DOCTYPE html><html><body></body></html>'); | |
const outputLocation = './output.svg'; | |
let body = (await d3).select(fakeDom.window.document).select('body'); | |
// Make an SVG Container | |
let svgContainer = body.append('div').attr('class', 'container') | |
.append("svg") | |
.attr("width", 1280) | |
.attr("height", 1024); | |
// Draw a line | |
let circle = svgContainer.append("line") | |
.attr("x1", 5) | |
.attr("y1", 5) | |
.attr("x2", 500) | |
.attr("y2", 500) | |
.attr("stroke-width", 2) | |
.attr("stroke", "black"); | |
// Output the result to console | |
console.log(body.select('.container').html()); | |
// Output the result to file | |
// fs.writeFileSync(outputLocation, body.select('.container').html()); | |
} | |
main(); |
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
var jsdom = require('jsdom'); | |
var fs = require('fs'); | |
var getD3 = require('./d3-shim'); | |
async function doTheThing(d3) { | |
var fakeDom = new jsdom.JSDOM(` | |
<!DOCTYPE html> | |
<html> | |
<body> | |
<!-- to illustrate/for visual debugging purposes --> | |
<div class="container" style="background-color:lightblue;"> | |
</div> | |
</body> | |
</html> | |
` | |
// simply replace all the extra whitespace | |
// so it doesnt print at the end | |
// | |
// \s means whitespace ('WS') (spaces, enter, tabs...) | |
// the regex means find any 2 or more WS, replace with '' | |
// | |
// the /g means do it for all of them, not just the 1st one | |
// | |
.replace(/\s\s+/g, '')); | |
// simulating browser, like "window" variable in browsers | |
var { window } = fakeDom; | |
// this is not the same as jQuery $('.container') or | |
// document.querySelector('.container'). | |
// | |
// im not sure why, but i tried to use standard DOM api's and it broke | |
// | |
var container = d3.select(window.document).select('.container'); | |
// Make the SVG itself | |
var svg = container | |
.append('svg') | |
.attr('width', 300) | |
.attr('height', 40); | |
var possibleStates = ['started', 'inProgress', 'completed']; | |
var possibleColors = ['yellow', 'orange', 'green' ]; | |
var segmentWidth = 100; | |
var currentState = possibleStates[1]; // 'inProgress' | |
var colorScale = d3.scale.ordinal() | |
.domain(possibleStates) | |
.range(possibleColors); | |
// draw a rectangle and forget about it | |
svg.append('rect') | |
.attr('class', 'bg-rect') | |
.attr('rx', 10) | |
.attr('ry', 10) | |
.attr('fill', 'gray') | |
.attr('height', 15) | |
// this could just as well have been a constant | |
// but d3 supports functions because its about dynamic data | |
.attr('width', () => segmentWidth * possibleStates.length) | |
.attr('x', 0); | |
// this time make a rectangle and dont forget about it | |
var progress = svg.append('rect') | |
.attr('class', 'progress-rect') | |
.attr('fill', () => colorScale(currentState)) | |
.attr('height', 15) | |
.attr('width', 0) | |
// "radius" (i think) -- this is what makes the corners rounded | |
.attr('rx', 10) | |
.attr('ry', 10) | |
.attr('x', 0); | |
// how to make it move slowly, animated | |
progress | |
.transition() | |
.duration(1000) | |
.attr('width', function(){ | |
var index = possibleStates.indexOf(currentState); | |
return (index + 1) * segmentWidth; | |
}); | |
// this overrides the previous action | |
progress.attr('width', 250); | |
/** | |
* requires waiting | |
**/ | |
function moveProgressBar(state = 'inProgress') { | |
progress.transition() | |
.duration(0) | |
.attr('fill', function(){ | |
return colorScale(state); | |
}) | |
.attr('width', function(){ | |
var index = possibleStates.indexOf(state); | |
return (index + 1) * segmentWidth; | |
}); | |
} | |
return { | |
fakeDom, | |
container, | |
svg, | |
moveProgressBar, | |
}; | |
} | |
async function progressBar() { | |
var d3 = await getD3; | |
var output = await doTheThing(d3); | |
var html = output.fakeDom.serialize(); | |
var svg = output.svg.node().outerHTML; | |
console.log('html'); | |
console.log(html); | |
// <!DOCTYPE html><html><head></head><body><div class="container" style="background-color:lightblue;"><div class="container"><svg width="300" height="40"><rect class="bg-rect" rx="10" ry="10" fill="gray" height="15" width="300" x="0"></rect><rect class="progress-rect" fill="orange" height="15" width="250" rx="10" ry="10" x="0"></rect></svg></div></div></body></html> | |
console.log('svg'); | |
console.log(svg); | |
// <svg width="300" height="40"> | |
// <rect class="bg-rect" rx="10" ry="10" fill="gray" height="15" width="300" x="0"></rect> | |
// <rect class="progress-rect" fill="orange" height="15" width="250" rx="10" ry="10" x="0"></rect> | |
// </svg> | |
// await fs.promises.writeFile('progress-bar.html', html, 'utf8'); | |
return output; | |
} | |
if (require.main === module) | |
progressBar(); | |
module.exports = { progressBar }; |
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
import * as d3 from 'd3'; | |
console.log(d3) |
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
{ | |
"name": "blah", | |
"version": "0.0.1", | |
"description": "", | |
"main": "index.js", | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"keywords": [], | |
"author": "Alexander Pavlovich <[email protected]>", | |
"license": "GPL-3.0-or-later", | |
"dependencies": { | |
"d3": "^7.0.0", | |
"d3-scale": "^4.0.0", | |
"jsdom": "^16.7.0", | |
"pdfmake": "^0.2.0" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment