Silhouette Gallery in JavaScript

Using ApexCharts with JavaScript

This Silhouette Gallery example uses ApexCharts.js directly in JavaScript, with no wrapper component.

Install it with npm install apexcharts, then mount the chart with new ApexCharts(element, options).render().

JavaScript installation guide
// Every button maps to one plotOptions.unit patch. The shapes come from
// apexcharts/unit-shapes, which registers each one under its own name; packed
// and columns are built in. Nothing else changes between views, which is the
// point: the dots keep their identity, colour and size, so the crowd re-forms
// instead of being rebuilt.
var VIEWS = {
  droplet: { layout: 'custom', positions: 'droplet' },
  tree: { layout: 'custom', positions: 'tree' },
  leaf: { layout: 'custom', positions: 'leaf' },
  sun: { layout: 'custom', positions: 'sun' },
  flame: { layout: 'custom', positions: 'flame' },
  fish: { layout: 'custom', positions: 'fish' },
  house: { layout: 'custom', positions: 'house' },
  battery: { layout: 'custom', positions: 'battery' },
  rocket: { layout: 'custom', positions: 'rocket' },
  bulb: { layout: 'custom', positions: 'bulb' },
  flask: { layout: 'custom', positions: 'flask' },
  car: { layout: 'custom', positions: 'car' },
  plane: { layout: 'custom', positions: 'plane' },
  human: { layout: 'custom', positions: 'human' },
  group: { layout: 'custom', positions: 'group' },
  target: { layout: 'custom', positions: 'target' },
  trophy: { layout: 'custom', positions: 'trophy' },
  moneybag: { layout: 'custom', positions: 'moneybag' },
  funnel: { layout: 'custom', positions: 'funnel' },
  shield: { layout: 'custom', positions: 'shield' },
  gear: { layout: 'custom', positions: 'gear' },
  robot: { layout: 'custom', positions: 'robot' },
  heart: { layout: 'custom', positions: 'heart' },
  pyramid: { layout: 'custom', positions: 'pyramid' },
  star: { layout: 'custom', positions: 'star' },
  arrow: { layout: 'custom', positions: 'arrow' },
  crown: { layout: 'custom', positions: 'crown' },
  cross: { layout: 'custom', positions: 'cross' },
  bolt: { layout: 'custom', positions: 'bolt' },
  globe: { layout: 'custom', positions: 'globe' },
  pin: { layout: 'custom', positions: 'pin' },
  mountain: { layout: 'custom', positions: 'mountain' },
  check: { layout: 'custom', positions: 'check' },
  wifi: { layout: 'custom', positions: 'wifi' },
  pulse: { layout: 'custom', positions: 'pulse' },
  xmark: { layout: 'custom', positions: 'xmark' },
  percent: { layout: 'custom', positions: 'percent' },
  question: { layout: 'custom', positions: 'question' },
  spiral: { layout: 'custom', positions: 'spiral' },
  packed: { layout: 'packed', positions: undefined },
  columns: { layout: 'columns', positions: undefined },
}

function setActive(id) {
  document
    .querySelectorAll('.actions button[data-view]')
    .forEach(function (btn) {
      btn.classList.toggle('active', btn.getAttribute('data-view') === id)
    })
}

function wireGallery(chart) {
  var current = 'heart'
  setActive(current)
  document
    .querySelectorAll('.actions button[data-view]')
    .forEach(function (btn) {
      btn.addEventListener('click', function () {
        var id = btn.getAttribute('data-view')
        if (id === current) return
        current = id
        setActive(current)
        chart.updateOptions({ plotOptions: { unit: VIEWS[id] } })
      })
    })
}

var options = {
  series: [576, 168, 42, 34],
  chart: {
    id: 'shapeGallery',
    type: 'unit',
    height: 460,
    animations: {
      enabled: true,
      speed: 900,
    },
  },
  labels: ['Engineering', 'Sales', 'Marketing', 'Operations'],
  colors: ['#008FFB', '#00B8D9', '#FFAB00', '#FF4560'],
  plotOptions: {
    unit: {
      layout: 'custom',
      positions: 'heart',
      // Keyed by global order, so the crowd migrates across a relayout instead
      // of each category fading in and out on the spot.
      transition: 'flow',
      clusterLabels: {
        show: false,
      },
    },
  },
  legend: {
    position: 'bottom',
  },
}

var chart = new ApexCharts(document.querySelector('#chart'), options)
chart.render()

// VIEWS, setActive and wireGallery live in the shared head script, which also
// registers every shape layout.
wireGallery(chart)