Animate-graph Usage

Animate Graph

  • Create clear, step-by-step visualizations to enhance your teaching and explanations in Revealjs.
  • It builds on:
    • d3 to generate and animate graphs,
    • Katex to print math objects. x=y.
  • This is generated to be used with Quarto within Rstudio.
    • Although, you may use it outside of Quarto too, like a regular plug in.
  • No coding required. All you need to know is how to add divs and spans to your Quarto document.
  • The aim is to generate presentations with animated graphs.
    • To make the lecture slides more interactive.
    • It is not to provide a data visualization package.
    • For example: revealing a point, shifting a curve, or shading an area.

Animate Graph

  • All you need to know is how to add divs and spans in your Quarto document.
  • The package automatically converts these elements into SVG elements using D3.js, enabling smooth transitions and animations.
  • It converts the below code to graph on the right:
:::{.animategraph        }

[]{.addElement type="line" var-x="quantity" var-y="demand" id="demand" }
[]{.addElement type="line" var-x="quantity" var-y="supply" }
[]{.addElement type="point" var-x="quantity" var-y="demand; supply" lines="true" }
[]{.addElement type="tick" var-x="2.5" var-y="2.5" label-y="$p^\\star$" label-x="$q^{\\star}$" id="equilibrium" }
[]{.move id="demand" var-x="quantity" var-y="demand_right" index=0 clone="true" }
[]{.addElement type="line" var-x="quantity" var-y="supply" }

:::

Generating a Graph

Generating a Graph

  • Generating a graph is simple:
    • Just create a div with the class animategraph.
  • This generates a graph using predefined data.
:::{.animategraph  }
:::
  • Generates an empty graph.

Size of a Graph

  • The graph takes the size of its parent element.
    • Default dimensions are 100% with minimum 100px.
  • The size can be specified using the width and height styles of the div.
:::{.animategraph style="width:300px; height:300px;  margin:auto;"  }
:::
  • Or specify the size of the parent element.
:::{style="width:300px; height:300px; margin:auto;"}

:::{.animategraph  }
:::

:::

Attaching Data

  • Data can be attached to the graph using the df attribute.
    • Data must be an array of JS objects. [{"x":1, "y":1}, {"x":2, "y":5}].
    • df-label can be added to be able to call the data across different graphs.
  • To specify variable for x and y-axis, specify var-x and var-y attributes.
:::{.animategraph var-x="x" var-y="y" df-label="df" df='[{"x":0,"y":0},{"x":1,"y":1},{"x":2,"y":4},{"x":3,"y":9},{"x":4,"y":16},{"x":5,"y":25},{"x":6,"y":36},{"x":7,"y":49},{"x":8,"y":64},{"x":9,"y":81},{"x":10,"y":100}]'  }

:::
  • In R, you may use jsonlite::toJSON to convert data.frame to the desired format.
    • Using inline code will be a more efficient way.
    • You need to enclose it with a single quote '.
:::{.animategraph var-x="x" var-y="y" df-label="df" df='`r jsonlite::toJSON(df)`'   }

:::

Elements of a Graph

An Element of a Graph

  • There are five types of elements:
    1. line: plots y=f(x).
    2. point: draws a circle at (x,y) coordinate.
    3. area: fills the area between y_0 and y_1.
    4. text: adds a text at (x,y) coordinate.
    5. tick: add a label on an axis at some value.
  • All parameters of an element can be changed afterward.
    • An element can be moved or changed in appearance.

Adding an Element

  • All elements of a graph must defined within the div.
  • To add an element, define a span with:
    • Class names animategraph and addElement.
    • type attribute to specify the type of the element.
    • var-* to specify variables. * may be x, y, y1 etc.
    • Other styling options as attributes or style (more on this later).
  • Possible types ares:
    • line: need to specify var-x and var-y as variable names.
    • point: need to specify var-x and var-y as coordinates.
    • area: We need to specify var-x as a single variable name and var-y as a semicolon separated by two variable names.
    • text: need to specify var-x and var-y as coordinates.
    • tick: need to specify var-* for a set of values for position and label-* for a set of labels to print.
      • * can be either x or y, indicating the axis.

