Last updated

Animation Styles

Most of the shapes in Carnac can be animated using AnimationStyle, which internally uses AbstractEffects. Every effect can animate only one property of a shape. Parameters of effect are very similar to the SMIL animation. This tutorial includes several examples of animation below.

# Color Animation

This animation example changes the color of the shape.

import { Rectangle } from "@int/geotoolkit/scene/shapes/Rectangle.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { Group } from "@int/geotoolkit/scene/Group.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
function createScene(canvas) {
  const color = new Rectangle({
    "left": 50,
    "top": 10,
    "width": 200,
    "height": 100,
    "linestyle": {
      color: KnownColors.Orange,
      width: 3
    },
    "fillstyle": KnownColors.Blue,
    "animationstyle": {
      "attributename": "fill",
      "duration": 1e3,
      "repeatcount": Infinity,
      "from": KnownColors.Blue,
      "to": KnownColors.Orange
    }
  });
  return new Plot({
    "canvaselement": canvas,
    "root": new Group().addChild(color)
  });
}
export { createScene };

createScene(document.querySelector('[ref="plot"]'));

# Combined Animation

Animation effects can be run one by one.

import { Rectangle } from "@int/geotoolkit/scene/shapes/Rectangle.ts";
import { AnimationStyle } from "@int/geotoolkit/attributes/AnimationStyle.ts";
import { AnimationFill } from "@int/geotoolkit/animation/AnimationFill.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { Group } from "@int/geotoolkit/scene/Group.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
function createScene(canvas) {
  const rectangle = new Rectangle({
    "left": 50,
    "top": 50,
    "width": 10,
    "height": 50,
    "linestyle": {
      color: KnownColors.Orange,
      width: 3
    },
    "fillstyle": KnownColors.Blue
  });
  const combineAnimation = new AnimationStyle([{
    "attributename": "width",
    "fill": AnimationFill.Freeze,
    "begin": "2s;fill.end",
    "duration": 1e3,
    "id": "width",
    "from": 10,
    "to": 100
  }, {
    "id": "fill",
    "attributename": "fill",
    "begin": "width.end+1s",
    "duration": 1e3,
    "from": KnownColors.Blue,
    "to": KnownColors.Yellow
  }]);
  rectangle.setAnimationStyle(combineAnimation);
  return new Plot({
    "canvaselement": canvas,
    "root": new Group().addChild(rectangle)
  });
}
export { createScene };

createScene(document.querySelector('[ref="plot"]'));

# Complex Animation

Animation style can contain several effects, which would be animated simultaneously.

import { Rectangle } from "@int/geotoolkit/scene/shapes/Rectangle.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { Group } from "@int/geotoolkit/scene/Group.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
function createScene(canvas) {
  const complex = new Rectangle({
    "left": 0,
    "top": 100,
    "width": 50,
    "height": 50,
    "linestyle": {
      color: KnownColors.Orange,
      width: 3
    },
    "fillstyle": KnownColors.Blue,
    "animationstyle": [{
      "attributename": "transform",
      "type": "rotate",
      "duration": 2e3,
      "repeatcount": Infinity,
      "from": 0,
      "to": 360
    }, {
      "attributename": "x",
      "duration": 2e3,
      "repeatcount": Infinity,
      "values": [0, 300]
    }, {
      "attributename": "y",
      "duration": 2e3,
      "repeatcount": Infinity,
      "values": [100, 10, 100]
    }]
  });
  return new Plot({
    "canvaselement": canvas,
    "root": new Group().addChild(complex)
  });
}
export { createScene };

createScene(document.querySelector('[ref="plot"]'));

# Custom Animation

Animation style can also animate custom properties. For this there are 2 requirements

  • Animated property can be got/set with getProperties/setProperties
  • Type of animated property should be Number

For example, on Arc we can animate radius and startArc/endArc properties.


.cg-tooltip-holder {
  position: relative;
}

