d3 | | d3 tiered pie chart | Search

This code generates an SVG image of a word cloud by using D3.js and the d3-cloud library to layout and style words based on their frequency. It takes an array of word objects as input and returns an SVG string representing the word cloud.

Run example

npm run import -- "Create a word-cloud"

Create a word-cloud

var D3Node = require('d3-node');
var cloud = require('d3-cloud');

var margin = {top: 20, right: 20, bottom: 30, left: 50},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

function drawD3Cloud(wordCount) {
    var d3n = new D3Node(); // initializes D3 with container element 
    var d3 = d3n.d3;
    var fill = d3.scaleOrdinal(d3.schemeCategory20);

    d3n.createSVG(
        width + margin.left + margin.right,
        height + margin.top + margin.bottom)
        .append('g')
        .attr(
            'transform',
            'translate(' + (margin.left + width / 2) + ',' + (margin.top + height / 2) + ')')
        .selectAll('text')
        .data(wordCount)
        .enter().append('text')
        .style('font-size', function (d) {
            return d.size + 'px';
        })
        .style('font-family', 'Impact')
        .style('fill', function (d, i) {
            return fill(i);
        })
        .attr('text-anchor', 'middle')
        .attr('transform', function (d) {
            return 'translate(' + [d.x, d.y] + ')rotate(' + d.rotate + ')';
        })
        .text(function (d) {
            return d.text;
        });

    return d3n.svgString();
};
function d3CloudToSVG(wordCount) {
    console.log('git');
    var Canvas = require('canvas');
    return new Promise(resolve => {
        cloud()
            .canvas(function () {
                return new Canvas(1, 1);
            })
            .size([width, height])
            .words(wordCount)
            .padding(0)
            .rotate(function () {
                return ~~(Math.random() * 120) - 60;
            })
            .font('Impact')
            .fontSize(function (d) {
                return d.size;
            })
            .on('end', function (wordCount) {
                resolve(drawD3Cloud(wordCount));
            })
            .start();
    });
};
module.exports = d3CloudToSVG;

What the code could have been:

const { createCanvas } = require('canvas');
const cloud = require('d3-cloud');
const { D3Node } = require('d3-node');

/**
 * Configuration for the D3 chart.
 * @type {Object}
 */
const config = {
  margin: {
    top: 20,
    right: 20,
    bottom: 30,
    left: 50,
  },
  width: 960,
  height: 500,
};

/**
 * Function to draw the D3 cloud chart.
 * @param {Object[]} wordCount - Array of objects containing word information.
 * @returns {Promise<string>} SVG string of the D3 chart.
 */
async function drawD3Cloud(wordCount) {
  // Create a new D3Node instance
  const d3n = new D3Node();
  const d3 = d3n.d3;

  // Create a scale for fill colors
  const fill = d3.scaleOrdinal(d3.schemeCategory20);

  // Create a new SVG element
  const svg = d3n.createSVG(config.width + config.margin.left + config.margin.right, config.height + config.margin.top + config.margin.bottom)
   .append('g')
   .attr('transform', `translate(${config.margin.left + config.width / 2}, ${config.margin.top + config.height / 2})`);

  // Select all text elements and bind data
  svg.selectAll('text')
   .data(wordCount)
   .enter()
   .append('text')
   .style('font-size', (d) => `${d.size}px`)
   .style('font-family', 'Impact')
   .style('fill', (d, i) => fill(i))
   .attr('text-anchor','middle')
   .attr('transform', (d) => `translate(${d.x}, ${d.y}) rotate(${d.rotate})`)
   .text((d) => d.text);

  // Return the SVG string
  return d3n.svgString();
}

/**
 * Function to generate the D3 cloud chart.
 * @param {Object[]} wordCount - Array of objects containing word information.
 * @returns {Promise<string>} SVG string of the D3 chart.
 */
async function d3CloudToSVG(wordCount) {
  // Create a new canvas element
  const canvas = createCanvas(1, 1);
  const context = canvas.getContext('2d');

  // Create a new cloud instance
  const cloudInstance = cloud()
   .canvas(() => canvas)
   .size([config.width, config.height])
   .words(wordCount)
   .padding(0)
   .rotate(() => ~~(Math.random() * 120) - 60)
   .font('Impact')
   .fontSize((d) => d.size)
   .on('end', (wordCount) => {
      // Draw the D3 cloud chart
      const svgString = drawD3Cloud(wordCount);
      context.font = '16px Arial';
      context.fillStyle = 'white';
      context.textAlign = 'center';
      context.textBaseline ='middle';
      context.fillText(svgString, canvas.width / 2, canvas.height / 2);
      // Return the SVG string
      return canvas.toDataURL();
    })
   .start();

  // Wait for the cloud instance to finish
  return new Promise((resolve) => {
    cloudInstance.on('end', (svgString) => resolve(svgString));
  });
}

module.exports = d3CloudToSVG;

This code generates an SVG image of a word cloud using D3.js and the d3-cloud library.

Here's a breakdown:

  1. Setup:

  2. drawD3Cloud Function:

  3. d3CloudToSVG Function:

  4. Export:

In essence, this code takes an array of words with their frequencies and generates a visually appealing word cloud as an SVG image.