Drawing a Line

  • To draw the plot of y=f(x):
    1. Define the data.frame in R.
    2. Generate a graph and attach df to it.
    3. Generate a span with:
      • .addElement,
      • type="line"
      • var-x="x" and var-y="y" (or name of other variables).


``{r}
df <- data.frame(x=0:10, y=(0:10)^2)
``

:::{.animategraph  df='`r jsonlite::toJSON(df)`'  }

[]{ .addElement type="line" var-x="x" var-y="y"}

:::

Drawing a Line

  • Instead of using the attached data,
  • You may assign a data frame for the individual line.
    • Set the df attribute to an array of JS objects.
    • Again you can use jsonlite::toJSON(df) function in R.
  • This is useful if you want to draw a straight line.


``{r}
df <- data.frame(x=0:10, y=(0:10)^2, yy =0:10, z=0, q=10:0)
``

:::{.animategraph  df='`r jsonlite::toJSON(df)`'  }

[]{ .addElement type="line" var-x="x" var-y="y" }
[]{ .addElement type="line" var-x="x" var-y="y" df='[{"x":0, "y":0}, {"x":5,"y":10}]' }

:::

Adding a Point

  • To add a point to an existing graph:
    1. generate a span with:
      • .addElement,
      • type="point"
      • var-x="5" and var-y="5" (or any other number).
  • You may use inline code to assign values.

:::{.animategraph  df='`r jsonlite::toJSON(df)`'  }

[]{ .addElement type="point" var-x="5" var-y="5"}
[]{ .addElement type="point" var-x="`r df$x[2]`" var-y="`r df$y[2]`"}

:::

Adding a Point at an Intersection

  • To add a point at an intersection of two curves:
    • define a span for a regular point element.
    • include the name of the variable for x axis to var-x,
    • include two variable names for var-y separated by a semicolon.
  • Then, the code
    • finds the first y0(x^\star)=y1(x^\star) in the domain,
    • adds a point at y0(x^\star).

:::{.animategraph  df='`r jsonlite::toJSON(df)`'  }

[]{ .addElement type="line" var-x="x" var-y="y"}
[]{ .addElement type="line" var-x="x" var-y="q"}
[]{ .addElement type="point" var-x="x" var-y="y; q" }

:::

Projections of a Point

  • Projection of a point on x and y axis can be plotted by
    • setting the lines attribute of a point to "true".
  • Right now, there is no way to alter their position or style.
    • But they automatically follow the point.
  • Alternatively, you can manually draw projections individually.
    • Then adjust their styles.

:::{.animategraph  df='`r jsonlite::toJSON(df)`'   }

[]{ .addElement type="point" var-x="2" var-y="5" lines="true" id='point1'   }

:::

Fill an Area

  • To fill the area between two variables:
    1. generate a span with:
      • .addElement,
      • type="area"
      • var-x="x", var-y="y0; y1" (or name of other variables).
  • The code fills the area between y0 and y1 until the first intersection.

:::{.animategraph  df='`r jsonlite::toJSON(df)`'   }

[]{ .addElement type="area" var-x="x" var-y="y; yy" range-x="full" }

:::

Fill an Area

  • The range of the x-axis to be filled can be set using range-x.
  • range-x is either full or two values separated with a semicolon.
    1. full fills the entire range.
    2. The first element is the x coordinate.
      • Either a numerical value on the x-axis,
      • or intersection to indicate an intersection point.
        • You don’t need to calculate it; the code finds the first intersection.
    3. The second element is
      • Either a numerical value on the x-axis (default is 0).
        • The area between the first and second element is filled.
      • Or the side (left or right). The default is intersection; left.

:::{.animategraph  df='`r jsonlite::toJSON(df)`'  }

[]{ .addElement type="area" var-x="x" var-y="y; q" range-x='intersection; left' }
[]{ .addElement type="area" var-x="x" var-y="y; q"  range-x='6; 9' }
[]{ .addElement type="line" var-x="x" var-y="y"   }
[]{ .addElement type="line" var-x="x" var-y="q"  }

:::

Adding a Text

  • To add a text on the graph:
    1. generate a span with:
      • .addElement,
      • type="text"
      • var-x="number" var-y="number" (coordinates).
      • text="text to display".
  • text may contain math expressions (more on this later).
  • The style of the span is assigned to the style of the element.
    • style-type: value.
    • It must be semicolon (;) separated.
      • background-color: red; color:green;.

:::{.animategraph   }

[]{ .addElement type="text" var-x="1" var-y="2" text="with style" style="background-color:lightblue;color:red;"  }

:::

Ticks

  • To add a tick on an axis:
    1. generate a span with:
      • .addElement,
      • type="tick"
      • var-x="value on x axis", var-y="value on y axis".
      • label-x="label on x axis" and label-y="label on y axis".
  • var-* and label-* can be semicolon separated values.
    • Math expressions can be added as labels.
  • Style can be changed using the style attribute.

:::{.animategraph }

[]{ .addElement type="tick" var-y="10" var-x="1, 5" label-x="$\\delta$, P" label-y="$P$"  }
[]{ .addElement type="tick" var-y="2"  label-y="$\\alpha$" style="background-color:green; color:red;"   }

:::

Math Symbols

  • Math symbols can be used in title.
  • They are rendered using Katex.
    • Just enclose the math symbols with dollar signs $math expression$.
    • Use double slash \\ to use a Greek letter: $\\alpha$ print \alpha.
  • Any text input can contain math symbols.
    • Text,
    • tick,
    • title,
    • axis labels,
    • legend,
    • ticks.

:::{.animategraph  df='`r jsonlite::toJSON(df)`'   }

[]{ .addElement type="text" var-x="2" var-y="5" text="Optimal $\\alpha^\star$"   }

:::

Using a Predefined Data

  • Data can be used in all graphs.
    • Make sure that either the id or the df-label attribute is defined in the graph the data is attached to.
  • You can use the data in two ways:
    • Specify which data you want to use in the df-label attribute of the graph div.
    • Or similarly, specify it when generating an element span.

