Skip to content

Instantly share code, notes, and snippets.

@GZGavinZhao
Created January 3, 2024 21:36
Show Gist options
  • Save GZGavinZhao/41fec2dbc61c20140438f80d141d9fe3 to your computer and use it in GitHub Desktop.
Save GZGavinZhao/41fec2dbc61c20140438f80d141d9fe3 to your computer and use it in GitHub Desktop.
angular#69
import 'dart:async';
import 'dart:html' as html;
import 'dart:js_util';
import 'dart:math';
import 'package:js/js.dart';
import 'package:ngdart/angular.dart';
import 'package:rava_frontend/src/shared/directives/value_accessors/custom_form_directives.dart';
// ignore: unused_import
import 'package:rava_frontend/src/shared/js_interop/bootstrap_interop.dart';
import 'package:rava_frontend/src/shared/js_interop/fabric_interop.dart';
import 'package:rava_frontend/src/shared/utils/flatcolor.dart';
class CustomSize {
num width;
num height;
CustomSize({required this.width, required this.height});
}
@JSExport()
@Component(
selector: 'cracha-editor-comp',
templateUrl: 'cracha_editor_page.html',
styleUrls: ['cracha_editor_page.css'],
directives: [
routerDirectives,
formDirectives,
//customFormDirectives,
],
)
class CrachaEditorPage
implements OnInit, AfterContentInit, AfterViewInit, OnDestroy {
@ViewChild('sidebar')
html.HtmlElement? sidebarElement;
// ignore: unused_field
final ChangeDetectorRef _changeDetectorRef;
@ViewChild('viewport')
html.DivElement? viewport;
@ViewChild('viewportInner')
html.DivElement? viewportInner;
@ViewChild('canvasEl')
html.CanvasElement? canvasEl;
final html.Element nativeElement;
late Canvas canvas;
Rect? stage;
/// tamanho da area de desenho (Prancheta)
// double currentWidth = 637;
// double currentHeight = 1012;
final CustomSize currentSize = CustomSize(width: 637, height: 1012);
late JSCrachaEditorPage selfjs;
CrachaEditorPage(this.nativeElement, this._changeDetectorRef)
{
selfjs = createDartExport(this) as JSCrachaEditorPage;
}
StreamSubscription? ssOnResize;
@override
void ngOnInit() {
ssOnResize = html.window.onResize.listen(onResize);
}
@override
void ngAfterContentInit() {}
@override
void ngAfterViewInit() async {
//https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements
//canvasEl.width = nativeElement.
//html.window.getComputedStyleMap();
await Future.delayed(Duration(milliseconds: 20));
// final comStyle = viewportInner!.getComputedStyle();
// print('height: ${comStyle.height}');
// print('width: ${comStyle.width}');
// final rect = viewportInner!.getBoundingClientRect();
// print('height: ${rect.height}');
// print('width: ${rect.width}');
// var width = viewportInner!.offsetWidth;
// var height = viewportInner!.offsetHeight;
setElementCanvasSize();
initFabric();
}
void onResize(e) {
// setCanvasSize();
}
void updateSize() {
final activeObj = canvas.getActiveObject();
// print('updateSize ${activeObj == null}');
// consoleLog(activeObj);
// print(activeObj);
if (activeObj == null) {
stage?.set('width', currentSize.width);
stage?.set('height', currentSize.height);
} else {
activeObj.set('width', currentSize.width);
activeObj.set('height', currentSize.height);
}
canvas.renderAll();
}
void setElementCanvasSize() {
final ele = viewportInner!;
// print('clientHeight: ${ele.clientHeight}');
// print('clientWidth: ${ele.clientWidth}');
canvasEl!.height = ele.clientHeight;
canvasEl!.width = ele.clientWidth;
}
void initFabric() {
canvas = Canvas(canvasEl);
stage = Rect(
jsify({
'left': (canvas.width / 2) -
((currentSize.width * (stage?.scaleX ?? 1)) / 2),
'top': 50,
'width': currentSize.width,
'height': currentSize.height,
'fill': '#fff',
'lockMovementY': true,
'lockMovementX': true,
'selectable': false,
'hoverCursor': 'default',
}),
);
canvas.add(stage);
num zoom = 1;
canvas.on('mouse:wheel', allowInterop((opt) {
final deltaY = opt.e.deltaY;
//var deltaX = opt.e.deltaX;
final mousePoint = canvas.getPointer(opt.e, true);
zoom = canvas.getZoom();
zoom *= pow(0.999, deltaY);
if (zoom > 20) zoom = 20;
if (zoom < 0.01) zoom = 0.01;
//min(max(zoom + (deltaY/150), .5), 6)
//canvas.setZoom(zoom);
canvas.zoomToPoint(Point(mousePoint.x, mousePoint.y), zoom);
opt.e.preventDefault();
opt.e.stopPropagation();
}));
// canvas.on('selection:created', allowInterop((obj) {
// onSelectObject(obj);
// }));
canvas.on('selection:created', selfjs.onSelectObject);
// canvas.on('selection:updated', allowInterop((obj) {
// onSelectObject(obj);
// }));
canvas.on('selection:updated', selfjs.onSelectObject);
// canvas.on('selection:cleared', allowInterop((event) {
// //change detection doesn't work
// onUnSelectObject(event);
// }));
canvas.on('selection:cleared', selfjs.onUnSelectObject);
}
void onUnSelectObject(event) {
//change current width of stage (valid drawing area)
currentSize.width = stage!.getScaledWidth().toDouble();
currentSize.height = stage!.getScaledHeight().toDouble();
// _changeDetectorRef.detectChanges();
}
void onSelectObject(event) {
final activeObj = canvas.getActiveObject();
final scaledWidth = activeObj.getScaledWidth();
final scaledHeight = activeObj.getScaledHeight();
currentSize.width = scaledWidth;
currentSize.height = scaledHeight;
// _changeDetectorRef.detectChanges();
}
void addObject(String name) {
switch (name) {
case 'rect':
var rect = Rect(
jsify({
'left': (canvas.width / 2) - ((100 * (1)) / 2),
'top': 50,
'width': 100,
'height': 100,
'fill': FlatColor().generateHex2(),
}),
);
canvas.add(rect);
break;
default:
}
}
//https://www.riodasostras.rj.gov.br/cdn/Vendor/limitless/4.0/bs5/template/html/layout_1/full/assets/js/app.js
// Toggle component sidebar
void sidebarComponentToggle(e) {
e.preventDefault();
sidebarElement?.classes.toggle('sidebar-mobile-expanded');
}
@override
void ngOnDestroy() {
ssOnResize?.cancel();
}
}
@JS()
@staticInterop
class JSCrachaEditorPage {}
extension on JSCrachaEditorPage {
external void onUnSelectObject(event);
external void onSelectObject(event);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment