GraphX™
GraphX Flutter 库。
警告:此库仍处于Alpha阶段,API可能会发生更改。
注意:GraphX™将$前缀约定用于所有内部和私有成员(属性和方法)。请勿在您的代码中调用它们...它们旨在由库内部使用,在软件包成型之前,它们将保持不变,至少是最初。
由于GraphX专注于视觉效果,以下是一些我在开发和测试GraphX过程中制作的随机原型屏幕截图。




背景。
GraphX™旨在帮助您在Flutter应用程序中构建自定义绘图。提供极大的灵活性,将屏幕像素提升到新的水平。
它受到我早期编程生涯中非常有影响力的Flash API的启发,而Flash API多年来在多种语言中启发了许多其他渲染框架。
我一直在想我多么怀念“玩”代码,让事物更有机、艺术、生动……我非常喜欢Flutter,但我总觉得它需要太多的样板代码才能让东西动起来(与我过去的代码相比)。
即使GraphX™不是一个动画库(尽管它有一个小型补间引擎),也不是一个游戏引擎,它也可以帮助您构建真正出色的用户体验!它只是运行在CustomPainter之上……利用Flutter SDK通过Canvas公开的SKIA引擎,但它也提供了一个“框架”来在Widget的世界之外运行独立的代码。
可用于简单地绘制一条线、一个圆、一个自定义按钮、UI上的某些闪屏效果,甚至屏幕的一部分中的完整游戏。
您可以随意与Flutter混合搭配,因为GraphX™使用CustomPainter,它是您Widget树的一部分。
概念。
此仓库是一个非常早期的原型……该库仍然缺乏加载远程资源、2.5D转换和其他一些便利功能的支持。
但是,它对加载rootBundle资源有非常基本的支持。
AssetLoader.loadBinary(assetId)
AssetLoader.loadGif(assetId)
AssetLoader.loadTextureAtlas(imagePath, xmlPath)
AssetLoader.loadTexture(assetId)
AssetLoader.loadImage(assetId)
AssetLoader.loadString(assetId)
AssetLoader.loadJson(assetId)
GraphX™还使用StaticText类提供基本的“原始”文本渲染支持。
它是如何工作的?
GraphX™内部驱动一个CustomPainter。其理念是简化Flutter的Canvas的使用,并添加**显示列表**概念,这与Widget Tree概念非常相似;因此,您可以命令式地编写、管理和创建更复杂的“场景”。
该库拥有自己的渲染周期,使用Flutter的Ticker(与AnimationController类似),并且每个SceneWidgetBuilder都会进行自己的输入捕获和处理(鼠标、键盘、触摸)。即使它运行在Widget树上,您也可以启用标志来捕获鼠标/触摸输入或按键事件(如果您想制作一个简单的游戏或桌面/Web工具)。
示例代码。
body: Center(
child: SceneBuilderWidget( /// wrap any Widget with SceneBuilderWidget
builder: () => SceneController.withLayers(
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™基于“场景”层,每个SceneBuilderWidget都需要一个SceneController。
此控制器是场景层的“初始化器”,可以是
back(背景绘制器),front(前景绘制器),- 或两者皆是。
每个“场景层”都必须扩展SceneRoot,它代表该特定场景层级的起点。将其视为MaterialApp小部件相对于树中所有其他子小部件的作用。
在这里,我们进入了GraphX™的世界,不再是Widget Trees或不可变属性。
您可以覆盖init()来设置当前Scene Painter对象所需的项,例如它是否需要键盘/鼠标/触摸访问,或者它是否需要Ticker并重绘CustomPainter,因为它将进行动画。
覆盖ready()作为您的入口点,在这里引擎已经设置好,并且可以利用尊贵的Stage。
class GameScene extends SceneRoot {
GameScene(){
config(autoUpdateAndRender: true, usePointer: true);
}
@override
void addedToStage() {
/// if you have to stop the Ticker. Will stop all
/// Tweens, Jugglers objects in GraphX.
stage.scene.core.ticker.pause();
}
目前,GraphX™有几个用于渲染显示列表的类
Shape和Sprite(它们是DisplayObject,DisplayObjectContainer是*抽象类*),
它们都有一个graphics属性,类型为Graphics,并提供了一个简单的API来在Flutter的Canvas上进行绘制。
顺便说一句,SceneRoot本身也是一个Sprite!它是显示树中的根节点,可以说是所有渲染的起点,也是您需要添加自己对象的地方。
例如,创建一个简单的紫色圆
@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.
}
SceneRoot是一个Sprite(它是DisplayObjectContainer)并且可以包含子项,而Shape是一个DisplayObject,不能包含子项。但这使得每次画家步骤的性能略有提高。
我们也可以使用根场景来绘制东西。
@override
addedToStage(){
graphics.beginFill(0x0000ff, .6)
..drawRoundRect(100, 100, 40, 40, 4)
..endFill();
...
}
在您的SceneRoot(在您的构造函数中)进行场景设置示例
config(
autoUpdateAndRender: true,
usePointer: true,
useTicker: true,
useKeyboard: false,
sceneIsComplex: true,
);
指针信号已被“简化”为鼠标事件……因为在DisplayObject上处理单点触摸/鼠标交互非常容易。
每个元素上都有很多信号可以监听……取自AS3和JS。
- onMouseDoubleClick
- onMouseClick
- onMouseDown
- onMouseUp
- onMouseMove
- onMouseOver
- onMouseOut
- onMouseScroll
它们都发出一个MouseInputData,其中包含所有需要的信息,例如舞台坐标或翻译后的本地坐标,“鼠标”按钮是否被按下等。
我将在接下来的几天里继续添加更多解释。
演示。
一些演示仅部分使用了GraphX™,并且可能对CPU产生很大影响。
屏幕录制演示
