:::{.animategraph #data var-x="x" var-y="y" df='`r jsonlite::toJSON(df)`' df-label="data" style="height:40%;"    }

[]{ .addElement type="area" var-x="x" var-y="y; yy" range-x="full" }

:::

:::{.animategraph  var-x="x" var-y="y" df-label="data"  style="height:40%;"   }

[]{ .addElement type="line" var-x="x" var-y="y"  }

:::

Changing an Element

Id

  • To manipulate an element afterward, an id must be defined.
    • using either id='someString' or #someString.
  • id must be unique within a graph.
    • But it can be repeated in other graphs.
    • Copying and pasting a code is fine.

:::{.animategraph  df='`r jsonlite::toJSON(df)`'  }

[]{ .addElement id='line1' type="line" var-x="x" var-y="y" }
[]{ .addElement #line2 type="line" var-x="x" var-y="yy"  }

:::

Moving an Element

  • To move an object,
    1. define a span object with classes animategraph and move.
    2. specify the element you want to move by id.
    3. define new var-* parameters.
    4. specify the timing of the move by the index attribute.
      • index automatically adds fragment as a class and data-fragment-index=index.

:::{.animategraph  var-x="x" var-y="y" df-label="data"      }

[]{ .addElement type="line" var-x="x" var-y="y"  id="line1" }
[]{ .move id="line1" var-x="x" var-y="yy" index=1 }

[]{ .addElement type="point" var-x="5" var-y="25"  #point1 }
[]{ .move #point1  var-x="8" var-y="50" index=0 }

[]{ .addElement type="area" var-x="x" var-y0="z" var-y1="y" range-x="full"  id="area1" }
[]{ .move type="area" var-x="x" var-y0="z" var-y1="yy" range-x="full"  id="area1" index=2 }

:::

Moving an Element - Clone

  • It is possible to clone the initial element and move the clone.
  • To do this, set clone="true".

:::{.animategraph  var-x="x" var-y="y" df-label="data"      }

[]{ .addElement type="line" var-x="x" var-y="y"  id="line1" }
[]{ .move id="line1" var-x="x" var-y="yy" index=0 clone="true" }
[]{ .move id="line1" var-x="x" var-y="q" index=1 clone="true" }

[]{ .addElement type="point" var-x="5" var-y="25"  #point1 }
[]{ .move #point1  var-x="8" var-y="50" index=1 }

[]{ .addElement type="area" var-x="x" var-y0="z" var-y1="y"  id="area1" }
[]{ .move type="area" var-x="x" var-y0="z" var-y1="yy"  id="area1" index=3 }

:::

Index - In and Out

  • The visibility of an element can be changed in two ways:
    • The index attribute specifies the fragment it becomes visible.
    • The index-out attribute specifies the fragment to which it becomes hidden.
  • Combining index and index-out attributes, you may time fade-in and fade-out.

:::{.animategraph  var-x="x" var-y="y" df-label="data"      }

[]{ .addElement type="line" var-x="x" var-y="y"  id="line1" }
[]{ .addElement type="line" var-x="x" var-y="yy"  id="line2" index="0" index-out="1" }
[]{ .addElement type="text" var-x="2" var-y="20"  text="Hello!" index="1" index-out="2" }
[]{ .addElement type="point" var-x="5" var-y="25"  #point1 }

:::

Changing Style of an Element

  • The style of an element can be changed afterward.
  • To do this:
    1. Generate a span with classes animategraph and setAttribute.
    2. Specify the element you want to alter by id.
    3. Specify new attribute values.
    4. Specify the timing using index.

:::{.animategraph  df-label="data"    }

[]{ .addElement type="line" var-x="x" var-y="y" color="red" id="line1"  }
[]{ .setAttribute  width="10" id="line1"   index=0 }
[]{ .setAttribute  color="orange" id="line1"   index=1 }
:::

Graph Properties

Title of a Graph

  • A title can be added by setting the
    • title attribute of the graph div.
  • The class of the title is animategraph-title.
    • You may alter its style using CSS.

:::{.animategraph  df-label="data" title="A Graph"   }

[]{ .addElement type="line" var-x="x" var-y="y"}

:::

Axis Labels

  • To set the axis label,
    • specify the label-x and label-y attributes for x and y axes (respectively).
  • Again, the label can contain math symbols.

:::{.animategraph  df-label="data" label-x="x" label-y="$\\delta$"   title="For high $\\beta$"    }

[]{ .addElement type="line" var-x="x" var-y="y"}

:::

Legend

  • To add a legend, set the legend attribute of graph div to "true".
    The default of legend is "false".
  • The default label is the id of the line.
    • If it is not defined, then it will print No Label!.
  • To hide a single line from the legend
    • set its showlegend attribute to "false".
    • default is "true".
  • Legend is only available for the line type.

:::{.animategraph  df-label="data"  legend="true"   }

[]{ .addElement type="line" var-x="x" var-y="y" id="line1"  label="High" }
[]{ .addElement type="line" var-x="x" var-y="yy" id="Low"   }
[]{ .addElement type="line" var-x="x" var-y="q"  showlegend="false"  }

:::

Axis Range

  • Axis range can be set in two ways:
    • Specify the variable name for each axis. The domain of the variable becomes the range of the axis.
    • Specify range-x and range-y attributes.
      • These must be semicolon separated values.
:::{.animategraph range-x="0, 30" range-y="10, 50"  df-label="data"   title="For high $\\beta$"    }

:::

Default Dataset

econ Dataset

  • The default dataset is econ.
    • I am an economist, so I included supply and demand variables.
  • Available variables:
    • quantity, demand, supply,demandCurve,supplyCurve`,
    • *_left for left-shifted curves and *_right for righted shifted curves,
      • wheree * can be anything other than quantity.
  • Demand and supply are actually invest demand and invest supply.
  • Curve implies functions have curvature.

:::{.animategraph    title="Linear" style="height:50%;"    }

[]{.addElement type="line" var-x="quantity" var-y="demand" id="demand" }
[]{.addElement type="line" var-x="quantity" var-y="supply" }
[]{.move id="demand" var-x="quantity" var-y="demand_right" index=0 clone="true" }

:::


:::{.animategraph    title="Curve" style="height:50%;"    }

[]{.addElement type="line" var-x="quantity" var-y="demandCurve" }
[]{.addElement type="line" var-x="quantity" var-y="supplyCurve" id="supply"  }
[]{.move var-x="quantity" var-y="supplyCurve_right" index="1" id="supply"  }

:::

Full Documentation