block by micahstubbs 0e2b63921f5642f0f65f51e27cccd02f

spinner with d3-component | es2015

Full Screen

an es2015 iteration on the block Spinner with d3-component from @currankelleher


This example demonstrates usage of d3-component to create a spinner component, and render it conditionally while something is loading. After loading finishes, the spinner goes away and is replaced by another component.

How often have you seen a data visualization show nothing but a blank screen while the data is loading? Showing a spinner with D3 and hiding it after data is loaded is not as easy as it seems. Here’s a solution for doing this, feel free to use it in your projects!

This demonstrates the following patterns supported by d3-component:

Built with blockbuilder.org

forked from curran‘s block: Posts with D3 Component

forked from curran‘s block: Spinny Loading Icon

index.html

<!DOCTYPE html>
<head>
  <meta charset='utf-8'>
  <script src='https://unpkg.com/d3@4'></script>
  <script src='https://unpkg.com/d3-component@3'></script>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.23.1/babel.min.js'></script>
</head>
<body>
  <svg width='960' height='500'></svg>
  <script src='vis.js'></script>
</body>

lebab.sh

# safe
lebab --replace vis.js --transform arrow
lebab --replace vis.js --transform for-of
lebab --replace vis.js --transform for-each
lebab --replace vis.js --transform arg-rest
lebab --replace vis.js --transform arg-spread
lebab --replace vis.js --transform obj-method
lebab --replace vis.js --transform obj-shorthand
lebab --replace vis.js --transform multi-var
# unsafe
lebab --replace vis.js --transform let
lebab --replace vis.js --transform template

preview.xcf

gimp xcf file�xB�B�gimp-image-grid(style solid)
(fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000))
(bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000))
(xspacing 10.000000)
(yspacing 10.000000)
(spacing-unit inches)
(xoffset 0.000000)
(yoffset 0.000000)
(offset-unit inches)
��x)Screen Shot 2017-03-18 at 2.09.46 PM.png�	

\�xx���x���&�)�,��2���yxx�q��1���	�o�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r��,��2���yxx�q��1���	�o�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r��,��2���yxx�q��1���	�o�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r������������9���6D��7���*$''#C��6���''�&5��*�����������&''�%6��)���709������5!&%"U������"���&#&!0�����V!(k�����O�!����''�������������� �"���''%$�����p�"���h!w�����z�#��쭆������1�$�������������
��������!���������	���s,A��!��|	�y�	���&#3�� ���	���	��H&'&0�� ���	���	��t!$#7�� ���	���	���W?F��!���	���
�����"���	���1���	���1���	���1���	���1���	���1���	���1���	���-����������9���6D��7���*$''#C��6���''�&5��*�����������&''�%6��)���709������5!&%"U������"���&#&!0�����V!(k�����O�!����''�������������� �"���''%$�����p�"���h!w�����z�#��쭆������1�$�������������
��������!���������	���s,A��!��|	�y�	���&#3�� ���	���	��H&'&0�� ���	���	��t!$#7�� ���	���	���W?F��!���	���
�����"���	���1���	���1���	���1���	���1���	���1���	���1���	���-����������9���6D��7���*$''#C��6���''�&5��*�����������&''�%6��)���709������5!&%"U������"���&#&!0�����V!(k�����O�!����''�������������� �"���''%$�����p�"���h!w�����z�#��쭆������1�$�������������
��������!���������	���s,A��!��|	�y�	���&#3�� ���	���	��H&'&0�� ���	���	��t!$#7�� ���	���	���W?F��!���	���
�����"���	���1���	���1���	���1���	���1���	���1���	���1���	���-��	�������;��cHIb���8�#�G��8��&''����7�'� u��7�'����7��$''&!��8��,""'���8��ۨ������������8���چap���7���. "! p��5���9%''�(��5���0&''�O�5���/''�&?�5���0&''�a�5���]"$&&"4��6���g4!(M��8��嬔���3�	�������;��cHIb���8�#�G��8��&''����7�'� u��7�'����7��$''&!��8��,""'���8��ۨ������������8���چap���7���. "! p��5���9%''�(��5���0&''�O�5���/''�&?�5���0&''�a�5���]"$&&"4��6���g4!(M��8��嬔���3�	�������;��cHIb���8�#�G��8��&''����7�'� u��7�'����7��$''&!��8��,""'���8��ۨ������������8���چap���7���. "! p��5���9%''�(��5���0&''�O�5���/''�&?�5���0&''�a�5���]"$&&"4��6���g4!(M��8��嬔���3��	��	��	��	��+����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1��lj��������+����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1��lj��������+����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1����r�1��lj������������	���1���	���	���q_��"���	���	��\($?��!���	������$'&-��!���	���	��Q #-��!���	���	���xb��"���	���
������"���	���1���	��������	�������ϥ��������	�������L!!W����������	���
����'"''� 8�����֞����	���
���C"''�`�����(����	�������''�&��
����%'����	�������''����������������E!''����	������| ''������K&%G������&''����	�������''�����`"&&"Y�����''���	���
���*$''�!A���|'&''&�p����*%''����	���
���� #''�!'����=%''�%:����e''����	������4:�����7&''�&5�����E"����	��������km�������7&''�&5������uJ����	�������������;%''�%8����������	�����q&&''�&g�
���	������T$''$ N��
���	�����݅95~�����	���������������	���1���	���1���	���1���	���1���	���1���	���1������1��Ĉ����������	���1���	���	���q_��"���	���	��\($?��!���	������$'&-��!���	���	��Q #-��!���	���	���xb��"���	���
������"���	���1���	��������	�������ϥ��������	�������L!!W����������	���
����'"''� 8�����֞����	���
���C"''�`�����(����	�������''�&��
����%'����	�������''����������������E!''����	������| ''������K&%G������&''����	�������''�����`"&&"Y�����''���	���
���*$''�!A���|'&''&�p����*%''����	���
���� #''�!'����=%''�%:����e''����	������4:�����7&''�&5�����E"����	��������km�������7&''�&5������uJ����	�������������;%''�%8����������	�����q&&''�&g�
���	������T$''$ N��
���	�����݅95~�����	���������������	���1���	���1���	���1���	���1���	���1���	���1������1��Ĉ����������	���1���	���	���q_��"���	���	��\($?��!���	������$'&-��!���	���	��Q #-��!���	���	���xb��"���	���
������"���	���1���	��������	�������ϥ��������	�������L!!W����������	���
����'"''� 8�����֞����	���
���C"''�`�����(����	�������''�&��
����%'����	�������''����������������E!''����	������| ''������K&%G������&''����	�������''�����`"&&"Y�����''���	���
���*$''�!A���|'&''&�p����*%''����	���
���� #''�!'����=%''�%:����e''����	������4:�����7&''�&5�����E"����	��������km�������7&''�&5������uJ����	�������������;%''�%8����������	�����q&&''�&g�
���	������T$''$ N��
���	�����݅95~�����	���������������	���1���	���1���	���1���	���1���	���1���	���1������1��Ĉ���������������9���P?=H|��6���7$%%$,k�5���D%''�&1��4���4&''�*w�4���2&''�)g�4���7&''�,��5��Q''�4��5���A(''(.��7���NGs��2�����<�������:�� (���9�'�%���8�'�#=��8�'���8�'����7�'�&"��8�'�g��8��#"I���8��=Lw���9���������������9���P?=H|��6���7$%%$,k�5���D%''�&1��4���4&''�*w�4���2&''�)g�4���7&''�,��5��Q''�4��5���A(''(.��7���NGs��2�����<�������:�� (���9�'�%���8�'�#=��8�'���8�'����7�'�&"��8�'�g��8��#"I���8��=Lw���9���������������9���P?=H|��6���7$%%$,k�5���D%''�&1��4���4&''�*w�4���2&''�)g�4���7&''�,��5��Q''�4��5���A(''(.��7���NGs��2�����<�������:�� (���9�'�%���8�'�#=��8�'���8�'����7�'�&"��8�'�g��8��#"I���8��=Lw���9���������P�P�P�P�s<9

vis.js

/* global d3 */
    
// This function simulates fetching with a 2 second delay.
// You can replace stuff here with e.g. d3.csv.
function fetchData(callback) {
  setTimeout(() => {
    callback([6, 5, 4, 3, 2, 1]);
  }, 2000);
}

// This function visualizes the data.
function visualize(selection, data) {
  const rects = selection
    .selectAll('rect')
    .data(data);
  rects.exit().remove();
  rects
    .enter().append('rect')
      .attr('x', (d, i) => (i * 100) + 182)
      .attr('y', d => 400)
      .attr('width', 50)
      .attr('height', 0)
    .merge(rects)
    .transition().duration(1000).ease(d3.easeBounce)
      .delay((d, i) => i * 500)
      .attr('y', d => 400 - (d * 50))
      .attr('height', d => d * 50);
}

// The stuff below uses d3-component to display a spinner
// while the data loads, then render the visualization after loading.
  
// This stateless component renders a static "wheel" made of circles,
// and rotates it depending on the value of props.angle.
const wheel = d3.component('g')
  .create(function (selection) {
    const minRadius = 4;
    const maxRadius = 10;
    const numDots = 10;
    const wheelRadius = 40;
    const rotation = 0;
    const rotationIncrement = 3;

    const radius = d3.scaleLinear()
    .domain([0, numDots - 1])
    .range([maxRadius, minRadius]);

    const angle = d3.scaleLinear()
    .domain([0, numDots])
    .range([0, Math.PI * 2]);

    selection
      .selectAll('circle').data(d3.range(numDots))
      .enter().append('circle')
        .attr('cx', d => Math.sin(angle(d)) * wheelRadius)
        .attr('cy', d => Math.cos(angle(d)) * wheelRadius)
        .attr('r', radius);
  })
  .render(function (selection, d) {
    selection.attr('transform', `rotate(${d})`);
  });

// This component with a local timer makes the wheel spin.
const spinner = ((() => {
  const timer = d3.local();
  return d3.component('g')
    .create(function (selection, d) {
      timer.set(selection.node(), d3.timer((elapsed) => {
        selection.call(wheel, elapsed * d.speed);
      }));
    })
    .render(function (selection, d) {
      selection.attr('transform', `translate(${d.x},${d.y})`);
    })
    .destroy(function (selection, d) {
      timer.get(selection.node()).stop();
      return selection
        .attr('fill-opacity', 1)
        .transition().duration(3000)
          .attr('transform', `translate(${d.x},${d.y}) scale(10)`)
          .attr('fill-opacity', 0);
    });
})());

// This component displays the visualization.
const visualization = d3.component('g')
  .render(function (selection, d) {
    selection.call(visualize, d.data);
  });

// This component manages an svg element, and
// either displays a spinner or text,
// depending on the value of the `loading` state.
const app = d3.component('g')
  .render(function (selection, d) {
    selection
      .call(spinner, !d.loading ? [] : {
        x: d.width / 2,
        y: d.height / 2,
        speed: 0.2,
      })
      .call(visualization, d.loading ? [] : d);
  });

// Kick off the app.
function main() {
  const svg = d3.select('svg');
  const width = svg.attr('width');
  const height = svg.attr('height');

  // Initialize the app to be "loading".
  svg.call(app, {
    width,
    height,
    loading: true,
  });

  // Invoke the data fetching logic.
  fetchData((data) => {
    svg.call(app, {
      width,
      height,
      loading: false,
      data,
    });
  });
}
main();