Skip to content

Instantly share code, notes, and snippets.

@ykmnkmi
Last active January 5, 2024 12:11
Show Gist options
  • Save ykmnkmi/f8f7cfc4ef746397fd4e7251a9e133b9 to your computer and use it in GitHub Desktop.
Save ykmnkmi/f8f7cfc4ef746397fd4e7251a9e133b9 to your computer and use it in GitHub Desktop.
FabricJS and AngularDart.
import 'dart:html';
import 'package:js/js.dart';
import 'package:ngdart/angular.dart';
import 'main.template.dart' as ng;
@JS('fabric.IEvent')
@staticInterop
abstract interface class IEvent<T extends Event> {}
extension<T extends Event> on IEvent<T> {
external T get e;
}
typedef IEventCallback<T extends Event> = void Function(IEvent<T> iEvent);
@JS('fabric.Object')
@staticInterop
abstract interface class Fabric {}
extension on Fabric {
external num getScaledWidth();
external num getScaledHeight();
}
@JS()
@anonymous
final class RectOptions {
external factory RectOptions({
num? top,
num? left,
num? width,
num? height,
String? fill,
});
}
@JS('fabric.Rect')
@staticInterop
final class Rect implements Fabric {
external factory Rect([RectOptions? options]);
}
extension on Rect {}
@JS('fabric.Canvas')
@staticInterop
final class Canvas {
external factory Canvas(CanvasElement canvasElement);
}
extension on Canvas {
external void add(Fabric object);
external Fabric getActiveObject();
external void on<T extends Event>(String event, IEventCallback<T> callback);
external void dispose();
}
void onSelectObject(IEvent<MouseEvent> iEvent) {
print(iEvent.e.client);
}
void onMouseWheel(IEvent<Event> iEvent) {
print(iEvent.e);
}
void main() {
runApp<App>(ng.AppNgFactory);
}
@Component(
selector: 'app',
template: '<canvas #canvas width="300" height="300"></canvas>',
)
class App implements AfterViewInit, OnDestroy {
App(this.zone, this.nativeElement) {
zone.onEventDone.listen(print); // prints null on check
}
final NgZone zone;
final Element nativeElement;
Canvas? canvas;
Rect? stage;
Size currentSize = Size(300, 300);
@ViewChild('canvas')
CanvasElement? canvasElement;
void onSelectObject(IEvent<MouseEvent> event) {
print('select');
var active = canvas!.getActiveObject();
currentSize.width = active.getScaledWidth();
currentSize.height = active.getScaledHeight();
}
void onUnSelectObject(IEvent<MouseEvent> event) {
print('unselect');
var stage = this.stage!;
currentSize.width = stage.getScaledWidth();
currentSize.height = stage.getScaledHeight();
}
void Function(T) wrap<T>(void Function(T) handler) {
return (T event) {
zone.run(() {
handler(event);
});
};
}
@override
void ngAfterViewInit() {
var canvas = Canvas(canvasElement!);
var stage = Rect(RectOptions(
top: 100,
left: 100,
width: 60,
height: 70,
fill: 'red',
));
canvas.add(stage);
canvas
..on('selection:created', allowInterop(wrap(onSelectObject)))
..on('selection:updated', allowInterop(wrap(onSelectObject)))
..on('selection:cleared', allowInterop(wrap(onUnSelectObject)));
this.canvas = canvas;
this.stage = stage;
}
@override
void ngOnDestroy() {
canvas?.dispose();
}
}
final class Size {
Size(this.width, this.height);
num width;
num height;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment