跳到正文

使用 spec ​

spec 就是普通的 JSON。你可以随 App 一起打包、从网络下载,或者在代码里构建,然后交给所在平台的引擎。

实验性功能

自定义 spec 目前仍是实验性功能。在 schema 宣布稳定之前,次版本更新可能会改动它。内置加载动画不受影响。

加载 spec ​

ts
import { LoaderKitView } from '@loader-kit/web';

const json = await (await fetch('/specs/typing-dots.json')).text();
const view = new LoaderKitView(host, {
  spec: json,                 // JSON 字符串或对象
  params: { count: 4 },
  onError: (message) => message && console.warn(message),
});
html
<loader-kit id="dots"></loader-kit>
<script type="module">
  import '@loader-kit/web/element';
  const el = document.querySelector('#dots');
  el.addEventListener('loaderkit-error', (e) => e.detail.message && console.warn(e.detail.message));
  el.spec = await (await fetch('/specs/typing-dots.json')).json();
</script>
kotlin
val json = context.assets.open("typing-dots.json").bufferedReader().use { it.readText() }

loader.onError = { error -> error.errors.forEach { Log.w("Loader", it) } }
loader.setSpecJson(json)
kotlin
val spec = remember(json) { IndicatorSpec.parse(json) }   // 会抛出 InvalidIndicatorSpecException
LoaderKitIndicator(spec = spec, modifier = Modifier.size(48.dp))
swift
let url = Bundle.main.url(forResource: "typing-dots", withExtension: "json")!
let json = try String(contentsOf: url, encoding: .utf8)

loader.specJSON = json
if let error = loader.specError { print(error.problems) }
swift
let spec = try IndicatorSpec(json: json)   // 会抛出 IndicatorSpecError
LoaderKitIndicator(spec: spec).frame(width: 48, height: 48)
csharp
indicator.SpecFailed += (_, error) =>
{
    foreach (var problem in error.Errors) Debug.WriteLine(problem);
};
indicator.Spec = File.ReadAllText("typing-dots.json");

在所有平台上,自定义 spec 都优先于内置的 indicator 名称。在 Android、Windows 和 Web 上,清除 spec 就会回到 indicator 指定的动画。在 Apple 平台上,indicator、spec 和 specJSON 是同一个设置:设置 spec 会替换掉 indicator,清除 spec 后什么也不会绘制,要回到原来的动画需要重新设置 indicator。

发布前先校验 ​

每个引擎在绘制前都会按同一套规则校验 spec。尽早检查你的 spec,别让错误到达用户手里:

位置API结果
JavaScript、Node、CI@loader-kit/spec 或 @loader-kit/web 中的 validate(spec)string[],有效时为空
JavaScript@loader-kit/web 中的 prepare({ spec }, params)抛出 InvalidIndicatorError(同时检查参数和限制)
AndroidIndicatorSpec.validate(json) / IndicatorSpec.parse(json)List<String> / 抛出 InvalidIndicatorSpecException
AppleIndicatorSpec.validate(json:) / IndicatorSpec(json:)[String] / 抛出 IndicatorSpecError
WindowsIndicatorSpec.TryParse(json, out spec, out errors) / IndicatorSpec.Parse(json)bool 及错误列表 / 抛出 InvalidIndicatorSpecException
编辑器JSON Schema输入时给出提示和波浪线
浏览器Playground实时预览,列出所有问题
ts
import { validate } from '@loader-kit/spec';
import spec from './typing-dots.json' with { type: 'json' };

const problems = validate(spec);
if (problems.length > 0) throw new Error(problems.join('\n'));

错误 ​

错误信息会带上字段路径,方便你快速定位:

text
schemaVersion must be 1
duration must be a positive number
layout.count uses unknown param "cout"
tracks[0].values must have the same length as keyTimes
tracks[1].keyTimes must be non-decreasing
tracks[0].property "strokeEnd" needs a ring shape
parts[1].shape.sweep must be within (0, 2π]
tracks[0].easing needs one entry per segment (2)
the spec needs at least one track or group track

视图遇到有问题的 spec 永远不会崩溃,而是什么都不画,并报告错误:

平台错误报告
WebspecError、onError 选项、loaderkit-error 事件
Android ViewonError(未设置时写入日志)
Compose在调用可组合项之前,IndicatorSpec.parse 就会抛出异常。如果 spec 因参数而变得无效,会输出一条警告日志
ApplespecError(IndicatorSpecError.problems)
WindowsSpecError 和 SpecFailed 事件

有些问题只有在用用户的参数准备 spec 时才能发现,validate() 发现不了:

  • stagger 数组或 durations 比元素个数短;
  • 下面的限制。

限制 ​

为了让绘制量有上限,引擎在准备 spec 时,会拒绝满足以下任一条件的 spec:

  • 元素总数超过 10,000 个;
  • 圆环弧段总数超过 10,000 段(对所有使用 ring 形状的部件,累加元素个数 × segments)。

向前兼容 ​

引擎会忽略不认识的字段,因此 schema 版本 1 的后续修订可以增加可选字段。JSON Schema 更严格:它会标出未知字段,因为在手写的 spec 里,这类字段通常是拼写错误。

播放控制依然适用 ​

自定义 spec 和内置动画使用同样的播放设置:速度、启动和停止、cycleProgress 以及减弱动态效果。修改 spec 或其参数会让动画重新开始。

基于 MIT 许可证发布。