Skip to content

Script Examples

Animating UI Elements

Download ezUI File

In this example, we created a dynamic graphic that represents the results of an election. By changing the input data, the graphical representation of the election results is automatically updated. We also utilized interactive components to control the display of the election results.

To do this, we determine if the user has adjusted the election data inputs and when the data changes, we retrieve the updated information and render it on the graphic. We also ensure that the data is validated and clamped within acceptable ranges before updating the graphic elements.

Locator

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
let drag = false;
const realSize = 200;
function onPointerDown(e) {
  drag = true;
  area.setPointerCapture(e.pointerId);
}

/* Define the IParty interface with optional properties for button, 
progress, and label elements */
interface IParty {
  color: string;
  letter: string;
  button?: Button;
  progress?: Label;
  label?: Label;
}

// Initialize an array of parties with specific colors and letters
const parties: IParty[] = [
  { color: '#9e0142', letter: 'A' },
  { color: '#d53e4f', letter: 'B' },
  { color: '#f46d43', letter: 'C' },
  { color: '#fdae61', letter: 'D' },
  { color: '#fee08b', letter: 'E' },
  { color: '#e6f598', letter: 'F' },
  { color: '#abdda4', letter: 'G' },
  { color: '#66c2a5', letter: 'H' },
  { color: '#3288bd', letter: 'I' },
  { color: '#5e4fa2', letter: 'J' },
];

// Define a constant for the margin between elements
const MARGIN = 5;

// Variable to keep track of initialization state
let initialized = false;

// Function to initialize party elements
function initialize() {
  // Return if already initialized
  if (initialized)
    return;

  // Set initialized to true
  initialized = true;

  /* Loop through each party and create button,
   progress, and label elements */
  for (let i = 0; i < parties.length; i++) {
    const party = parties[i];

    // Clone button template and set properties
    const button = cloneElement(partyTemplate, { left: MARGIN, text: party.letter });
    button.style.backgroundColor = party.color;
    party.button = button;

    // Clone progress template and set properties
    const progress = cloneElement(progressTemplate);
    progress.width = 0;
    progress.style.backgroundColor = party.color;
    party.progress = progress;

    // Clone label template
    const label = cloneElement(labelTemplate);
    party.label = label;
  }
}

// Function to handle the simulation onClick event
simulate.onClick = () => {
  // Initialize party elements if not already initialized
  initialize();

  // Variables to store total value and individual party values
  let sum = 0;
  const values: Record<string, number> = {};

  // Generate random values for each party and calculate total sum
  for (const party of parties) {
    const value = Math.random() * 100;
    sum += value;
    values[party.letter] = value;
  }

  // Find the maximum value among the parties
  const max = Math.max(...Object.values(values));

  // Sort parties based on their values in descending order
  const sorted = _.orderBy(parties, party => values[party.letter], 'desc');

  // Variable to track the top position for each party element
  let top = MARGIN;

  // Loop through each sorted party and update their elements
  for (const party of sorted) {
    const value = values[party.letter];
    const progress = value / max;
    const percent = 100 * value / sum;

    // Update button position
    party.button.top = top;

    // Update progress bar position and width
    party.progress.top = top + progressTemplate.top - partyTemplate.top;
    party.progress.left = MARGIN + progressTemplate.left - partyTemplate.left;
    party.progress.width = progress * progressTemplate.width;

    // Update label position and text
    party.label.top = top + labelTemplate.top - partyTemplate.top;
    party.label.left = MARGIN + labelTemplate.left - partyTemplate.left;
    party.label.text = `${percent.toFixed(1)} %`;

    // Increment top position for the next party element
    top += party.button.height + MARGIN;
  }
}


// Initial Read
function readData() {
  updatePosition('x', vtxPosition.value.x);
  updatePosition('y', vtxPosition.value.y);
}

readData();