.cg-tooltip {
  position: absolute;
  display: block;
  padding: 2px 12px 3px 7px;
  overflow: visible !important;
  font-family: Roboto, Helvetica, Arial, sans-serif;
  font-size: 13px;
  background: white !important;
  opacity: 0.9;
  color: #333333;
  border: solid 1px gray;
  border-radius: 5px;
  text-align: left;
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
  border-radius: 5px;
  margin: 0 !important;
  z-index: 10000;
  max-width: 400px;
  text-wrap: normal !important;
  white-space: normal !important;
}
/* Default setting for tooltip */
.cg-tooltip-container {
  position: absolute;
  display: block;
  overflow: visible !important;
  font-family: Roboto, Helvetica, Arial, sans-serif;
  font-size: 12px;
  padding: 3px 7px;
  background: #f7f7f7;
  color: #333333;
  border: 1px solid #938e8e;
  opacity: 0.8;
  text-align: left;
  box-shadow: 3px 3px 10px #888;
  margin: 0 !important;
  z-index: 10000;
  max-width: 400px;
  text-wrap: normal !important;
  white-space: normal !important;
  user-select: none;
}
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
  .cg-tooltip-container {
    border-radius: 0;
  }
}
/* Default left arrow for tooltip */
.cg-tooltip-arrow-left::before {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  left: 0;
  top: 50%;
  border: 5px solid transparent;
  border-left: 0;
  border-right: 5px solid  #938e8e;
  transform: translate(calc(-100%), -50%);
}
.cg-tooltip-arrow-left::after {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  left: 0;
  top: 50%;
  border: 4px solid transparent;
  border-left: 0;
  border-right: 4px solid #f7f7f7;
  transform: translate(calc(-100%), -50%);
}
/* Default top arrow for tooltip */
.cg-tooltip-arrow-top::before {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  left: 50%;
  top: 0;
  border: 5px solid transparent;
  border-top: 0;
  border-bottom: 5px solid #938e8e;
  transform: translate(-50%, -100%);
}
.cg-tooltip-arrow-top::after {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  left: 50%;
  top: 0;
  border: 4px solid transparent;
  border-top: 0;
  border-bottom: 4px solid #f7f7f7;
  transform: translate(-50%, -100%);
}
/* Default right arrow for tooltip */
.cg-tooltip-arrow-right::before {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  right: 0;
  top: 50%;
  border: 5px solid transparent;
  border-right: 0;
  border-left: 5px solid #938e8e;
  transform: translate(100%, -50%);
}
.cg-tooltip-arrow-right::after {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  right: 0;
  top: 50%;
  border: 4px solid transparent;
  border-right: 0;
  border-left: 4px solid #f7f7f7;
  transform: translate(100%, -50%);
}
/* Default bottom arrow for tooltip */
.cg-tooltip-arrow-bottom::before {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  left: 50%;
  bottom: 0px;
  border: 5px solid transparent;
  border-bottom: 0;
  border-top: 5px solid #938e8e;
  transform: translate(-50%, 100%);
  z-index: 10000;
}
.cg-tooltip-arrow-bottom::after {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  left: 50%;
  bottom: 0;
  border: 4px solid transparent;
  border-bottom: 0;
  border-top: 4px solid #f7f7f7;
  transform: translate(-50%, 100%);
  z-index: 10000;
}
/* Tooltip item name */
/* Tooltip item value */
/* .cg-tooltip-item-value */
/* Tooltip item value */
.cg-tooltip-item-unit {
  text-transform: none;
}

.cg-tooltip-item-name {
    text-transform: capitalize;
    white-space: nowrap;
    vertical-align: middle;
    font-size: 13px;
}
.cg-tooltip-row {
  display: flex;
  flex-direction: row;
  align-items: center;
  white-space: pre-wrap;
  font-size: 12px;
  line-height: 100%;
  margin: 1px 0;
}
.cg-tooltip-title {
  font-size: 13px;
  height: 14px;
  text-transform: capitalize;
}
.cg-tooltip-title .cg-tooltip-symbol {
  margin-right: 0 !important;
}
.cg-tooltip-title-name {
  vertical-align: middle;
}
.cg-tooltip-row + .cg-tooltip-row {
  margin-top: 4px;
}
.cg-tooltip-row.cg-tooltip-title + .cg-tooltip-row {
  margin-top: 5px;
}
.cg-tooltip-item-value + .cg-tooltip-item-unit {
    margin-left: 1px;
}
/* Tooltip symbol */
.cg-tooltip-symbol-cell {
  display: inline-flex;
  min-width: 13px; /* 10px size + 3px margin */
}
.cg-tooltip-symbol {
  margin-right: 3px;
  background-color: transparent;
  display: block;
}
.cg-tooltip-symbol > img {
  display: block;
}
.cg-tooltip-list-cell {
  display: inline-flex;
}
.cg-tooltip-list-symbol {
  display: block;
  margin-right: 3px;
  width: 6px;
  height: 6px;
  vertical-align: middle;
  border-radius: 50%;
  border: 1px solid rgba(0,0,0,.4);
}
.cg-tooltip-symbol-legacy {
  border-radius: 4px;
  margin-right: 5px;
  height: 8px;
  width: 8px;
  display: inline-block;
}
.cg-tooltip-title-legacy {
  font-weight: 900;
}

/* Tooltip symbol circle */
.cg-tooltip-symbol.circle {
  height: 10px;
  width: 10px;
  display: inline-block;
  border-radius: 50%;
  border: 1px solid rgba(0,0,0,.4);
}
/* Tooltip symbol line */
.cg-tooltip-symbol.line {
    height: 10px;
    width: 10px;
    display: inline-block;
    transform: scale(1.2, 0.2);
}
/* Tooltip symbol diamond */
.cg-tooltip-symbol.diamond {
    height: 10px;
    width: 10px;
    display: inline-block;
    transform: rotate(45deg);
    border-radius: 0px;
}
/* Tooltip symbol square */
.cg-tooltip-symbol.square {
    height: 10px;
    width: 10px;
    display: inline-block;
    border-radius: 0px;
    border: 1px solid rgba(0,0,0,.4);
}

# Custom Effect

This example of custom animation on 3D PieChart shows how to animate inclination and pad of outsideline properties.

