Qlik Community

Qlik Design Blog

All about product and Qlik solutions: scripting, data modeling, visual design, extensions, best practices, etc.

Announcements
QlikWorld, June 24-25, 2020. Free virtual event for DI and DA gurus. Register Now
Employee
Employee

Let's check out how we can build an animated rank chart with picasso.js! You can check out an example in the History of the Fortune 500 app that we built for Fortune at https://qlik.fortune.com/

In this post I'm going to review the picasso.js settings for building an animated rank chart. For the chart to be animated, you'll also need to implement something like I covered in my last blog post about animating picasso.js at https://community.qlik.com/t5/Qlik-Design-Blog/Animations-with-picasso-js/ba-p/1686543.  

Data

For this example I'm going to use dimensions and measures like we were using the q picasso plugin. You'll want to have 1 dimension and 2 measures. The first measure should be the value you are ranking, and the second measure should be  a rank expression.

Settings

The general idea here is that we need to calculate the position of the bars along the y-axis such that as we interpolate the change in the rank the position will change. We also use a labels component in place of an axis component for the y axis labels, since the labels component will attach to the bars and move along with the bars, as opposed to the y-axis, which would be a band scale axis that has discrete positions. Here's what the settings are, with some comments to explain.

 

 

{
  scales: { 
    y: { 
      data: { 
        extract: { 
          field: 'qDimensionInfo/0', 
          props: { 
            rank: { field: 'qMeasureInfo/1' } 
          } 
        },
        sort: (a, b) => a.rank.value - b.rank.value, // sort values in scale (in case we use brushing or something
      },
      padding: 0.2,
    }, 
    x: { 
      data: { field: 'qMeasureInfo/0' }, 
      include: [0], 
      expand: 0.5, // you need to use expand so the labels fit, may need to adjust based on length of your labels
    },
  },
  components: [
    // this is the main box component
    {
      type: 'box',
      key: 'bars',
      displayOrder: 1,
      data: { 
        extract: { 
          field: 'qDimensionInfo/0', 
          props: { 
            start: 0, 
            end: { field: 'qMeasureInfo/0' }, 
            rank: { field: 'qMeasureInfo/1' } 
          } 
        } 
      },
      settings: {
        major: { 
          scale: 'y',
          // this is what positions the bars on the y-axis
          // the reason we calculate the position manually is so that as we interpolate the change in rank it will animate
          fn: (d) => (d.datum.rank.value * d.scale.step()) - (d.scale.paddingOuter() * d.scale.bandwidth()) - (0.5 * d.scale.bandwidth()), 
        },
        minor: { scale: 'x', ref: 'end' },
        orientation: 'horizontal',
      },
    },
    // we use these labels instead of an axis component for animation reasons.
    // we can attach the labels to the bars so they animate along with the position of the bars
    {
      type: 'labels',
      displayOrder: 2,
      settings: {
        sources: [{
          component: 'bars',
          selector: 'rect',
          strategy: {
            type: 'bar',
            settings: {
              align: 0.5,
              justify: 0,
              fontSize: 14,
              direction: 'left',
              labels: [{ 
                placements: [{ position: 'outside', fill: '#666' }],
                label: (node) => node.data.label, 
              }],
              padding: {
                top: 0, right: 8, bottom: 0, left: 0,
              },
            },
          },
        }],
      },
    },
    // these are the value labels
    {
      type: 'labels',
      displayOrder: 2,
      settings: {
        sources: [{
          component: 'bars',
          selector: 'rect',
          strategy: {
            type: 'bar',
            settings: {
              align: 0.5,
              justify: 0,
              fontSize: 11,
              direction: 'right',
              labels: [{ 
                placements: [{ position: 'outside', fill: '#666' }],
                label: (node) => node.data.end.value, 
              }],
              padding: {
                top: 0, right: 0, bottom: 0, left: 6,
              },
            },
          },
        }],
      },
    }, 
  ],
}

 

 

 

Now you need to do is interpolate the change in the rank value when updating the chart, and you'll have an animating rank chart. You can also check out these settings at https://observablehq.com/@fkabinoff/rank-chart-that-can-be-animated-by-interpolating-rank-chang.  

1 Comment
Partner
Partner

Great ! this website is beautifull.

136 Views
Labels