Skip to main content
Td

D3 Svelte Treemap

D3 treemap example, written in Svelte.


by Tony Dang on

This post is part of a series on converting the official D3 examples to Svelte.

D3 treemap written in Svelte

analytics animate data display flex physics query scale util vis
flare.vis.operator.layout.NodeLinkTreeLayout 12,870NodeLinkTreeLayout12,870 flare.vis.operator.layout.RadialTreeLayout 12,348RadialTreeLayout12,348 flare.vis.operator.layout.CirclePackingLayout 12,003CirclePackingLayout12,003 flare.vis.operator.layout.CircleLayout 9,317CircleLayout9,317 flare.vis.operator.layout.TreeMapLayout 9,191TreeMapLayout9,191 flare.vis.operator.layout.StackedAreaLayout 9,121StackedAreaLayout9,121 flare.vis.operator.layout.ForceDirectedLayout 8,411ForceDirectedLayout8,411 flare.vis.operator.layout.Layout 7,881Layout7,881 flare.vis.operator.layout.AxisLayout 6,725AxisLayout6,725 flare.vis.operator.layout.IcicleTreeLayout 4,864IcicleTreeLayout4,864 flare.vis.operator.layout.DendrogramLayout 4,853DendrogramLayout4,853 flare.vis.operator.layout.BundledEdgeRouter 3,727BundledEdgeRouter3,727 flare.vis.operator.layout.IndentedTreeLayout 3,174IndentedTreeLayout3,174 flare.vis.operator.layout.PieLayout 2,728PieLayout2,728 flare.vis.operator.layout.RandomLayout 870RandomLayout870 flare.vis.operator.label.Labeler 9,956Labeler9,956 flare.vis.operator.label.RadialLabeler 3,899RadialLabeler3,899 flare.vis.operator.label.StackedAreaLabeler 3,202StackedAreaLabeler3,202 flare.vis.operator.encoder.PropertyEncoder 4,138PropertyEncoder4,138 flare.vis.operator.encoder.Encoder 4,060Encoder4,060 flare.vis.operator.encoder.ColorEncoder 3,179ColorEncoder3,179 flare.vis.operator.encoder.SizeEncoder 1,830SizeEncoder1,830 flare.vis.operator.encoder.ShapeEncoder 1,690ShapeEncoder1,690 flare.vis.operator.distortion.Distortion 6,314Distortion6,314 flare.vis.operator.distortion.BifocalDistortion 4,461BifocalDistortion4,461 flare.vis.operator.distortion.FisheyeDistortion 3,444FisheyeDistortion3,444 flare.vis.operator.filter.FisheyeTreeFilter 5,219FisheyeTreeFilter5,219 flare.vis.operator.filter.VisibilityFilter 3,509VisibilityFilter3,509 flare.vis.operator.filter.GraphDistanceFilter 3,165GraphDistanceFilter3,165 flare.vis.operator.OperatorList 5,248OperatorList5,248 flare.vis.operator.OperatorSequence 4,190OperatorSequence4,190 flare.vis.operator.OperatorSwitch 2,581OperatorSwitch2,581 flare.vis.operator.Operator 2,490Operator2,490 flare.vis.operator.SortOperator 2,023SortOperator2,023 flare.vis.operator.IOperator 1,286IOperator1,286 flare.vis.data.Data 20,544Data20,544 flare.vis.data.DataList 19,788DataList19,788 flare.vis.data.NodeSprite 19,382NodeSprite19,382 flare.vis.data.ScaleBinding 11,275ScaleBinding11,275 flare.vis.data.DataSprite 10,349DataSprite10,349 flare.vis.data.TreeBuilder 9,930TreeBuilder9,930 flare.vis.data.render.EdgeRenderer 5,569EdgeRenderer5,569 flare.vis.data.render.ShapeRenderer 2,247ShapeRenderer2,247 flare.vis.data.render.ArrowType 698ArrowType698 flare.vis.data.render.IRenderer 353IRenderer353 flare.vis.data.Tree 7,147Tree7,147 flare.vis.data.EdgeSprite 3,301EdgeSprite3,301 flare.vis.controls.TooltipControl 8,435TooltipControl8,435 flare.vis.controls.SelectionControl 7,862SelectionControl7,862 flare.vis.controls.PanZoomControl 5,222PanZoomControl5,222 flare.vis.controls.HoverControl 4,896HoverControl4,896 flare.vis.controls.ControlList 4,665ControlList4,665 flare.vis.controls.ClickControl 3,824ClickControl3,824 flare.vis.controls.ExpandControl 2,832ExpandControl2,832 flare.vis.controls.DragControl 2,649DragControl2,649 flare.vis.controls.AnchorControl 2,138AnchorControl2,138 flare.vis.controls.Control 1,353Control1,353 flare.vis.controls.IControl 763IControl763 flare.vis.legend.Legend 20,859Legend20,859 flare.vis.legend.LegendRange 10,530LegendRange10,530 flare.vis.legend.LegendItem 4,614LegendItem4,614 flare.vis.axis.Axis 24,593Axis24,593 flare.vis.axis.CartesianAxes 6,703CartesianAxes6,703 flare.vis.axis.Axes 1,302Axes1,302 flare.vis.axis.AxisGridLine 652AxisGridLine652 flare.vis.axis.AxisLabel 636AxisLabel636 flare.vis.Visualization 16,540Visualization16,540 flare.vis.events.DataEvent 2,313DataEvent2,313 flare.vis.events.SelectionEvent 1,880SelectionEvent1,880 flare.vis.events.TooltipEvent 1,701TooltipEvent1,701 flare.vis.events.VisualizationEvent 1,117VisualizationEvent1,117 flare.util.Strings 22,026Strings22,026 flare.util.Shapes 19,118Shapes19,118 flare.util.Maths 17,705Maths17,705 flare.util.Displays 12,555Displays12,555 flare.util.palette.ColorPalette 6,367ColorPalette6,367 flare.util.palette.SizePalette 2,291SizePalette2,291 flare.util.palette.ShapePalette 2,059ShapePalette2,059 flare.util.palette.Palette 1,229Palette1,229 flare.util.Geometry 10,993Geometry10,993 flare.util.heap.FibonacciHeap 9,354FibonacciHeap9,354 flare.util.heap.HeapNode 1,233HeapNode1,233 flare.util.Colors 10,001Colors10,001 flare.util.math.SparseMatrix 3,366SparseMatrix3,366 flare.util.math.DenseMatrix 3,165DenseMatrix3,165 flare.util.math.IMatrix 2,815IMatrix2,815 flare.util.Arrays 8,258Arrays8,258 flare.util.Dates 8,217Dates8,217 flare.util.Sort 6,887Sort6,887 flare.util.Stats 6,557Stats6,557 flare.util.Property 5,559Property5,559 flare.util.Filter 2,324Filter2,324 flare.util.Orientation 1,486Orientation1,486 flare.util.IValueProxy 874IValueProxy874 flare.util.IPredicate 383IPredicate383 flare.util.IEvaluable 335IEvaluable335 flare.animate.interpolate.Interpolator 8,746Interpolator8,746 flare.animate.interpolate.MatrixInterpolator 2,202MatrixInterpolator2,202 flare.animate.interpolate.ColorInterpolator 2,047ColorInterpolator2,047 flare.animate.interpolate.RectangleInterpolator 2,042RectangleInterpolator2,042 flare.animate.interpolate.ArrayInterpolator 1,983ArrayInterpolator1,983 flare.animate.interpolate.PointInterpolator 1,675PointInterpolator1,675 flare.animate.interpolate.ObjectInterpolator 1,629ObjectInterpolator1,629 flare.animate.interpolate.NumberInterpolator 1,382NumberInterpolator1,382 flare.animate.interpolate.DateInterpolator 1,375DateInterpolator1,375 flare.animate.Transitioner 19,975Transitioner19,975 flare.animate.Easing 17,010Easing17,010 flare.animate.Transition 9,201Transition9,201 flare.animate.Tween 6,006Tween6,006 flare.animate.FunctionSequence 5,842FunctionSequence5,842 flare.animate.Scheduler 5,593Scheduler5,593 flare.animate.Sequence 5,534Sequence5,534 flare.animate.Parallel 5,176Parallel5,176 flare.animate.TransitionEvent 1,116TransitionEvent1,116 flare.animate.ISchedulable 1,041ISchedulable1,041 flare.animate.Pause 449Pause449 flare.query.methods.range 772range772 flare.query.methods.iff 748iff748 flare.query.methods.gte 625gte625 flare.query.methods.lte 619lte619 flare.query.methods.gt 603gt603 flare.query.methods.mul 603mul603 flare.query.methods.sub 600sub600 flare.query.methods.neq 599neq599 flare.query.methods.lt 597lt597 flare.query.methods.div 595div595 flare.query.methods.eq 594eq594 flare.query.methods.add 593add593 flare.query.methods.mod 591mod591 flare.query.methods.isa 461isa461 flare.query.methods.fn 460fn460 flare.query.methods.not 386not386 flare.query.methods.stddev 363stddev363 flare.query.methods.xor 354xor354 flare.query.methods.variance 335variance335 flare.query.methods.and 330and330 flare.query.methods.or 323or323 flare.query.methods.orderby 307orderby307 flare.query.methods.update 307update307 flare.query.methods.where 299where299 flare.query.methods.select 296select296 flare.query.methods.distinct 292distinct292 flare.query.methods.average 287average287 flare.query.methods.max 283max283 flare.query.methods.min 283min283 flare.query.methods.sum 280sum280 flare.query.methods.count 277count277 flare.query.methods._ 264_264 flare.query.Query 13,896Query13,896 flare.query.Expression 5,130Expression5,130 flare.query.Comparison 5,103Comparison5,103 flare.query.DateUtil 4,141DateUtil4,141 flare.query.StringUtil 4,130StringUtil4,130 flare.query.Arithmetic 3,891Arithmetic3,891 flare.query.Match 3,748Match3,748 flare.query.CompositeExpression 3,677CompositeExpression3,677 flare.query.ExpressionIterator 3,617ExpressionIterator3,617 flare.query.Fn 3,240Fn3,240 flare.query.BinaryExpression 2,893BinaryExpression2,893 flare.query.If 2,732If2,732 flare.query.IsA 2,039IsA2,039 flare.query.Variance 1,876Variance1,876 flare.query.AggregateExpression 1,616AggregateExpression1,616 flare.query.Range 1,594Range1,594 flare.query.Not 1,554Not1,554 flare.query.Literal 1,214Literal1,214 flare.query.Variable 1,124Variable1,124 flare.query.Xor 1,101Xor1,101 flare.query.And 1,027And1,027 flare.query.Or 970Or970 flare.query.Distinct 933Distinct933 flare.query.Average 891Average891 flare.query.Maximum 843Maximum843 flare.query.Minimum 843Minimum843 flare.query.Sum 791Sum791 flare.query.Count 781Count781 flare.analytics.graph.MaxFlowMinCut 7,840MaxFlowMinCut7,840 flare.analytics.graph.ShortestPaths 5,914ShortestPaths5,914 flare.analytics.graph.LinkDistance 5,731LinkDistance5,731 flare.analytics.graph.BetweennessCentrality 3,534BetweennessCentrality3,534 flare.analytics.graph.SpanningTree 3,416SpanningTree3,416 flare.analytics.cluster.HierarchicalCluster 6,714HierarchicalCluster6,714 flare.analytics.cluster.AgglomerativeCluster 3,938AgglomerativeCluster3,938 flare.analytics.cluster.CommunityStructure 3,812CommunityStructure3,812 flare.analytics.cluster.MergeEdge 743MergeEdge743 flare.analytics.optimization.AspectRatioBanker 7,074AspectRatioBanker7,074 flare.scale.TimeScale 5,833TimeScale5,833 flare.scale.QuantitativeScale 4,839QuantitativeScale4,839 flare.scale.Scale 4,268Scale4,268 flare.scale.OrdinalScale 3,770OrdinalScale3,770 flare.scale.LogScale 3,151LogScale3,151 flare.scale.QuantileScale 2,435QuantileScale2,435 flare.scale.IScaleMap 2,105IScaleMap2,105 flare.scale.ScaleType 1,821ScaleType1,821 flare.scale.RootScale 1,756RootScale1,756 flare.scale.LinearScale 1,316LinearScale1,316 flare.data.converters.GraphMLConverter 9,800GraphMLConverter9,800 flare.data.converters.DelimitedTextConverter 4,294DelimitedTextConverter4,294 flare.data.converters.JSONConverter 2,220JSONConverter2,220 flare.data.converters.IDataConverter 1,314IDataConverter1,314 flare.data.converters.Converters 721Converters721 flare.data.DataSource 3,331DataSource3,331 flare.data.DataUtil 3,322DataUtil3,322 flare.data.DataSchema 2,165DataSchema2,165 flare.data.DataField 1,759DataField1,759 flare.data.DataTable 772DataTable772 flare.data.DataSet 586DataSet586 flare.physics.NBodyForce 10,498NBodyForce10,498 flare.physics.Simulation 9,983Simulation9,983 flare.physics.Particle 2,822Particle2,822 flare.physics.Spring 2,213Spring2,213 flare.physics.SpringForce 1,681SpringForce1,681 flare.physics.GravityForce 1,336GravityForce1,336 flare.physics.DragForce 1,082DragForce1,082 flare.physics.IForce 319IForce319 flare.display.TextSprite 10,066TextSprite10,066 flare.display.DirtySprite 8,833DirtySprite8,833 flare.display.RectSprite 3,623RectSprite3,623 flare.display.LineSprite 1,732LineSprite1,732 flare.flex.FlareVis 4,116FlareVis4,116

Original Plot | Svelte REPL | Github

Code

<!-- Treemap.svelte -->
<script>
  import * as d3 from "d3";
  import Swatches from "./Swatches.svelte";

  // Receive plot data as prop.
  export let data;

  // Specify the chart’s dimensions.
  const width = 1154;
  const height = 1154;

  // Specify the color scale.
  const color = d3.scaleOrdinal(
    data.children.map((d) => d.name),
    d3.schemeTableau10,
  );

  // Specify formatting function.
  const format = d3.format(",d");

  // Specify initial tiling method.
  let tile = d3.treemapBinary;

  // Compute the layout.
  $: root = d3
    .treemap()
    .tile(tile) // e.g., d3.treemapSquarify
    .size([width, height])
    .padding(1)
    .round(true)(
    d3
      .hierarchy(data)
      .sum((d) => d.value)
      .sort((a, b) => b.value - a.value),
  );

  // Helper function to recursively find the parent of a given leaf at depth 1.
  function getFirstDepthParent(leaf) {
    return leaf.depth > 1 ? getFirstDepthParent(leaf.parent) : leaf;
  }
</script>

<!-- Tiling method selection menu -->
<label>
  Tiling method
  <select bind:value={tile} style="margin-bottom: 16px; color: #374151;">
    <option value={d3.treemapBinary} selected>binary</option>
    <option value={d3.treemapSquarify}>squarify</option>
    <option value={d3.treemapSliceDice}>slice-dice</option>
    <option value={d3.treemapSlice}>slice</option>
    <option value={d3.treemapDice}>dice</option>
  </select>
</label>

<!-- Legend -->
<Swatches {color} />

<svg
  {width}
  {height}
  viewBox="0 0 {width} {height}"
  style="max-width: 100%; height: auto;"
>
  {#each root.leaves() as leaf, leafIndex}
    <!-- Get nodes of current leaf -->
    {@const nodes = leaf.data.name
      .split(/(?=[A-Z][a-z])|\s+/g)
      .concat(format(leaf.value))}

    <!-- Add a cell for each leaf of the hierarchy -->
    <g transform="translate({leaf.x0},{leaf.y0})">
      <!-- Add a tooltip -->
      <title>
        {`${leaf
          .ancestors()
          .reverse()
          .map((leaf) => leaf.data.name)
          .join(".")}\n${format(leaf.value)}`}
      </title>

      <!-- Add a color rectangle -->
      <rect
        id="rect-{leafIndex}"
        fill={color(getFirstDepthParent(leaf).data.name)}
        fill-opacity={0.8}
        width={leaf.x1 - leaf.x0}
        height={leaf.y1 - leaf.y0}
      />

      <!-- Add a clipPath to ensure text does not overflow -->
      <clipPath id="clip-{leafIndex}">
        <use href="#rect-{leafIndex}" />
      </clipPath>

      <!-- Add multiline text. The last line shows the value and has a specific formatting. -->
      <text clip-path="url(#clip-{leafIndex})">
        {#each nodes as node, nodeIndex}
          <tspan
            x="3"
            y="{(nodeIndex === nodes.length - 1) * 0.3 +
              1.1 +
              nodeIndex * 0.9}em"
            fill-opacity={nodeIndex === nodes.length - 1 ? 0.7 : null}
          >
            {node}
          </tspan>
        {/each}
      </text>
    </g>
  {/each}
</svg>
<!-- Swatches.svelte -->
<script>
  export let color;
  export let swatchWidth = 15;
  export let swatchHeight = 15;
  export let marginLeft = 0;
</script>

<div
  style="
    display: flex; 
    align-items: center; 
    min-height: 33px; 
    margin-left: {marginLeft}px; 
    font: 10px sans-serif;
  "
>
  {#each color.domain() as category}
    <span
      style="
        display: inline-flex;
        align-items: center; 
        margin-right: 1em; 
        --color: {color(category)};
        --width: {swatchWidth}px;
        --height: {swatchHeight}px;
      "
    >
      {category}
    </span>
  {/each}
</div>

<style>
  span::before {
    content: "";
    width: var(--width);
    height: var(--height);
    margin-right: 0.5em;
    background: var(--color);
  }
</style>