<div align="center">
    <a>
        <h3>🎨</h3>
        <h1>GraphX™</h1>
    </a>

[![pub package](https://img.shields.io/pub/v/graphx.svg?logo=data:image/svg+xml;base64, &label=graphx&style=for-the-badge&color=blue)](https://pub.dev/packages/graphx)
[![style: effective dart](https://img.shields.io/badge/style-effective_dart-40c4ff.svg?style=for-the-badge&color=blue)](https://pub.dev/packages/effective_dart)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=for-the-badge&color=blue)](https://opensource.org/licenses/MIT)

| rendering | prototype | design |

Making drawings and animations in Flutter extremely simple.

</div>

### wiki-tips.

To get some extended, boring explanations, and eventually some sample codes, check the [GraphX™ Wiki](<https://github.com/roipeker/graphx/wiki/GraphX-tips-and-random%5BnextInt()%5D-stuffs.#graphx-general-tips>)

---

[Try Graphx (0.0.9) on Dart Pad](https://dartpad.dev/21b6670a42d32e37440192e19279e71b?)

#### news!

- Support for [null-safety](https://github.com/roipeker/graphx/tree/null-safety)
- Support for HotReload

#### prototyping

GraphX is all about visuals, here you have some screen captures of random prototypes I've been doing, while developing and testing graphx.

For your GraphX scene to support **Hot Reload**, you should initialize your variables and DisplayObjects inside `addedToStage`, and optionally clean them in `dispose`.

[![artificial horizon](https://media.giphy.com/media/NMG8gfpJxFiu1eALZo/giphy.gif)](https://media.giphy.com/media/NMG8gfpJxFiu1eALZo/source.mp4)
[![parallax game](https://media.giphy.com/media/RIrvhfZoDtal41Tb4e/giphy-downsized.gif)](https://media.giphy.com/media/RIrvhfZoDtal41Tb4e/source.mp4)
[![charts pie color 2](https://media.giphy.com/media/pQdeurUOAqWdZuxxUK/giphy.gif)](https://media.giphy.com/media/pQdeurUOAqWdZuxxUK/source.mp4)
[![simple particles](https://media.giphy.com/media/VYSJF6uUO323FV0Nhh/giphy.gif)](https://media.giphy.com/media/WodwBEccmRjmhq2dAp/source.mp4)
[![drawing api playful v1](https://media.giphy.com/media/HdJmgzVYLK8jUxX437/giphy.gif)](https://media.giphy.com/media/HdJmgzVYLK8jUxX437/source.mp4)

... jump to [other gifs samples](#screencast-demos) ...

<div align="left">
    
## Background.

GraphX™ is here to help you build custom drawings in your Flutter apps. Providing a great versatility to power those screen pixels to a different level.

It's inspired by the good-old Flash API, which forged my way into programming back in the days, and inspired many other rendering frameworks, in several languages through the years.

I was thinking how much I missed to "play" with code, to make things more organic, artistic, alive... I totally love Flutter, but I always feel that it requires too much boilerplate to make things move around (compared to what I used to code).

Even if GraphX™ is not an animation library (although has a small tween engine), nor a game engine, It can help you build really awesome user experiences! It just runs on top of `CustomPainter`... Using what Flutter SDK exposes from the SKIA engine through the Canvas, yet, gives you some "framework" to run `isolated` from the Widget's world.

Can be used to simple draw a line, a circle, maybe a custom button, some splash effect on your UI, or even a full-blown game in a portion of the screen.

Mix and match with Flutter as you please, as **GraphX**™ uses `CustomPainter`, it is part of your Widget's tree.

## Concept.

The repo is in early stages. You can check the changelog to get the latest updates.

GraphX has support for loading `rootBundle` assets:

```dart
ResourceLoader.loadBinary(assetId)
ResourceLoader.loadGif(assetId)
ResourceLoader.loadTextureAtlas(imagePath, xmlPath)
ResourceLoader.loadTexture(assetId)
ResourceLoader.loadImage(assetId)
ResourceLoader.loadString(assetId)
ResourceLoader.loadJson(assetId)
ResourceLoader.loadSvg(assetId)
```

As well as network images (SVG is not supported on non-SKIA targets):

```dart
ResourceLoader.loadNetworkTexture(url);
ResourceLoader.loadNetworkSvg(url);
```

ResourceLoader also stores in cache based on the `assetId` or `url` provided. You can pass `cacheId` in most methods
to override that, once the resources loaded, you can access them with:

```dart
ResourceLoader.getTexture(id);
ResourceLoader.getSvg(id);
ResourceLoader.getAtlas(id);
ResourceLoader.getGif(id);
```

GraphX™ also provides "raw" support for Text rendering, using the `StaticText` class.

---

How does it work?

GraphX™ drives a `CustomPainter` inside. The idea is to simplify the usage of Flutter's `Canvas`, plus adding the **display list** concept, very similar to the Widget Tree concept; so you can imperatively code, manage and create more complex "Scenes".

The library has its own rendering cycle using Flutter's `Ticker` (pretty much like `AnimationController` does), and each `SceneWidgetBuilder` does its own input capture and processing (mouse, keyboard, touches). Even if it runs on the Widget tree, you can enable the flags to capture mouse/touch input, or keystrokes events (if u wanna do some simple game, or desktop/web tool).

### Sample code.

```dart
  body: Center(
    child: SceneBuilderWidget( /// wrap any Widget with SceneBuilderWidget
      builder: () => SceneController(
        back: GameSceneBack(), /// optional provide the background layer
        front: GameSceneFront(), /// optional provide the foreground layer
      ),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            'You have pushed the button this many times:',
          ),
          Text(
            '$_counter',
            style: Theme.of(context).textTheme.headline4,
          ),
        ],
      ),
    ),
  ),
```

GraphX™ is based on "Scenes", each `SceneBuilderWidget` requires a `SceneController`.
This controller is the initializer of the Scenes layers, which can be:

- `back` (background painter),
- `front` (foreground painter),
- or both.

Also takes a `SceneConfig()`, so you can configure what you need from the Widget's side.
You can make use of some predefined Scene configurators:

- `SceneConfig.static`: If you plan to only use this scene to draw some graphics, like a background.
- `SceneConfig.games`: Activates all GraphX features, auto render and update, pointers and keyboard support.
- `SceneConfig.tools`: Shortcut of _games_, helpful if you wanna use it in some custom drawing editor, or similar with keyboard shortcuts.
- `SceneConfig.interactive` (_default_): Probably the most common setup for mobile, enables all features except keyboard support.
- `SceneConfig.autoRender`: Allows you to have a ticker running, and auto update the scene, with NO inputs (mouse/touch/keyboard), if you wanna have an animated Widget, or maybe if you wanna control it externally.

Each "Scene" has to extend `Sprite`, this root class represents the starting point of that particular scene hierarchy. Think of it as `MaterialApp` widget is to all other children Widgets in the tree.

Here we get into **GraphX™** world, no more Widgets trees or immutable properties.

You can make custom UI widgets, games, or make use of GraphX to create a static drawing, like curved backgrounds, or complex shapes.

Is a good practice to override `addedToStage()` as your entry point, here the Scene is ready, the `root` class has been added to the _glorified stage_, so you can access the Canvas size through `stage.stageWidth` and `stage.stageHeight`, the keyboard manager (if available), and lots of other properties, up to the `SceneController` that owns the scene (`stage.scene.core`, although, that's irrelevant for now):

```dart
class GameScene extends Sprite {

  @override
  void addedToStage() {
    /// Here you can access the `stage`, get the size of the
    /// current Scene, keyboard events, or any stage property
    /// You can initialize your DisplayObjects here to play
    /// "safe" if you need to access any stage property.
  }
```

For now, GraphX™ has a few classes for rendering in the "display list":
Like `Shape` (for "pen" drawings commands through it's `graphics` property), `Sprite` (create hierarchies of rendering objects), `StaticText` (for Texts), `GxIcon` (for Flutter icons), `Bitmap` (for `GTexture`, which is a wrapper around `dart:ui.Image`), `MovieClip`(for Spritesheet and Gif support), `SvgShape` (dependency for `svg`, package not included), `SimpleParticleSystem` (to create optimized particles for games), and Flare/Rive render objects which will live in another package/utility eventually to avoid dependencies.

By the way, in the previous example, `GameScene` is the `root` node in the _display tree_, the entry point where DisplayObjects renders, and where you need to add your own objects.

For instance, to create a simple purple circle:

```dart
@override
void addedToStage(){
    var circle = Shape();
    circle.graphics.lineStyle(2, Colors.purple.value) /// access HEX value of Color
      ..drawCircle(0, 0, 20)
      ..endFill();
    addChild(circle); // add the child to the rootScene.
}
```

`Sprite` internally extends from the abstract class `DisplayObjectContainer`, and as the name implies, is a container that can contain more `DisplayObject`s. Yet, `Shape` is a `DisplayObject` (another abstract class, and also, the root class of all rendering objects in **GraphX**), so it can't contain children. That makes it a bit more performant on each painter step.
So, when you need to group objects, you should create `Sprite`s and add children into it, even other `Sprite`s, that's the idea of **GraphX** after all, group rendering objects so you can transform them independently or transform a parent `Sprite` (or subclass of it), and apply it to the tree inside of it, transformations are accumulative from parent to child ...

#### What is a transformation?

The ability to translate, scale, rotate, skew a `DisplayObject` through his properties: x, y, width, height, scaleX, scaleY, rotation, skewX, skewY, etc.

We could also use our root scene to draw things:

```dart
@override
addedToStage(){
  graphics.beginFill(0x0000ff, .6)
  ..drawRoundRect(100, 100, 40, 40, 4)
  ..endFill();
...
}
```

#### Pointer access

Pointer signals has been "simplified" as Mouse events now... as it's super easy to work with single touch / mouse interactions in `DisplayObject`s.
There are a bunch of signals to listen on each object... taken from AS3, and JS.

- onMouseDoubleClick
- onMouseClick
- onMouseDown
- onMouseUp
- onMouseMove
- onMouseOver
- onMouseOut
- onMouseScroll

They all emit a `MouseInputData` with all the needed info inside, like stage coordinates, or translated local coordinates, which "mouse" button is pressed, etc.

---

### Demos.

_Some demos are only using **GraphX™** partially_

- [snake game ⇢](https://graphx-snake-game.surge.sh/)
- [breakout game ⇢](https://graphx-breakout-v4.surge.sh/)

- [3d card with shadow ⇢](https://graphx-dropshadow-card.surge.sh/)
- [rating ⇢](https://graphx-star-rating.surge.sh/) ([dribbble design](https://dribbble.com/shots/12287144-Rating))

- [drawpad ⇢](https://graphx-drawpad3.surge.sh/) // [creepy version ⇢](https://graphx-drawpad2.surge.sh/)

- [node garden ⇢](https://graphx-node-garden.surge.sh/)

- [fb reactions ⇢](https://graphx-fb-reactions.surge.sh/)

- [puzzle pieces ⇢](https://roi-puzzle-v2.surge.sh/)

- [lines repulsion ⇢](https://roi-graphx-mouse-repulsion.surge.sh/)
- [liquify dog ⇢](https://roi-graphx-liquify-dog.surge.sh/)
- [image transform triangles ⇢](https://roi-graphx-image-transform-triangles.surge.sh/)
- [jelly green ⇢](https://roi-graphx-jelly-green.surge.sh/) ([source](https://gist.github.com/roipeker/dbf792b862ad8dfb526c227c2e1d4ad9))

- [drawing-ball collision ⇢](https://roi-graphx-balls-collision.surge.sh/) ([source](https://gist.github.com/roipeker/d0fbbb1fa5409594f18c8e280ac39d93))

- [spiral 3d ⇢](https://roi-graphx-spiral3d.surge.sh/) ([source](https://gist.github.com/roipeker/f5987e7158a3a7e932e2547e3d919951))

- [splashscreen ⇢](https://roi-graphx-splash.surge.sh/) ([source](https://gist.github.com/roipeker/37374272d15539aa60c2bdc39001a035))

- [color spectrum ⇢](https://roi-graphx-color-picker.surge.sh/) (based on [SuperDeclarative! workshop](https://www.youtube.com/watch?v=HURA4DKjA1c))

- [ui line button ⇢](https://roi-graphx-linebutton.surge.sh/)

- [flutter widget mix ⇢](https://roi-graphx-widgetmix.surge.sh)

- [space shooter ⇢](https://roi-graphx-spaceshooter.surge.sh)

  > controls > move: ARROWS, thrust: SHIFT, shoot: SPACEBAR, shield: U

- [artificial horizon ⇢](https://roi-graphx-artificial-horizon.surge.sh/)

  > controls > change altitude and rotation: ARROWS

- [split RGB ⇢](https://roi-graphx-rgbsplit.surge.sh)

- [input text particles ⇢](https://roi-graphx-particles-input.surge.sh)

- [fishEye particles ⇢](https://roi-graphx-fisheyeparticles.surge.sh/)

- [fishEye particles (basic) ⇢](https://roi-graphx-fisheyetext.surge.sh)

- [particles emitter ⇢](https://roi-graphx-particles2.surge.sh)

- [shapeMaker clone ⇢](https://roi-graphx-shapemaker.surge.sh)

- [mouse follower ⇢](https://roi-graphx-dotchain.surge.sh)

- [basic hit test ⇢](https://roi-graphx-hittest.surge.sh)

- [spriteSheet rendering ⇢](https://roi-graphx-spritesheet.surge.sh)

- [displayObject pivot ⇢](https://roi-graphx-textpivot.surge.sh)

- [simple solo-ping-pong game ⇢](https://roi-graphx-pingpong.surge.sh/)

- [first experiment with graphx ⇢](https://roi-graphx-cells.surge.sh/)

---

Feel free to play around with the current API, even if it's still rough on edges and unoptimized, it might help you do things quicker.

SKIA is pretty powerful!

</div>

---

### help & socialize.

| **Discord**                                                                                                                                | **Telegram**                                                                                                                                            |
| :----------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [![Discord Shield](https://img.shields.io/discord/777232130991718440.svg?style=for-the-badge&logo=discord)](https://discord.gg/5aTX6HzS5Q) | [![Telegram](https://img.shields.io/badge/chat-on%20Telegram-blue.svg?style=for-the-badge&logo=telegram)](https://t.me/joinchat/Mbc7jBxxAm4K1uhaVPIR-Q) |

---

### Screencast Demos.

(Some demos uses GraphX's only for ticker, input events or initial scene graph, making usage of
direct `Canvas` calls).\_

- charts bezier + gradient

  [![charts bezier + gradient](https://media.giphy.com/media/QWHufIK9GyEAIM4Dcn/giphy.gif)](https://media.giphy.com/media/QWHufIK9GyEAIM4Dcn/source.mp4)

- neumorphic button

  [![neumorphic button](https://media.giphy.com/media/tX24wynwPRVm6cymjy/giphy.gif)](https://media.giphy.com/media/tX24wynwPRVm6cymjy/source.mov)

- 3d card shadow

  [![3d card shadow](https://media.giphy.com/media/18XFI8lY9Uj6cgoF66/giphy-downsized.gif)](https://media.giphy.com/media/18XFI8lY9Uj6cgoF66/source.mp4)

- 3d pizza box

  [![3d pizza box](https://media.giphy.com/media/8OUnKDJ2ujT9pBpylj/giphy.gif)](https://media.giphy.com/media/8OUnKDJ2ujT9pBpylj/source.mp4)

- pendulum

  [![pendulum](https://media.giphy.com/media/6D946gz1PkF0zZV697/giphy.gif)](https://media.giphy.com/media/6D946gz1PkF0zZV697/source.mp4)

- rating stars

  [![rating stars](https://media.giphy.com/media/2ZK44FneclymOpyEXR/giphy.gif)](https://media.giphy.com/media/2ZK44FneclymOpyEXR/source.mov)

- rotating dial

  [![rotating dial](https://media.giphy.com/media/xC8rB3jR9nXDJDMwQM/giphy.gif)](https://media.giphy.com/media/xC8rB3jR9nXDJDMwQM/source.mp4)

- intro "universo flutter"

  [![intro "universo flutter"](https://media.giphy.com/media/ZyVw45nnrQ49Ig3NCb/giphy.gif)](https://media.giphy.com/media/ZyVw45nnrQ49Ig3NCb/source.mp4)

- 3d spiral loader

  [![3d spiral loader](https://media.giphy.com/media/eT1pePI6NqpEg3rBmA/giphy.gif)](https://media.giphy.com/media/eT1pePI6NqpEg3rBmA/source.mov)

- breakout game

  [![breakout game](https://media.giphy.com/media/roLsn44mOUpbOhV0Da/giphy.gif)](https://media.giphy.com/media/roLsn44mOUpbOhV0Da/source.mov)

- gauges

  [![gauges](https://media.giphy.com/media/rWF1Sc4CGLf3zfYlXn/giphy-downsized.gif)](https://media.giphy.com/media/rWF1Sc4CGLf3zfYlXn/source.mp4)

- bubble loader

  [![bubble loader](https://media.giphy.com/media/pKXa68pcv2H1dSjxYX/giphy.gif)](https://media.giphy.com/media/pKXa68pcv2H1dSjxYX/source.mp4)

- xmas counter

  [![xmas counter](https://media.giphy.com/media/yTNXKR5BHbQKOKpfrS/giphy-downsized.gif)](https://media.giphy.com/media/yTNXKR5BHbQKOKpfrS/source.mp4)

- google fonts

  [![google fonts](https://media.giphy.com/media/oUoYS87SzOldcI5itX/giphy.gif)](https://media.giphy.com/media/oUoYS87SzOldcI5itX/source.mp4)

- graphics.drawTriangles

  [![graphics.drawTriangles](https://media.giphy.com/media/Dh7i3D5z1kbWpc4bn3/giphy-downsized.gif)](https://media.giphy.com/media/Dh7i3D5z1kbWpc4bn3/source.mp4)

- image transform

  [![image transform](https://media.giphy.com/media/s9BcsLdSGMU0ARvOQX/giphy.gif)](https://media.giphy.com/media/s9BcsLdSGMU0ARvOQX/source.mp4)

- svg sample demo

  [![svg sample demo](https://media.giphy.com/media/OtGpmd1fAVzw3pK7kD/giphy.gif)](https://media.giphy.com/media/wLuFm9xlXXmkllWJQt/source.mp4)

- chart lines

  [![charts lines](https://media.giphy.com/media/uVFvFOTUICAsYqb13r/giphy.gif)](https://media.giphy.com/media/uVFvFOTUICAsYqb13r/source.mp4)

- charts pie

  [![charts pie color 1](https://media.giphy.com/media/z1aIQzYSSGVKeWbabJ/giphy.gif)](https://media.giphy.com/media/z1aIQzYSSGVKeWbabJ/source.mp4)

- mouse cursor support

  [![mouse cursor support](https://media.giphy.com/media/MjXTKJpen8vIN34rfW/giphy.gif)](https://media.giphy.com/media/MjXTKJpen8vIN34rfW/source.mp4)

- debug objects bounds

  [![debug objects bounds](https://media.giphy.com/media/F7Wnsw3kUjk0L4CDfu/giphy.gif)](https://media.giphy.com/media/F7Wnsw3kUjk0L4CDfu/source.mp4)

- demo sample tween

  [![demo sample tween](https://media.giphy.com/media/EY4RhVoqHTKVBJUNzW/giphy.gif)](https://media.giphy.com/media/EY4RhVoqHTKVBJUNzW/source.mp4)

- direction blur filter

  [![directional blur filter](https://media.giphy.com/media/a4Rzda8uvFxCPvfI22/giphy.gif)](https://media.giphy.com/media/a4Rzda8uvFxCPvfI22/source.mp4)

- hand drawing v1

  [![hand drawing v1](https://media.giphy.com/media/uliHRVWVW5IlliliIi/giphy-downsized.gif)](https://media.giphy.com/media/uliHRVWVW5IlliliIi/source.mp4)

- hand drawing v2

  [![hand drawing v2](https://media.giphy.com/media/f6UJj36HqFYJuejz5M/giphy.gif)](https://media.giphy.com/media/f6UJj36HqFYJuejz5M/source.mp4)

- drawing api playful v2

  [![drawing api playful v2](https://media.giphy.com/media/Ld3XIYErKsoyCQtzcg/giphy.gif)](https://media.giphy.com/media/Ld3XIYErKsoyCQtzcg/source.mp4)

- elastic band

  [![elastic band](https://media.giphy.com/media/KiSrFNYQ7kED1HzSlJ/giphy.gif)](https://media.giphy.com/media/KiSrFNYQ7kED1HzSlJ/source.mp4)

- flare playback

  [![Flare playback](https://media.giphy.com/media/t0ZcOUPdCtg8aPtL2B/giphy-downsized.gif)](https://media.giphy.com/media/t0ZcOUPdCtg8aPtL2B/source.mp4)

- flip child scenes

  [![Flip child scenes](https://media.giphy.com/media/siMNzfRWTaKK9Pw0n2/giphy.gif)](https://media.giphy.com/media/siMNzfRWTaKK9Pw0n2/source.mp4)

- flutter widgets mix

  [![Mix with Flutter widgets](https://media.giphy.com/media/YfzNLmfE1hutWI176e/giphy-downsized.gif)](https://media.giphy.com/media/YfzNLmfE1hutWI176e/source.mp4)

- icon with gradient paint

  [![icon painter gradient](https://media.giphy.com/media/gC94IOdu6v1GoWJZWY/giphy.gif)](https://media.giphy.com/media/gC94IOdu6v1GoWJZWY/source.mp4)

- inverted masks

  [![inverted masks](https://media.giphy.com/media/1tsbaO28YXXxc1lvsd/giphy-downsized.gif)](https://media.giphy.com/media/1tsbaO28YXXxc1lvsd/source.mp4)

- isometric demo

  [![isometric demo](https://media.giphy.com/media/EInY3MKZ2xvmYNl3fm/giphy.gif)](https://media.giphy.com/media/EInY3MKZ2xvmYNl3fm/source.mp4)

- light button

  [![light button](https://media.giphy.com/media/4Sspuw3R8Rdr2tsE4T/giphy.gif)](https://media.giphy.com/media/4Sspuw3R8Rdr2tsE4T/source.mp4)

- marquesina

  [![marquesina de texto](https://media.giphy.com/media/Q2cIsU34CbzZHfNA2z/giphy.gif)](https://media.giphy.com/media/Q2cIsU34CbzZHfNA2z/source.mp4)

- menu with mask

  [![menu mask](https://media.giphy.com/media/xaEN62vmEQxTR1zFpy/giphy.gif)](https://media.giphy.com/media/xaEN62vmEQxTR1zFpy/source.mp4)

- menu mouse test

  [![menu mouse](https://media.giphy.com/media/d9cQT0mOwgbRJ2fbyd/giphy.gif)](https://media.giphy.com/media/d9cQT0mOwgbRJ2fbyd/source.mp4)

- nested transformations

  [![nested transform touch](https://media.giphy.com/media/HLdqEQze3LUDlDCTBo/giphy.gif)](https://media.giphy.com/media/HLdqEQze3LUDlDCTBo/source.mp4)

- particles with alpha

  [![particles with alpha](https://media.giphy.com/media/Z9D7bpWqjX8KJMTMMc/giphy-downsized.gif)](https://media.giphy.com/media/Z9D7bpWqjX8KJMTMMc/source.mp4)

- particles blending

  [![particles blend](https://media.giphy.com/media/roD1B1diHxT9A61msb/giphy-downsized-large.gif)](https://media.giphy.com/media/roD1B1diHxT9A61msb/source.mp4)

- circular progress panel

  [![progress panel](https://media.giphy.com/media/uygZcQPIe7Dp4RHHrB/giphy.gif)](https://media.giphy.com/media/uygZcQPIe7Dp4RHHrB/source.mp4)

- rive playback

  [![rive playback](https://media.giphy.com/media/lVBkZ6o1qBqnek92Qj/giphy-downsized.gif)](https://media.giphy.com/media/lVBkZ6o1qBqnek92Qj/source.mp4)

- 3d rotation

  [![rotation 3d](https://media.giphy.com/media/7T3hqnHc7cRrqEjE4a/giphy.gif)](https://media.giphy.com/media/7T3hqnHc7cRrqEjE4a/source.mp4)

- spiral

  [![spiral](https://media.giphy.com/media/z9FFwt6sPQSqrVuMyF/giphy-downsized.gif)](https://media.giphy.com/media/z9FFwt6sPQSqrVuMyF/source.mp4)

- spritesheet explosion

  [![spritesheet explosion](https://media.giphy.com/media/Ldj7i8XiPZpYZ92WNN/giphy.gif)](https://media.giphy.com/media/Ldj7i8XiPZpYZ92WNN/source.mp4)

- supernova tween

  [![star effect](https://media.giphy.com/media/LFAhCww7vVItef78v9/giphy.gif)](https://media.giphy.com/media/LFAhCww7vVItef78v9/source.mp4)

- text rainbow

  [![text rainbow](https://media.giphy.com/media/wk8s7jJnwfdBQfbdvb/giphy.gif)](https://media.giphy.com/media/wk8s7jJnwfdBQfbdvb/source.mp4)

- basic tween animation

  [![tween animation](https://media.giphy.com/media/XNO5QpJCyctdLZYMCS/giphy.gif)](https://media.giphy.com/media/XNO5QpJCyctdLZYMCS/source.mp4)

- tween behaviour

  [![tween behaviour](https://media.giphy.com/media/DWbutR01h9LpschVDA/giphy.gif)](https://media.giphy.com/media/DWbutR01h9LpschVDA/source.mp4)

- tween color

  [![tween color](https://media.giphy.com/media/1tjXlWG1ImPhI3eij4/giphy.gif)](https://media.giphy.com/media/1tjXlWG1ImPhI3eij4/source.mp4)

- multiple scenes

  [![multiple scenes](https://media.giphy.com/media/mUoYPvPQIqZZ0rEVVe/giphy-downsized.gif)](https://media.giphy.com/media/mUoYPvPQIqZZ0rEVVe/source.mp4)

- [line button ⇢](https://roi-graphx-linebutton.surge.sh/)

  [![line button](https://media.giphy.com/media/Uq4pPWGa2Qo5WwlRqA/giphy.gif)](https://media.giphy.com/media/Uq4pPWGa2Qo5WwlRqA/source.mp4)

- [color picker ⇢](https://roi-graphx-color-picker.surge.sh/)

  [![color picker](https://media.giphy.com/media/r8BGvFFPdHU59dJbbB/giphy.gif)](https://media.giphy.com/media/r8BGvFFPdHU59dJbbB/source.mp4)

- responsive switch

  [![responsive switch](https://media.giphy.com/media/vO4DwTNeIXUS7beQFA/giphy.gif)](https://media.giphy.com/media/vO4DwTNeIXUS7beQFA/source.mp4)

---

#### Donation

You can [buymeacoffee](https://www.buymeacoffee.com/roipeker) or support **GraphX™** via [Paypal](https://www.paypal.me/roipeker/)

[![Donate via PayPal](https://cdn.rawgit.com/twolfson/paypal-github-button/1.0.0/dist/button.svg)](https://www.paypal.me/roipeker/)

## [![Support via buymeacoffee](https://cdn.buymeacoffee.com/buttons/v2/default-white.png)](https://www.buymeacoffee.com/roipeker)