import { AbstractProcessor } from "@int/geotoolkit/animation/processors/AbstractProcessor.ts";
import { obfuscate } from "@int/geotoolkit/lib.js";
import { AbstractEffect } from "@int/geotoolkit/animation/effects/AbstractEffect.ts";
import { Registry } from "@int/geotoolkit/animation/effects/Registry.ts";
import { DataMode, LabelLocation, PieMode } from "@int/geotoolkit/controls/shapes/DonutChart.ts";
import { PieChart } from "@int/geotoolkit/controls/shapes/PieChart.ts";
import { AnimationStyle } from "@int/geotoolkit/attributes/AnimationStyle.ts";
import { Rect } from "@int/geotoolkit/util/Rect.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
import { Functions } from "@int/geotoolkit/animation/Easing.ts";
class Processor extends AbstractProcessor {
  constructor() {
    super();
  }
  process(from, to, out, func) {
    out = out || {};
    out["inclination3d"] = func(from["inclination3d"], to["inclination3d"]);
    out["outsideline"] = out["outsideline"] || {};
    out["outsideline"]["pad"] = func(from["outsideline"]["pad"], to["outsideline"]["pad"]);
    return out;
  }
  clone(value) {
    return {
      "inclination3d": value["inclination3d"],
      "outsideline": {
        "pad": value["outsideline"]["pad"]
      }
    };
  }
}
obfuscate(Processor);
class Effect extends AbstractEffect {
  constructor(attr) {
    super(attr);
    this.setProcessor(new Processor());
  }
  isApplicable(effect, node) {
    return effect["attributename"] === "options" && node instanceof PieChart;
  }
  getAnimatedValue(node) {
    const pieChart = node instanceof PieChart ? node : null;
    const options = pieChart?.getOptions();
    if (!options) {
      return null;
    }
    return {
      "inclination3d": options["inclination3d"],
      "outsideline": {
        "pad": options["outsideline"]["pad"]
      }
    };
  }
  apply(node) {
    const options = this.getCurrentValue();
    const pieChart = node instanceof PieChart ? node : null;
    pieChart?.setOptions({
      "inclination3d": options["inclination3d"],
      "outsideline": {
        "pad": options["outsideline"]["pad"]
      }
    });
  }
}
obfuscate(Effect);
Registry.getInstance().registerEffect(Effect);
let idTimeout, idInterval;
function createScene(canvas) {
  const values = {
    "Chert": 30,
    "Shale": 17,
    "Salt": 22,
    "Limestone": 10
  };
  const data = {
    "mode": DataMode.Associative,
    "values": values
  };
  const options = {
    "minpercentage": 2,
    "maxslices": 4,
    "piemode": PieMode.Pie3D,
    "inclination3d": 0,
    "depth3d": 50,
    "fillstyles": [
      KnownColors.Red,
      KnownColors.Blue,
      KnownColors.Green,
      KnownColors.Yellow
    ],
    "label": {
      "textstyle": {
        "font": "8pt Arial"
      },
      "location": LabelLocation.Outside
    },
    "outsideline": {
      "length": 15,
      "pad": 0
    }
  };
  const widget = new PieChart(options, data);
  const animationStyle = new AnimationStyle({
    "attributename": "options",
    "begin": "auto",
    "duration": 1500,
    "function": Functions.EaseOutBounce
  });
  widget.setAnimationStyle(animationStyle);
  const plot = new Plot({
    "canvaselement": canvas,
    "root": widget,
    "autorootbounds": false
  });
  const W = plot.getWidth(), H = plot.getHeight();
  const xC = W / 2, yC = H / 2;
  widget.setBounds(new Rect(xC - 130, yC - 130, xC + 130, yC + 130));
  widget.setOptions({
    "inclination3d": 50,
    "outsideline": {
      "pad": 25
    }
  });
  idInterval = window.setInterval(() => {
    widget.setAnimationStyle(null).setVisible(false).setOptions({
      "inclination3d": 0,
      "outsideline": {
        "pad": 0
      }
    }).setAnimationStyle(animationStyle);
    idTimeout = window.setTimeout(() => {
      widget.setOptions({
        "inclination3d": 50,
        "outsideline": {
          "pad": 25
        }
      }).setVisible(true);
    }, 300);
  }, 4e3);
  return plot;
}
function clear() {
  clearInterval(idInterval);
  clearTimeout(idTimeout);
}
export {
  clear,
  createScene
};

createScene(document.querySelector('[ref="plot"]'));

# Opacity Animation

This animation example shows how to change the Opacity to create the animation effect.

import { Rectangle } from "@int/geotoolkit/scene/shapes/Rectangle.ts";
import { Image } from "@int/geotoolkit/scene/shapes/Image.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { Group } from "@int/geotoolkit/scene/Group.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
import intImage from "/src/assets/images/slb-134x80.png?import";
function createScene(canvas) {
  const opacity = [new Rectangle({
    "left": 50,
    "top": 50,
    "width": 50,
    "height": 50,
    "linestyle": {
      color: KnownColors.Orange,
      width: 3
    },
    "fillstyle": KnownColors.Blue,
    "animationstyle": {
      "attributename": "opacity",
      "duration": 1e3,
      "repeatcount": Infinity,
      "from": 1,
      "to": 0
    }
  }), new Image({
    "ax": 120,
    "ay": 35,
    "url": intImage,
    "animationstyle": {
      "attributename": "opacity",
      "duration": 1e3,
      "repeatcount": Infinity,
      "from": 1,
      "to": 0
    }
  })];
  return new Plot({
    "canvaselement": canvas,
    "root": new Group().addChild(opacity)
  });
}
export { createScene };

createScene(document.querySelector('[ref="plot"]'));

# Position Animation

This animation example uses the EasingFunction to change the position of the shape.


.cg-tooltip-holder {
  position: relative;
}

