drawnui-react 0.1.0-preview.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/PARITY.md +287 -0
- package/README.md +92 -0
- package/SKIPPED.md +107 -0
- package/dist/controls/AnimatedFramesRenderer.d.ts +58 -0
- package/dist/controls/AnimatedFramesRenderer.js +133 -0
- package/dist/controls/GridStructure.d.ts +79 -0
- package/dist/controls/GridStructure.js +403 -0
- package/dist/controls/RefreshIndicator.d.ts +35 -0
- package/dist/controls/RefreshIndicator.js +82 -0
- package/dist/controls/SkiaBackdrop.d.ts +25 -0
- package/dist/controls/SkiaBackdrop.js +80 -0
- package/dist/controls/SkiaButton.d.ts +58 -0
- package/dist/controls/SkiaButton.js +148 -0
- package/dist/controls/SkiaCarousel.d.ts +133 -0
- package/dist/controls/SkiaCarousel.js +603 -0
- package/dist/controls/SkiaCheckbox.d.ts +21 -0
- package/dist/controls/SkiaCheckbox.js +118 -0
- package/dist/controls/SkiaDecoratedGrid.d.ts +15 -0
- package/dist/controls/SkiaDecoratedGrid.js +46 -0
- package/dist/controls/SkiaDrawer.d.ts +46 -0
- package/dist/controls/SkiaDrawer.js +212 -0
- package/dist/controls/SkiaDynamicDrawnCell.d.ts +11 -0
- package/dist/controls/SkiaDynamicDrawnCell.js +17 -0
- package/dist/controls/SkiaEditor.d.ts +163 -0
- package/dist/controls/SkiaEditor.js +803 -0
- package/dist/controls/SkiaGif.d.ts +54 -0
- package/dist/controls/SkiaGif.js +206 -0
- package/dist/controls/SkiaHotspot.d.ts +13 -0
- package/dist/controls/SkiaHotspot.js +36 -0
- package/dist/controls/SkiaImage.d.ts +75 -0
- package/dist/controls/SkiaImage.js +222 -0
- package/dist/controls/SkiaImageTiles.d.ts +27 -0
- package/dist/controls/SkiaImageTiles.js +76 -0
- package/dist/controls/SkiaLabel.d.ts +160 -0
- package/dist/controls/SkiaLabel.js +580 -0
- package/dist/controls/SkiaLayout.d.ts +163 -0
- package/dist/controls/SkiaLayout.js +723 -0
- package/dist/controls/SkiaLottie.d.ts +75 -0
- package/dist/controls/SkiaLottie.js +290 -0
- package/dist/controls/SkiaProgress.d.ts +40 -0
- package/dist/controls/SkiaProgress.js +80 -0
- package/dist/controls/SkiaRadioButton.d.ts +32 -0
- package/dist/controls/SkiaRadioButton.js +157 -0
- package/dist/controls/SkiaRichLabel.d.ts +77 -0
- package/dist/controls/SkiaRichLabel.js +274 -0
- package/dist/controls/SkiaScroll.d.ts +231 -0
- package/dist/controls/SkiaScroll.js +958 -0
- package/dist/controls/SkiaScrollBar.d.ts +56 -0
- package/dist/controls/SkiaScrollBar.js +158 -0
- package/dist/controls/SkiaShaderCarousel.d.ts +67 -0
- package/dist/controls/SkiaShaderCarousel.js +246 -0
- package/dist/controls/SkiaShape.d.ts +63 -0
- package/dist/controls/SkiaShape.js +317 -0
- package/dist/controls/SkiaSlider.d.ts +74 -0
- package/dist/controls/SkiaSlider.js +243 -0
- package/dist/controls/SkiaSprite.d.ts +99 -0
- package/dist/controls/SkiaSprite.js +324 -0
- package/dist/controls/SkiaSpriteSet.d.ts +27 -0
- package/dist/controls/SkiaSpriteSet.js +75 -0
- package/dist/controls/SkiaSvg.d.ts +43 -0
- package/dist/controls/SkiaSvg.js +181 -0
- package/dist/controls/SkiaSwitch.d.ts +26 -0
- package/dist/controls/SkiaSwitch.js +147 -0
- package/dist/controls/SkiaToggle.d.ts +50 -0
- package/dist/controls/SkiaToggle.js +71 -0
- package/dist/controls/SnappingLayout.d.ts +78 -0
- package/dist/controls/SnappingLayout.js +217 -0
- package/dist/controls/TextSpan.d.ts +70 -0
- package/dist/controls/TextSpan.js +76 -0
- package/dist/core/Accessibility.d.ts +104 -0
- package/dist/core/Accessibility.js +150 -0
- package/dist/core/Animators.d.ts +82 -0
- package/dist/core/Animators.js +247 -0
- package/dist/core/Canvas.d.ts +89 -0
- package/dist/core/Canvas.js +328 -0
- package/dist/core/ControlStyle.d.ts +6 -0
- package/dist/core/ControlStyle.js +11 -0
- package/dist/core/Easing.d.ts +13 -0
- package/dist/core/Easing.js +15 -0
- package/dist/core/Gestures.d.ts +74 -0
- package/dist/core/Gestures.js +104 -0
- package/dist/core/ImageEffects.d.ts +29 -0
- package/dist/core/ImageEffects.js +55 -0
- package/dist/core/KeyboardManager.d.ts +25 -0
- package/dist/core/KeyboardManager.js +54 -0
- package/dist/core/ScrollAnimators.d.ts +90 -0
- package/dist/core/ScrollAnimators.js +244 -0
- package/dist/core/SkiaControl.d.ts +401 -0
- package/dist/core/SkiaControl.js +1239 -0
- package/dist/core/SkiaEffect.d.ts +216 -0
- package/dist/core/SkiaEffect.js +571 -0
- package/dist/core/SkiaImageManager.d.ts +43 -0
- package/dist/core/SkiaImageManager.js +122 -0
- package/dist/core/Super.d.ts +61 -0
- package/dist/core/Super.js +178 -0
- package/dist/core/TextInputProxy.d.ts +31 -0
- package/dist/core/TextInputProxy.js +144 -0
- package/dist/core/Types.d.ts +177 -0
- package/dist/core/Types.js +122 -0
- package/dist/core/ViewsAdapter.d.ts +41 -0
- package/dist/core/ViewsAdapter.js +113 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.js +48 -0
- package/dist/react/SkiaShell.d.ts +144 -0
- package/dist/react/SkiaShell.js +490 -0
- package/dist/react/index.d.ts +110 -0
- package/dist/react/index.js +158 -0
- package/dist/react/reconciler.d.ts +14 -0
- package/dist/react/reconciler.js +160 -0
- package/package.json +60 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { DrawingContext, SkiaControl } from "./SkiaControl";
|
|
2
|
+
import { Easing } from "./Easing";
|
|
3
|
+
import { type Color } from "./Types";
|
|
4
|
+
/** DrawnUi IOverlayEffect: drawn by the owning control after its content (PostAnimators). */
|
|
5
|
+
export interface IOverlayEffect {
|
|
6
|
+
/** Return true to request another frame (still animating). */
|
|
7
|
+
Render(context: DrawingContext, control: SkiaControl): boolean;
|
|
8
|
+
}
|
|
9
|
+
/** DrawnUi AnimatorBase: registration + running state. Time is in nanoseconds like the .NET version. */
|
|
10
|
+
export declare class AnimatorBase {
|
|
11
|
+
readonly Uid: number;
|
|
12
|
+
Parent: SkiaControl | null;
|
|
13
|
+
/** Post animators are also added to Parent.PostAnimators and drawn above its content. */
|
|
14
|
+
IsPostAnimator: boolean;
|
|
15
|
+
IsRunning: boolean;
|
|
16
|
+
WasStarted: boolean;
|
|
17
|
+
LastFrameTimeNanos: number;
|
|
18
|
+
StartFrameTimeNanos: number;
|
|
19
|
+
OnStart?: () => void;
|
|
20
|
+
OnStop?: () => void;
|
|
21
|
+
private delayHandle;
|
|
22
|
+
constructor(parent: SkiaControl);
|
|
23
|
+
protected Register(): boolean;
|
|
24
|
+
protected Unregister(): void;
|
|
25
|
+
Start(delayMs?: number): void;
|
|
26
|
+
Stop(): void;
|
|
27
|
+
/** Returns true when there is nothing more to do (not running / finished). */
|
|
28
|
+
TickFrame(frameTimeNanos: number): boolean;
|
|
29
|
+
Dispose(): void;
|
|
30
|
+
private SetRunning;
|
|
31
|
+
}
|
|
32
|
+
/** DrawnUi SkiaValueAnimator: drives mValue from mMinValue to mMaxValue over Speed ms with Easing. */
|
|
33
|
+
export declare class SkiaValueAnimator extends AnimatorBase {
|
|
34
|
+
mValue: number;
|
|
35
|
+
mMinValue: number;
|
|
36
|
+
mMaxValue: number;
|
|
37
|
+
/** Duration in ms. */
|
|
38
|
+
Speed: number;
|
|
39
|
+
Easing: Easing;
|
|
40
|
+
/** -1 = forever, n = repeat n more times. */
|
|
41
|
+
Repeat: number;
|
|
42
|
+
/** Eased progress, may exceed 1 on the finishing frame. */
|
|
43
|
+
protected Progress: number;
|
|
44
|
+
OnUpdated?: (value: number) => void;
|
|
45
|
+
Finished?: () => void;
|
|
46
|
+
TickFrame(frameTimeNanos: number): boolean;
|
|
47
|
+
/** Passed over mValue; subclasses derive their own reported value here. */
|
|
48
|
+
protected TransformReportedValue(_deltaT: number): number;
|
|
49
|
+
/** Updates mValue from elapsed time; true when the target was reached. */
|
|
50
|
+
protected UpdateValue(_deltaT: number, deltaFromStart: number): boolean;
|
|
51
|
+
protected FinishedRunning(): boolean;
|
|
52
|
+
}
|
|
53
|
+
/** DrawnUi RenderingAnimator: a value animator that paints itself above its Parent (IOverlayEffect). */
|
|
54
|
+
export declare class RenderingAnimator extends SkiaValueAnimator implements IOverlayEffect {
|
|
55
|
+
constructor(parent: SkiaControl);
|
|
56
|
+
Stop(): void;
|
|
57
|
+
/** While running, the ancestors' caches hold a frame without this effect: stale them so the parent's ExecutePostAnimators runs (C# parent invalidation). */
|
|
58
|
+
TickFrame(frameTimeNanos: number): boolean;
|
|
59
|
+
Render(context: DrawingContext, control: SkiaControl): boolean;
|
|
60
|
+
protected OnRendering(_context: DrawingContext, _control: SkiaControl): boolean;
|
|
61
|
+
/** Top-left of the control in canvas pixels (its last drawn position). */
|
|
62
|
+
protected static GetSelfDrawingLocation(control: SkiaControl): {
|
|
63
|
+
X: number;
|
|
64
|
+
Y: number;
|
|
65
|
+
};
|
|
66
|
+
/** Runs draw() clipped to the control's shape when control.ClipEffects is set. */
|
|
67
|
+
protected static DrawWithClipping(context: DrawingContext, control: SkiaControl, draw: () => void): void;
|
|
68
|
+
}
|
|
69
|
+
/** DrawnUi RippleAnimator: expanding fading circle from the touch point, 500ms CubicIn. */
|
|
70
|
+
export declare class RippleAnimator extends RenderingAnimator {
|
|
71
|
+
static DiameterDefault: number;
|
|
72
|
+
static OpacityDefault: number;
|
|
73
|
+
Color: Color;
|
|
74
|
+
/** Touch point inside the control, points. */
|
|
75
|
+
X: number;
|
|
76
|
+
Y: number;
|
|
77
|
+
Diameter: number;
|
|
78
|
+
Opacity: number;
|
|
79
|
+
constructor(control: SkiaControl);
|
|
80
|
+
protected OnRendering(context: DrawingContext, control: SkiaControl): boolean;
|
|
81
|
+
protected TransformReportedValue(deltaT: number): number;
|
|
82
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// Mirrors DrawnUi Features/Animators: AnimatorBase -> SkiaValueAnimator -> RenderingAnimator (+ RippleAnimator).
|
|
2
|
+
// Animators register with the Canvas (Superview.RegisterAnimator) and tick once per drawn frame.
|
|
3
|
+
import { Easing } from "./Easing";
|
|
4
|
+
import { Super } from "./Super";
|
|
5
|
+
import { Colors } from "./Types";
|
|
6
|
+
let uidCounter = 0;
|
|
7
|
+
/** DrawnUi AnimatorBase: registration + running state. Time is in nanoseconds like the .NET version. */
|
|
8
|
+
export class AnimatorBase {
|
|
9
|
+
Uid = ++uidCounter;
|
|
10
|
+
Parent;
|
|
11
|
+
/** Post animators are also added to Parent.PostAnimators and drawn above its content. */
|
|
12
|
+
IsPostAnimator = false;
|
|
13
|
+
IsRunning = false;
|
|
14
|
+
WasStarted = false;
|
|
15
|
+
LastFrameTimeNanos = 0;
|
|
16
|
+
StartFrameTimeNanos = 0;
|
|
17
|
+
OnStart;
|
|
18
|
+
OnStop;
|
|
19
|
+
delayHandle = 0;
|
|
20
|
+
constructor(parent) { this.Parent = parent; }
|
|
21
|
+
Register() {
|
|
22
|
+
const parent = this.Parent;
|
|
23
|
+
if (!parent)
|
|
24
|
+
return false;
|
|
25
|
+
if (this.IsPostAnimator) {
|
|
26
|
+
const effect = this;
|
|
27
|
+
if (typeof effect.Render !== "function")
|
|
28
|
+
throw new Error("Post animator must implement IOverlayEffect");
|
|
29
|
+
if (!parent.PostAnimators.includes(effect))
|
|
30
|
+
parent.PostAnimators.push(effect);
|
|
31
|
+
}
|
|
32
|
+
const ok = parent.Superview?.RegisterAnimator(this) ?? false;
|
|
33
|
+
parent.Repaint();
|
|
34
|
+
return ok;
|
|
35
|
+
}
|
|
36
|
+
Unregister() {
|
|
37
|
+
const parent = this.Parent;
|
|
38
|
+
if (!parent)
|
|
39
|
+
return;
|
|
40
|
+
if (this.IsPostAnimator) {
|
|
41
|
+
const i = parent.PostAnimators.indexOf(this);
|
|
42
|
+
if (i >= 0)
|
|
43
|
+
parent.PostAnimators.splice(i, 1);
|
|
44
|
+
}
|
|
45
|
+
parent.Superview?.UnregisterAnimator(this.Uid);
|
|
46
|
+
}
|
|
47
|
+
Start(delayMs = 0) {
|
|
48
|
+
if (this.delayHandle) {
|
|
49
|
+
clearTimeout(this.delayHandle);
|
|
50
|
+
this.delayHandle = 0;
|
|
51
|
+
}
|
|
52
|
+
if (delayMs > 0) {
|
|
53
|
+
this.delayHandle = window.setTimeout(() => { this.delayHandle = 0; this.Start(); }, delayMs);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (this.Register()) {
|
|
57
|
+
this.WasStarted = true;
|
|
58
|
+
if (!this.IsRunning) {
|
|
59
|
+
this.LastFrameTimeNanos = 0;
|
|
60
|
+
this.StartFrameTimeNanos = 0;
|
|
61
|
+
this.SetRunning(true);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
Stop() {
|
|
66
|
+
if (this.delayHandle) {
|
|
67
|
+
clearTimeout(this.delayHandle);
|
|
68
|
+
this.delayHandle = 0;
|
|
69
|
+
}
|
|
70
|
+
this.Unregister();
|
|
71
|
+
this.LastFrameTimeNanos = 0;
|
|
72
|
+
this.StartFrameTimeNanos = 0;
|
|
73
|
+
this.SetRunning(false);
|
|
74
|
+
this.WasStarted = false;
|
|
75
|
+
}
|
|
76
|
+
/** Returns true when there is nothing more to do (not running / finished). */
|
|
77
|
+
TickFrame(frameTimeNanos) {
|
|
78
|
+
if (!this.IsRunning)
|
|
79
|
+
return true;
|
|
80
|
+
this.LastFrameTimeNanos = frameTimeNanos;
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
Dispose() {
|
|
84
|
+
this.Stop();
|
|
85
|
+
this.Parent = null;
|
|
86
|
+
this.OnStart = undefined;
|
|
87
|
+
this.OnStop = undefined;
|
|
88
|
+
}
|
|
89
|
+
SetRunning(value) {
|
|
90
|
+
if (this.IsRunning === value)
|
|
91
|
+
return;
|
|
92
|
+
this.IsRunning = value;
|
|
93
|
+
if (value)
|
|
94
|
+
this.OnStart?.();
|
|
95
|
+
else
|
|
96
|
+
this.OnStop?.();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** DrawnUi SkiaValueAnimator: drives mValue from mMinValue to mMaxValue over Speed ms with Easing. */
|
|
100
|
+
export class SkiaValueAnimator extends AnimatorBase {
|
|
101
|
+
mValue = 0;
|
|
102
|
+
mMinValue = Number.MIN_SAFE_INTEGER;
|
|
103
|
+
mMaxValue = Number.MAX_SAFE_INTEGER;
|
|
104
|
+
/** Duration in ms. */
|
|
105
|
+
Speed = 0;
|
|
106
|
+
Easing = Easing.Linear;
|
|
107
|
+
/** -1 = forever, n = repeat n more times. */
|
|
108
|
+
Repeat = 0;
|
|
109
|
+
/** Eased progress, may exceed 1 on the finishing frame. */
|
|
110
|
+
Progress = 0;
|
|
111
|
+
OnUpdated;
|
|
112
|
+
Finished;
|
|
113
|
+
TickFrame(frameTimeNanos) {
|
|
114
|
+
if (!this.IsRunning)
|
|
115
|
+
return true;
|
|
116
|
+
if (this.LastFrameTimeNanos === 0) {
|
|
117
|
+
this.LastFrameTimeNanos = frameTimeNanos;
|
|
118
|
+
this.StartFrameTimeNanos = frameTimeNanos;
|
|
119
|
+
}
|
|
120
|
+
const deltaFromStart = frameTimeNanos - this.StartFrameTimeNanos;
|
|
121
|
+
const deltaNanos = frameTimeNanos - this.LastFrameTimeNanos;
|
|
122
|
+
this.LastFrameTimeNanos = frameTimeNanos;
|
|
123
|
+
let finished = this.UpdateValue(deltaNanos, deltaFromStart);
|
|
124
|
+
// Always evaluate: subclasses derive their state here (a?.(f()) would skip f() with no subscriber).
|
|
125
|
+
const reported = this.TransformReportedValue(deltaNanos);
|
|
126
|
+
this.OnUpdated?.(reported);
|
|
127
|
+
if (finished)
|
|
128
|
+
finished = this.FinishedRunning();
|
|
129
|
+
return finished;
|
|
130
|
+
}
|
|
131
|
+
/** Passed over mValue; subclasses derive their own reported value here. */
|
|
132
|
+
TransformReportedValue(_deltaT) { return this.mValue; }
|
|
133
|
+
/** Updates mValue from elapsed time; true when the target was reached. */
|
|
134
|
+
UpdateValue(_deltaT, deltaFromStart) {
|
|
135
|
+
const elapsedMs = deltaFromStart / 1_000_000;
|
|
136
|
+
const progress = this.Speed > 0 ? elapsedMs / this.Speed : 1;
|
|
137
|
+
const deltaValue = this.mMaxValue - this.mMinValue;
|
|
138
|
+
const eased = this.Easing.Ease(Math.min(progress, 1));
|
|
139
|
+
this.Progress = eased;
|
|
140
|
+
const value = deltaValue * eased + this.mMinValue;
|
|
141
|
+
if (value < this.mMinValue) {
|
|
142
|
+
this.mValue = this.mMinValue;
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
if (value >= this.mMaxValue || progress >= 1) {
|
|
146
|
+
this.mValue = this.mMaxValue;
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
this.mValue = value;
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
FinishedRunning() {
|
|
153
|
+
if (this.Repeat < 0 || this.Repeat > 0) {
|
|
154
|
+
if (this.Repeat > 0)
|
|
155
|
+
this.Repeat--;
|
|
156
|
+
this.mValue = this.mMinValue;
|
|
157
|
+
this.LastFrameTimeNanos = 0;
|
|
158
|
+
this.StartFrameTimeNanos = 0;
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
this.Stop();
|
|
162
|
+
this.Finished?.();
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/** DrawnUi RenderingAnimator: a value animator that paints itself above its Parent (IOverlayEffect). */
|
|
167
|
+
export class RenderingAnimator extends SkiaValueAnimator {
|
|
168
|
+
constructor(parent) { super(parent); }
|
|
169
|
+
Stop() {
|
|
170
|
+
const parent = this.Parent;
|
|
171
|
+
super.Stop();
|
|
172
|
+
parent?.RepaintComposition(); // ancestors re-record without the effect
|
|
173
|
+
}
|
|
174
|
+
/** While running, the ancestors' caches hold a frame without this effect: stale them so the parent's ExecutePostAnimators runs (C# parent invalidation). */
|
|
175
|
+
TickFrame(frameTimeNanos) {
|
|
176
|
+
const finished = super.TickFrame(frameTimeNanos);
|
|
177
|
+
if (this.IsRunning)
|
|
178
|
+
this.Parent?.RepaintComposition();
|
|
179
|
+
return finished;
|
|
180
|
+
}
|
|
181
|
+
Render(context, control) {
|
|
182
|
+
return this.OnRendering(context, control);
|
|
183
|
+
}
|
|
184
|
+
OnRendering(_context, _control) { return false; }
|
|
185
|
+
/** Top-left of the control in canvas pixels (its last drawn position). */
|
|
186
|
+
static GetSelfDrawingLocation(control) {
|
|
187
|
+
return { X: control.DrawingRect.Left, Y: control.DrawingRect.Top };
|
|
188
|
+
}
|
|
189
|
+
/** Runs draw() clipped to the control's shape when control.ClipEffects is set. */
|
|
190
|
+
static DrawWithClipping(context, control, draw) {
|
|
191
|
+
const canvas = context.Context.Canvas;
|
|
192
|
+
if (!control.ClipEffects) {
|
|
193
|
+
draw();
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const clip = control.CreateClip();
|
|
197
|
+
const count = canvas.save();
|
|
198
|
+
canvas.clipPath(clip, Super.CK.ClipOp.Intersect, true);
|
|
199
|
+
draw();
|
|
200
|
+
canvas.restoreToCount(count);
|
|
201
|
+
clip.delete();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/** DrawnUi RippleAnimator: expanding fading circle from the touch point, 500ms CubicIn. */
|
|
205
|
+
export class RippleAnimator extends RenderingAnimator {
|
|
206
|
+
static DiameterDefault = 300.0;
|
|
207
|
+
static OpacityDefault = 0.2;
|
|
208
|
+
Color = Colors.White;
|
|
209
|
+
/** Touch point inside the control, points. */
|
|
210
|
+
X = 0;
|
|
211
|
+
Y = 0;
|
|
212
|
+
Diameter = 0;
|
|
213
|
+
Opacity = 0;
|
|
214
|
+
constructor(control) {
|
|
215
|
+
super(control);
|
|
216
|
+
this.IsPostAnimator = true;
|
|
217
|
+
this.Speed = 500;
|
|
218
|
+
this.mMinValue = 0;
|
|
219
|
+
this.mMaxValue = 1;
|
|
220
|
+
this.Easing = Easing.CubicIn;
|
|
221
|
+
}
|
|
222
|
+
OnRendering(context, control) {
|
|
223
|
+
if (!this.IsRunning)
|
|
224
|
+
return false;
|
|
225
|
+
const loc = RenderingAnimator.GetSelfDrawingLocation(control);
|
|
226
|
+
const x = this.X * context.Scale + loc.X;
|
|
227
|
+
const y = this.Y * context.Scale + loc.Y;
|
|
228
|
+
RenderingAnimator.DrawWithClipping(context, control, () => {
|
|
229
|
+
const paint = new Super.CK.Paint();
|
|
230
|
+
paint.setAntiAlias(true);
|
|
231
|
+
const c = Super.ParseColor(this.Color);
|
|
232
|
+
paint.setColor(Super.CK.Color4f(c[0], c[1], c[2], this.Opacity));
|
|
233
|
+
// Same as the .NET RippleAnimator: Diameter is passed as the circle radius.
|
|
234
|
+
context.Context.Canvas.drawCircle(x, y, this.Diameter * context.Scale, paint);
|
|
235
|
+
paint.delete();
|
|
236
|
+
});
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
TransformReportedValue(deltaT) {
|
|
240
|
+
const progress = super.TransformReportedValue(deltaT);
|
|
241
|
+
const opacityProgress = progress * 1.15;
|
|
242
|
+
if (opacityProgress <= 1)
|
|
243
|
+
this.Opacity = RippleAnimator.OpacityDefault - RippleAnimator.OpacityDefault * opacityProgress;
|
|
244
|
+
this.Diameter = RippleAnimator.DiameterDefault * progress;
|
|
245
|
+
return progress;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { Surface } from "canvaskit-wasm";
|
|
2
|
+
import type { SkiaControl } from "./SkiaControl";
|
|
3
|
+
import type { AnimatorBase } from "./Animators";
|
|
4
|
+
import { SkiaAccessibilityManager } from "./Accessibility";
|
|
5
|
+
import { type Color, type RenderingModeType } from "./Types";
|
|
6
|
+
import { type GesturesMode, SkiaGesturesParameters, TouchActionEventArgs } from "./Gestures";
|
|
7
|
+
/**
|
|
8
|
+
* Mirrors DrawnUi Canvas (DrawnView): hosts one Content control on an HTML canvas element,
|
|
9
|
+
* owns RenderingScale (devicePixelRatio), the surface, the on-demand frame loop and raw input.
|
|
10
|
+
* Frames are drawn only after Update() (invalidation), never continuously.
|
|
11
|
+
* Gestures are accumulated and processed in order at the START of the next frame, like DrawnUi.
|
|
12
|
+
*/
|
|
13
|
+
export declare class Canvas {
|
|
14
|
+
readonly Element: HTMLCanvasElement;
|
|
15
|
+
/** Points a pointer may travel between Down and Up and still count as a tap (AppoMobi TouchEffect default). */
|
|
16
|
+
static TappedCancelMoveThresholdPoints: number;
|
|
17
|
+
BackgroundColor: Color;
|
|
18
|
+
/** Accelerated = WebGL surface, Default = software. Read once at first frame. */
|
|
19
|
+
RenderingMode: RenderingModeType;
|
|
20
|
+
RenderingScale: number;
|
|
21
|
+
/** Duration of the last Draw in ms (measure + arrange + render, excluding GPU flush). */
|
|
22
|
+
FrameTime: number;
|
|
23
|
+
/** Frames per second over the last second of drawn frames. */
|
|
24
|
+
FPS: number;
|
|
25
|
+
private frameTimes;
|
|
26
|
+
/** Registry + rate-limited snapshot of accessible controls, rendered by the DOM overlay (DrawnUi AccessibilityManager). */
|
|
27
|
+
readonly AccessibilityManager: SkiaAccessibilityManager;
|
|
28
|
+
private content?;
|
|
29
|
+
get Content(): SkiaControl | undefined;
|
|
30
|
+
set Content(value: SkiaControl | undefined);
|
|
31
|
+
private surface?;
|
|
32
|
+
/** GL context + GrContext live for the Canvas lifetime; only the on-screen surface is recreated on resize. */
|
|
33
|
+
private glHandle?;
|
|
34
|
+
private grContext?;
|
|
35
|
+
private frameId;
|
|
36
|
+
private disposed;
|
|
37
|
+
private readonly observer;
|
|
38
|
+
constructor(Element: HTMLCanvasElement);
|
|
39
|
+
/** Request a redraw (full measure + arrange + render) on the next animation frame. */
|
|
40
|
+
Update(): void;
|
|
41
|
+
/** Deletes the current surface; a pending frame on it is cancelled first (drawing on a deleted surface faults). */
|
|
42
|
+
private ReleaseSurface;
|
|
43
|
+
/** On-screen surface at the element's current pixel size, reusing the GL/GrContext when accelerated. */
|
|
44
|
+
private CreateSurface;
|
|
45
|
+
/**
|
|
46
|
+
* Resize = the browser wipes the bitmap when width/height change, so the new frame is drawn
|
|
47
|
+
* SYNCHRONOUSLY here. ResizeObserver callbacks run after layout and before paint, so the
|
|
48
|
+
* redrawn content lands in the same paint and no blank frame is ever shown while dragging.
|
|
49
|
+
*/
|
|
50
|
+
private OnResized;
|
|
51
|
+
/** Draws one frame immediately (outside the rAF loop) and presents it. */
|
|
52
|
+
private DrawNow;
|
|
53
|
+
private Draw;
|
|
54
|
+
private readonly disposeQueue;
|
|
55
|
+
/** Queues a cache for deletion after the current frame has been flushed. */
|
|
56
|
+
DisposeObject(obj: {
|
|
57
|
+
Dispose(): void;
|
|
58
|
+
}): void;
|
|
59
|
+
private DrainDisposeQueue;
|
|
60
|
+
readonly AnimatingControls: Map<number, AnimatorBase>;
|
|
61
|
+
RegisterAnimator(animator: AnimatorBase): boolean;
|
|
62
|
+
UnregisterAnimator(uid: number): void;
|
|
63
|
+
/** Ticks every registered animator once; returns how many ran. */
|
|
64
|
+
protected ExecuteAnimators(frameTimeNanos: number): number;
|
|
65
|
+
/** Frames drawn so far (SkiaBackdrop uses it to refresh once after a cached record). */
|
|
66
|
+
FrameIndex: number;
|
|
67
|
+
/** On-screen surface (SkiaBackdrop snapshots it). */
|
|
68
|
+
get Surface(): Surface | undefined;
|
|
69
|
+
Dispose(): void;
|
|
70
|
+
private gestures;
|
|
71
|
+
get Gestures(): GesturesMode;
|
|
72
|
+
set Gestures(value: GesturesMode);
|
|
73
|
+
private readonly activeTouchIds;
|
|
74
|
+
private readonly pointerDownArgs;
|
|
75
|
+
private readonly previousTouchArgs;
|
|
76
|
+
private readonly pendingGestures;
|
|
77
|
+
private readonly onPointer;
|
|
78
|
+
private readonly preventTouch;
|
|
79
|
+
/** Mouse wheel -> TouchActionResult.Wheel (page scroll suppressed while gestures are enabled). */
|
|
80
|
+
private readonly onWheel;
|
|
81
|
+
private AttachInput;
|
|
82
|
+
private DetachInput;
|
|
83
|
+
/** Port of DrawnUi.Blazor Canvas.OnTouchAction: per-pointer state machine producing Down / Panning / Tapped / Up. */
|
|
84
|
+
OnTouchAction(args: TouchActionEventArgs): void;
|
|
85
|
+
private OnGestureEvent;
|
|
86
|
+
private ProcessPendingGestures;
|
|
87
|
+
/** Entry into the control tree, same shape as DrawnUi Canvas.ProcessGestures. */
|
|
88
|
+
protected ProcessGestures(root: SkiaControl, args: SkiaGesturesParameters): SkiaControl | null;
|
|
89
|
+
}
|