.cg-tooltip {
  position: absolute;
  display: block;
  padding: 2px 12px 3px 7px;
  overflow: visible !important;
  font-family: Roboto, Helvetica, Arial, sans-serif;
  font-size: 13px;
  background: white !important;
  opacity: 0.9;
  color: #333333;
  border: solid 1px gray;
  border-radius: 5px;
  text-align: left;
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
  border-radius: 5px;
  margin: 0 !important;
  z-index: 10000;
  max-width: 400px;
  text-wrap: normal !important;
  white-space: normal !important;
}
/* Default setting for tooltip */
.cg-tooltip-container {
  position: absolute;
  display: block;
  overflow: visible !important;
  font-family: Roboto, Helvetica, Arial, sans-serif;
  font-size: 12px;
  padding: 3px 7px;
  background: #f7f7f7;
  color: #333333;
  border: 1px solid #938e8e;
  opacity: 0.8;
  text-align: left;
  box-shadow: 3px 3px 10px #888;
  margin: 0 !important;
  z-index: 10000;
  max-width: 400px;
  text-wrap: normal !important;
  white-space: normal !important;
  user-select: none;
}
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
  .cg-tooltip-container {
    border-radius: 0;
  }
}
/* Default left arrow for tooltip */
.cg-tooltip-arrow-left::before {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  left: 0;
  top: 50%;
  border: 5px solid transparent;
  border-left: 0;
  border-right: 5px solid  #938e8e;
  transform: translate(calc(-100%), -50%);
}
.cg-tooltip-arrow-left::after {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  left: 0;
  top: 50%;
  border: 4px solid transparent;
  border-left: 0;
  border-right: 4px solid #f7f7f7;
  transform: translate(calc(-100%), -50%);
}
/* Default top arrow for tooltip */
.cg-tooltip-arrow-top::before {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  left: 50%;
  top: 0;
  border: 5px solid transparent;
  border-top: 0;
  border-bottom: 5px solid #938e8e;
  transform: translate(-50%, -100%);
}
.cg-tooltip-arrow-top::after {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  left: 50%;
  top: 0;
  border: 4px solid transparent;
  border-top: 0;
  border-bottom: 4px solid #f7f7f7;
  transform: translate(-50%, -100%);
}
/* Default right arrow for tooltip */
.cg-tooltip-arrow-right::before {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  right: 0;
  top: 50%;
  border: 5px solid transparent;
  border-right: 0;
  border-left: 5px solid #938e8e;
  transform: translate(100%, -50%);
}
.cg-tooltip-arrow-right::after {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  right: 0;
  top: 50%;
  border: 4px solid transparent;
  border-right: 0;
  border-left: 4px solid #f7f7f7;
  transform: translate(100%, -50%);
}
/* Default bottom arrow for tooltip */
.cg-tooltip-arrow-bottom::before {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  left: 50%;
  bottom: 0px;
  border: 5px solid transparent;
  border-bottom: 0;
  border-top: 5px solid #938e8e;
  transform: translate(-50%, 100%);
  z-index: 10000;
}
.cg-tooltip-arrow-bottom::after {
  content: '';
  position: absolute;
  display: block;
  width: 0px;
  left: 50%;
  bottom: 0;
  border: 4px solid transparent;
  border-bottom: 0;
  border-top: 4px solid #f7f7f7;
  transform: translate(-50%, 100%);
  z-index: 10000;
}
/* Tooltip item name */
/* Tooltip item value */
/* .cg-tooltip-item-value */
/* Tooltip item value */
.cg-tooltip-item-unit {
  text-transform: none;
}

.cg-tooltip-item-name {
    text-transform: capitalize;
    white-space: nowrap;
    vertical-align: middle;
    font-size: 13px;
}
.cg-tooltip-row {
  display: flex;
  flex-direction: row;
  align-items: center;
  white-space: pre-wrap;
  font-size: 12px;
  line-height: 100%;
  margin: 1px 0;
}
.cg-tooltip-title {
  font-size: 13px;
  height: 14px;
  text-transform: capitalize;
}
.cg-tooltip-title .cg-tooltip-symbol {
  margin-right: 0 !important;
}
.cg-tooltip-title-name {
  vertical-align: middle;
}
.cg-tooltip-row + .cg-tooltip-row {
  margin-top: 4px;
}
.cg-tooltip-row.cg-tooltip-title + .cg-tooltip-row {
  margin-top: 5px;
}
.cg-tooltip-item-value + .cg-tooltip-item-unit {
    margin-left: 1px;
}
/* Tooltip symbol */
.cg-tooltip-symbol-cell {
  display: inline-flex;
  min-width: 13px; /* 10px size + 3px margin */
}
.cg-tooltip-symbol {
  margin-right: 3px;
  background-color: transparent;
  display: block;
}
.cg-tooltip-symbol > img {
  display: block;
}
.cg-tooltip-list-cell {
  display: inline-flex;
}
.cg-tooltip-list-symbol {
  display: block;
  margin-right: 3px;
  width: 6px;
  height: 6px;
  vertical-align: middle;
  border-radius: 50%;
  border: 1px solid rgba(0,0,0,.4);
}
.cg-tooltip-symbol-legacy {
  border-radius: 4px;
  margin-right: 5px;
  height: 8px;
  width: 8px;
  display: inline-block;
}
.cg-tooltip-title-legacy {
  font-weight: 900;
}

/* Tooltip symbol circle */
.cg-tooltip-symbol.circle {
  height: 10px;
  width: 10px;
  display: inline-block;
  border-radius: 50%;
  border: 1px solid rgba(0,0,0,.4);
}
/* Tooltip symbol line */
.cg-tooltip-symbol.line {
    height: 10px;
    width: 10px;
    display: inline-block;
    transform: scale(1.2, 0.2);
}
/* Tooltip symbol diamond */
.cg-tooltip-symbol.diamond {
    height: 10px;
    width: 10px;
    display: inline-block;
    transform: rotate(45deg);
    border-radius: 0px;
}
/* Tooltip symbol square */
.cg-tooltip-symbol.square {
    height: 10px;
    width: 10px;
    display: inline-block;
    border-radius: 0px;
    border: 1px solid rgba(0,0,0,.4);
}

# Size Animation

This animation example shows how to change the attributes height and width to create the animation effect.

import { Rectangle } from "@int/geotoolkit/scene/shapes/Rectangle.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { Group } from "@int/geotoolkit/scene/Group.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
function createScene(canvas) {
  const size = new Rectangle({
    "left": 50,
    "top": 50,
    "width": 5,
    "height": 50,
    "linestyle": {
      color: KnownColors.Orange,
      width: 3
    },
    "fillstyle": KnownColors.Blue,
    "animationstyle": [{
      "attributename": "width",
      "duration": 1e3,
      "repeatcount": Infinity,
      "from": 5,
      "to": 200
    }, {
      "attributename": "height",
      "duration": 1e3,
      "repeatcount": Infinity,
      "from": 50,
      "to": 5
    }]
  });
  return new Plot({
    "canvaselement": canvas,
    "root": new Group().addChild(size)
  });
}
export { createScene };

createScene(document.querySelector('[ref="plot"]'));

# Transformation

This animation example shows how to change the transform attributes to create the animation effect.

import { Rectangle } from "@int/geotoolkit/scene/shapes/Rectangle.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { Group } from "@int/geotoolkit/scene/Group.ts";
import { KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
function createScene(canvas) {
  const transformation = new Rectangle({
    "left": 50,
    "top": 50,
    "width": 50,
    "height": 50,
    "linestyle": {
      color: KnownColors.Orange,
      width: 3
    },
    "fillstyle": KnownColors.Blue,
    "animationstyle": {
      "attributename": "transform",
      "type": "translate",
      "duration": 1e3,
      "repeatcount": Infinity,
      "unit": "cm",
      "from": { "x": 0, "y": 0 },
      "to": { "x": 2, "y": 0 }
    }
  });
  return new Plot({
    "canvaselement": canvas,
    "root": new Group().addChild(transformation)
  });
}
export { createScene };

createScene(document.querySelector('[ref="plot"]'));