diff --git a/package-lock.json b/package-lock.json index 88d18ebe10901678d3378268c909c2fe1ed49fa9..a46a31752f5e7bc92ee49d8eb47cf8ed07c523e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "medsurf-draw", - "version": "1.0.15", + "version": "1.0.18", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -821,6 +821,15 @@ "@types/node": "12.12.14" } }, + "@types/jquery": { + "version": "3.3.31", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.31.tgz", + "integrity": "sha512-Lz4BAJihoFw5nRzKvg4nawXPzutkv7wmfQ5121avptaSIXlDNJCUuxZxX/G+9EVidZGuO0UBlk+YjKbwRKJigg==", + "dev": true, + "requires": { + "@types/sizzle": "2.3.2" + } + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -833,6 +842,12 @@ "integrity": "sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA==", "dev": true }, + "@types/sizzle": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", + "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==", + "dev": true + }, "@types/webfontloader": { "version": "1.6.29", "resolved": "https://registry.npmjs.org/@types/webfontloader/-/webfontloader-1.6.29.tgz", @@ -5179,6 +5194,11 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, + "jquery": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz", + "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -7641,6 +7661,11 @@ } } }, + "spectrum-colorpicker": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/spectrum-colorpicker/-/spectrum-colorpicker-1.8.0.tgz", + "integrity": "sha1-uSbPUALAp3hgtfg1HhwJPGUgAQc=" + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", diff --git a/package.json b/package.json index fc11492714df275536fa6087ded6a34f16e4bd81..2c61a6ed103d9cb10bdd20ac04b96382549ee8f5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "medsurf-draw", - "version": "1.0.15", + "version": "1.0.18", "description": "Draw annotations on jpg/zoomify images, based on PIXI.js", "keywords": [ "draw", @@ -29,13 +29,16 @@ "@ascii-dev-user/medsurf-lib": "file:/srv/data/unibe/medsurf-shared/dist/medsurf-lib", "@babel/core": "^7.8.3", "debounce": "^1.2.0", + "jquery": "^3.4.1", "pixi.js-keyboard": "^1.0.9", "pixi.js-legacy": "^5.2.0", + "spectrum-colorpicker": "^1.8.0", "uuid": "^3.3.3", "webfontloader": "^1.6.28" }, "devDependencies": { "@types/debounce": "^1.2.0", + "@types/jquery": "^3.3.31", "@types/webfontloader": "^1.6.29", "babel-loader": "^8.0.6", "html-webpack-plugin": "^3.2.0", diff --git a/src/app/index.ts b/src/app/index.ts index 53f87fb58b11303df99c8c9c64ec3909a74e8c64..21ab16eaa5aaf0d7b58e5f69719918a268e43d9a 100644 --- a/src/app/index.ts +++ b/src/app/index.ts @@ -1,6 +1,7 @@ import * as PIXI from "pixi.js-legacy"; import * as Models from '@ascii-dev-user/medsurf-lib/models'; import * as Keyboard from "pixi.js-keyboard"; +import * as $ from "jquery"; import {MedsurfTileSprite} from "../lib/elements/images/MedsurfTileSprite"; import {PositionPoint} from "../lib/elements/positionings/PositionPoint"; import {RectanglePrimitive} from "../lib/elements/primitives/RectanglePrimitive"; @@ -12,6 +13,7 @@ import {ImageNavigatorElement} from "../lib/elements/interactions/ImageNavigator import {FillCollection} from "../lib/elements/collections/FillCollection"; import {LegendCollection} from "../lib/elements/collections/LegendCollection"; import {MedsurfSprite} from "../lib"; +require("spectrum-colorpicker"); const canvas = document.getElementById("medsurf_canvas") as HTMLCanvasElement; const width = canvas.width; @@ -67,6 +69,41 @@ PIXI.Renderer.registerPlugin('bla', bla); loader.add("cursor_scale", "./assets/cursors/scale.png"); loader.add("cursor_select", "./assets/cursors/select.png"); loader.load((loader: PIXI.Loader, resources: any) => { + // Color picker + $("#color_picker").spectrum({ + preferredFormat: "hex", + allowEmpty: true, + hideAfterPaletteSelect: true, + showAlpha: true, + showButtons: false, + showPalette: true, + palette: [ + ["#000000", "#ffffff", "#9B9B9B", "#A00057"], + ["#FA0202", "#D56038", "#F39200", "#A6CA5E"], + ["#357E32", "#169995", "#1F89CD", "#210B8A"], + ["#6E6EBE"], + ], + replacerClassName: 'color_picker', + showInitial: true, + localStorageKey: "spectrum.draw" + }); + $("#text_picker").spectrum({ + preferredFormat: "hex", + hideAfterPaletteSelect: true, + showButtons: false, + showPalette: true, + palette: [ + ["#000000", "#ffffff", "#9B9B9B", "#A00057"], + ["#FA0202", "#D56038", "#F39200", "#A6CA5E"], + ["#357E32", "#169995", "#1F89CD", "#210B8A"], + ["#6E6EBE"], + ], + replacerClassName: 'color_picker', + showInitial: true, + localStorageKey: "spectrum.draw" + }); + + // App const app = new PIXI.Application({ width: width, height: height, view: canvas }); app.ticker.add(async (delta: number) => { // @ts-ignore @@ -300,7 +337,7 @@ PIXI.Renderer.registerPlugin('bla', bla); 20 / imageWidth, 20 / imageWidth ), - strokeWidth: 1, + strokeWidth: 1 / imageWidth, options: { hasLine: false, hasFill: true, @@ -334,11 +371,13 @@ PIXI.Renderer.registerPlugin('bla', bla); 20 / imageWidth, 20 / imageWidth ), - strokeWidth: 1, + strokeWidth: 1 / imageWidth, options: { - hasLine: false, + hasLine: true, + lineColor: 0x000000, hasFill: true, fillColor: 0x00FF00, + fillAlpha: 0.6 } }, imageWidth); point2.addChild(rect); @@ -368,7 +407,7 @@ PIXI.Renderer.registerPlugin('bla', bla); 10 / imageWidth, 10 / imageWidth ), - strokeWidth: 1, + strokeWidth: 1 / imageWidth, options: { hasLine: false, hasFill: true, diff --git a/src/lib/elements/collections/FillCollection.ts b/src/lib/elements/collections/FillCollection.ts index f3f019539f273ca7992ecf5b24823ae3b9e66299..65aa31fa3ed24602bcc9e8f28f4a6ade6ad462d8 100644 --- a/src/lib/elements/collections/FillCollection.ts +++ b/src/lib/elements/collections/FillCollection.ts @@ -100,10 +100,10 @@ export class FillCollection extends BaseElementContainer<Models.FillCollection> this.interactiveItems = []; this.lines = []; this._fillColor = this.model.options.fillColor; + this._fillAlpha = this.model.options.fillAlpha; /* TODO remove this.isInteractive = false; this._color = model.options ? model.options.fillColor || 0xFFFFFF : 0xFFFFFF; - this._fillAlpha = this._fillAlphaNormal; */ // Events @@ -147,7 +147,7 @@ export class FillCollection extends BaseElementContainer<Models.FillCollection> this._configurationElement = new ConfigurationElement(this.modeInteraction); // Configurations - this._colorPicker = new ColorElement(this.model.options.fillColor); + this._colorPicker = new ColorElement(this.model.options.fillColor, this.model.options.fillAlpha); this._colorPicker.on("color", this._onColor, this); this._configurationElement.addChild(this._colorPicker); @@ -825,8 +825,15 @@ export class FillCollection extends BaseElementContainer<Models.FillCollection> //</editor-fold> //<editor-fold desc="Configurations"> - protected _onColor(color: number): void { + protected _onColor(hasFill: boolean, color: number, alpha: number): void { + this.model.options.hasFill = hasFill; + this.model.options.fillColor = color; + this._fillColor = this.model.options.fillColor; + + this.model.options.fillAlpha = alpha; + this._fillAlpha = this.model.options.fillAlpha; + this.draw(); } diff --git a/src/lib/elements/connections/Line.ts b/src/lib/elements/connections/Line.ts index 7a0c7a92f7a4928689167f30b92c33992e8a3a87..a7ef04c6f64b2d5f543231b04779cef919d3cc16 100644 --- a/src/lib/elements/connections/Line.ts +++ b/src/lib/elements/connections/Line.ts @@ -47,9 +47,9 @@ export class Line extends BaseElementContainer<Models.Line> { * Members */ private _graphicLine: GraphicLine; + protected _strokeWidth: number; protected _lineColor: number; protected _lineAlpha: number; - protected _strokeWidth: number; /** * Interactions @@ -77,6 +77,7 @@ export class Line extends BaseElementContainer<Models.Line> { * Design */ protected readonly _strokeWidthDefault: number = 2; + protected readonly _lineAlphaDefault: number = 1; protected readonly _lineColorDefault: number = 0xFFFFFF; protected readonly _lineColorSelected: number = 0x4a90e2; @@ -101,17 +102,14 @@ export class Line extends BaseElementContainer<Models.Line> { // Defaults if (!this.model.options) { this.model.options = { - hasLine: false, + hasLine: true, hasFill: false, }; } if (!this.model.options.lineColor) { - this.model.options.hasFill = true; this.model.options.lineColor = this._lineColorDefault; } if (!this.model.options.lineAlpha) { - this.model.options.hasFill = true; - this.model.options.lineColor = this._lineColorDefault; this.model.options.lineAlpha = this._lineAlphaDefault; } @@ -125,9 +123,9 @@ export class Line extends BaseElementContainer<Models.Line> { controlStart: null, controlEnd: null, }; + this._strokeWidth = this.model.strokeWidth * this.imageWidth; this._lineColor = this.model.options.lineColor; this._lineAlpha = this.model.options.lineAlpha; - this._strokeWidth = this.model.strokeWidth * this.imageWidth; /* TODO remove // this._start = start; @@ -183,7 +181,7 @@ export class Line extends BaseElementContainer<Models.Line> { this._configurationElement = new ConfigurationElement(this.modeInteraction); // Configurations - this._colorPicker = new ColorElement(this.model.options.lineColor); + this._colorPicker = new ColorElement(this.model.options.lineColor, this.model.options.lineAlpha); this._colorPicker.on("color", this._onColor, this); this._configurationElement.addChild(this._colorPicker); @@ -290,7 +288,13 @@ export class Line extends BaseElementContainer<Models.Line> { if (startLines.length == 0 && endLines.length == 0) { // No matching control points - this._lineElement.lineStyle(this._strokeWidth, this._lineColor, this._lineAlpha); + if (this.model.options.hasLine) { + this._lineElement.lineStyle(this._strokeWidth, this._lineColor, this._lineAlpha); + } + /* TODO + if (this.model.options.hasFill) { + } + */ this._lineElement.moveTo(this.graphicLine.start.x, this.graphicLine.start.y); this._lineElement.lineTo(this.graphicLine.end.x, this.graphicLine.end.y); } @@ -1100,8 +1104,10 @@ export class Line extends BaseElementContainer<Models.Line> { //</editor-fold> //<editor-fold desc="Configurations"> - protected _onColor(color: number): void { + protected _onColor(hasLine: boolean, color: number, alpha: number): void { + this.model.options.hasLine = hasLine; this.model.options.lineColor = color; + this.model.options.lineAlpha = alpha; this.draw(); } diff --git a/src/lib/elements/inputs/ColorElement.ts b/src/lib/elements/inputs/ColorElement.ts index 5512e687fd0ce0f29cbcd32f7aab4a52f94197e3..4948e2a15f63da866c2e32434d95f529c8e6ae9a 100644 --- a/src/lib/elements/inputs/ColorElement.ts +++ b/src/lib/elements/inputs/ColorElement.ts @@ -1,6 +1,8 @@ import * as PIXI from "pixi.js-legacy"; +import * as $ from 'jquery'; import {BaseContainer} from "../../bases/BaseModul"; import {ConfigurationElement} from "../interactions/ConfigurationElement"; +require("spectrum-colorpicker"); /** * Color element @@ -9,8 +11,15 @@ export class ColorElement extends BaseContainer { /** * Members */ - protected _color: number; - protected _onChangeFunc: any; + protected _color: number | undefined; + protected _alpha: number; + + /** + * Methods + */ + protected _onMoveFunc: any; + protected _onHideFunc: any; + /** * Elements @@ -21,7 +30,6 @@ export class ColorElement extends BaseContainer { * Environment */ protected _colorPicker: HTMLInputElement; - protected readonly _colorPickerId: string = "color_picker"; /** * Design @@ -29,21 +37,28 @@ export class ColorElement extends BaseContainer { protected readonly _lineWidth: number = 1; protected readonly _lineColor: number = 0x4a90e2; protected readonly _lineAlpha: number = 1; - protected readonly _fillAlpha: number = 1; /** * Constructor + * @param color + * @param alpha + * @param colorPickerId */ - public constructor(color: number) { + public constructor(color: number | undefined, alpha: number = 1, colorPickerId: string = "color_picker") { super(); // Setup this.zIndex = 500; this._color = color; - this._onChangeFunc = this._onChange.bind(this); + this._alpha = alpha; + + // Func + this._onMoveFunc = this._onMove.bind(this); + this._onHideFunc = this._onHide.bind(this); // Environment - this._colorPicker = document.getElementById(this._colorPickerId) as HTMLInputElement; + // @ts-ignore + this._colorPicker = $("#" + colorPickerId); // Elements this._colorPickerElement = new PIXI.Graphics(); @@ -60,13 +75,20 @@ export class ColorElement extends BaseContainer { public draw(): void { this._colorPickerElement.clear(); this._colorPickerElement.lineStyle(this._lineWidth, this._lineColor, this._lineAlpha); - this._colorPickerElement.beginFill(this._color, this._fillAlpha); + if (this._color !== undefined) { + this._colorPickerElement.beginFill(this._color, this._alpha); + } else { + this._colorPickerElement.beginFill(this._color, 0.00000001); + } this._colorPickerElement.drawRect(0, 0, 10, 10); this._colorPickerElement.endFill(); } public destroy(options?: { children?: boolean; texture?: boolean; baseTexture?: boolean }): void { - this._colorPicker.removeEventListener("change", this._onChangeFunc, true); + // @ts-ignore + this._colorPicker.off("move.spectrum", this._onMoveFunc); + // @ts-ignore + this._colorPicker.off("hide.spectrum", this._onHideFunc); this._colorPickerElement.off("pointerdown", this._onPointerDown, this); this._colorPickerElement.off("pointerup", this._onPointerUp, this); @@ -83,17 +105,65 @@ export class ColorElement extends BaseContainer { event.stopPropagation(); if (this._colorPicker) { - this._colorPicker.value = "#" + this._color.toString(16); - this._colorPicker.addEventListener("change", this._onChangeFunc, true); - this._colorPicker.click(); + if (this._color !== undefined) { + // @ts-ignore + this._colorPicker.spectrum("set", "#" + ("000000" + this._color.toString(16)).substr(-6)); + } else { + // @ts-ignore + this._colorPicker.spectrum("set", null); + } + if (this._alpha && this._color !== undefined) { + // @ts-ignore + const color = this._colorPicker.spectrum("get"); + color.setAlpha(this._alpha); + // @ts-ignore + this._colorPicker.spectrum("set", color); + } + + // Events + // @ts-ignore + this._colorPicker.on("move.spectrum", this._onMoveFunc); + // @ts-ignore + this._colorPicker.on('hide.spectrum', this._onHideFunc); + + // OR create an show listener and prevent default + setTimeout(() => { + // @ts-ignore + this._colorPicker.spectrum("show"); + }, 100); } } - protected _onChange(): void { - this._colorPicker.removeEventListener("change", this._onChangeFunc, true); - this._color = parseInt(this._colorPicker.value.substr(1, 6), 16); + protected _onMove(event: any, color: any): void { + if (color === null || color === undefined) { + this._color = undefined; + this._alpha = 0; + this.emit("color", false, this._color, this._alpha); + } else { + this._color = parseInt(color.toHexString().substr(1, 6), 16); + this._alpha = color.getAlpha(); + this.emit("color", true, this._color, this._alpha); + } + this.draw(); + } + + protected _onHide(event: any, color: any): void { + // Events + // @ts-ignore + this._colorPicker.off("move.spectrum", this._onMoveFunc); + // @ts-ignore + this._colorPicker.off("hide.spectrum", this._onHideFunc); + + if (color === null || color === undefined) { + this._color = undefined; + this._alpha = 0; + this.emit("color", false, this._color, this._alpha); + } else { + this._color = parseInt(color.toHexString().substr(1, 6), 16); + this._alpha = color._a; + this.emit("color", true, this._color, this._alpha); + } this.draw(); - this.emit("color", this._color); } //</editor-fold> diff --git a/src/lib/elements/primitives/ArrowPrimitive.ts b/src/lib/elements/primitives/ArrowPrimitive.ts index f99a6cf66294fa14068dcf1eaf35e4cdc8c243e5..9153e254ac7652c92acedf11ef2e34980b35c272 100644 --- a/src/lib/elements/primitives/ArrowPrimitive.ts +++ b/src/lib/elements/primitives/ArrowPrimitive.ts @@ -27,15 +27,17 @@ import {PointElement} from "../interactions/PointElement"; /** * Arrow primitive * TODO configurationElement -> better positioning when rotate - * TODO hasLine and hasFill */ export class ArrowPrimitive extends BaseElementContainer<Models.ArrowPrimitive> { /** * Members */ protected _rectangle: PIXI.Rectangle; - protected _fillColor: number; protected _strokeWidth: number; + protected _lineColor: number | undefined; + protected _lineAlpha: number | undefined; + protected _fillColor: number | undefined; + protected _fillAlpha: number | undefined; /** * Interactions @@ -59,7 +61,8 @@ export class ArrowPrimitive extends BaseElementContainer<Models.ArrowPrimitive> /** * Configurations */ - protected _colorPicker: ColorElement; + protected _lineColorPicker: ColorElement; + protected _fillColorPicker: ColorElement; protected _staticButton: ButtonElement; protected _selftestButton: ButtonElement; protected _selftestChooseButton: ButtonElement; @@ -70,6 +73,15 @@ export class ArrowPrimitive extends BaseElementContainer<Models.ArrowPrimitive> * Design */ protected readonly _strokeWidthDefault: number = 2; + + protected readonly _hasLineDefault: boolean = true; + protected readonly _lineAlphaDefault: number = 1; + protected readonly _lineColorDefault: number = 0x000000; + protected readonly _lineColorSelftest: number = 0xFFC67B; + protected readonly _lineColorSelftestSelected: number = 0x4ae29c; + protected readonly _lineColorSelftestUnselected: number = 0xF02C6B; + + protected readonly _hasFillDefault: boolean = false; protected readonly _fillAlphaDefault: number = 1; protected readonly _fillColorDefault: number = 0xFFFFFF; protected readonly _fillColorSelftest: number = 0xFFC67B; @@ -90,31 +102,35 @@ export class ArrowPrimitive extends BaseElementContainer<Models.ArrowPrimitive> } if (!this.model.options) { this.model.options = { - hasLine: false, - hasFill: false, + hasLine: this._hasLineDefault, + hasFill: this._hasFillDefault, }; } - if (!this.model.options.fillColor) { - this.model.options.hasFill = true; - this.model.options.fillColor = this._fillColorDefault; + if (this.model.options.hasLine && !this.model.options.lineColor) { + this.model.options.lineColor = this._lineColorDefault; } - if (!this.model.options.fillAlpha) { - this.model.options.hasFill = true; - this.model.options.fillColor = this._fillColorDefault; - this.model.options.fillAlpha = this._fillAlphaDefault; + if (this.model.options.hasLine && !this.model.options.lineAlpha) { + this.model.options.fillAlpha = this._lineAlphaDefault; } // Setup this.zIndex = 300; // TODO how to implement moveToFront etc... + this._rectangle = new PIXI.Rectangle( 0, 0, this.model.rectangle.width * this.imageWidth, this.model.rectangle.height * this.imageWidth ); - this._fillColor = this.model.options.fillColor; + this._strokeWidth = this.model.strokeWidth * this.imageWidth; + this._lineColor = this.model.options.lineColor; + this._lineAlpha = this.model.options.lineAlpha; + + this._fillColor = this.model.options.fillColor; + this._fillAlpha = this.model.options.fillAlpha; + // Position this.position.set( this.model.rectangle.x * this.imageWidth, @@ -191,9 +207,14 @@ export class ArrowPrimitive extends BaseElementContainer<Models.ArrowPrimitive> this._rotateMeasureElement = new RotateMeasureElement(this.rotateInteraction); // Configurations - this._colorPicker = new ColorElement(this.model.options.fillColor); - this._colorPicker.on("color", this._onColor, this); - this._configurationElement.addChild(this._colorPicker); + this._lineColorPicker = new ColorElement(this.model.options.lineColor, this.model.options.lineAlpha); + this._lineColorPicker.on("color", this._onLineColor, this); + this._configurationElement.addChild(this._lineColorPicker); + + // TODO how to handle empty stuff + this._fillColorPicker = new ColorElement(this.model.options.fillColor, this.model.options.fillAlpha); + this._fillColorPicker.on("color", this._onFillColor, this); + this._configurationElement.addChild(this._fillColorPicker); this._staticButton = new ButtonElement(this.model.isStatic ? "\uf3c1" : "\uf023"); this._staticButton.on("button", this._onStaticButton, this); @@ -269,8 +290,11 @@ export class ArrowPrimitive extends BaseElementContainer<Models.ArrowPrimitive> //<editor-fold desc="Public functions"> public draw(): void { this._arrowElement.clear(); - if (this._fillColor) { - this._arrowElement.beginFill(this._fillColor); + if (this.model.options.hasLine) { + this._arrowElement.lineStyle(this._strokeWidth, this._lineColor, this._lineAlpha); + } + if (this.model.options.hasFill) { + this._arrowElement.beginFill(this._fillColor, this._fillAlpha); } this._arrowElement.moveTo(this._rectangle.x, this._rectangle.y + this._rectangle.height / 2); this._arrowElement.lineTo(this._rectangle.x + this._rectangle.width, this._rectangle.y); @@ -280,7 +304,14 @@ export class ArrowPrimitive extends BaseElementContainer<Models.ArrowPrimitive> this._arrowElement.endFill(); // @ts-ignore - this._arrowElement.hitArea = new PIXI.Polygon(this._arrowElement.geometry.points); + // this._arrowElement.hitArea = new PIXI.Polygon(this._arrowElement.geometry.points); + this._arrowElement.hitArea = new PIXI.Polygon([ + new PIXI.Point(this._rectangle.x, this._rectangle.y + this._rectangle.height / 2), + new PIXI.Point(this._rectangle.x + this._rectangle.width, this._rectangle.y), + new PIXI.Point(this._wedgePointElement.position.x, this._wedgePointElement.position.y), + new PIXI.Point(this._rectangle.x + this._rectangle.width, this._rectangle.y + this._rectangle.height), + new PIXI.Point(this._rectangle.x, this._rectangle.y + this._rectangle.height / 2), + ]); } public cleanUp(): void { @@ -334,7 +365,8 @@ export class ArrowPrimitive extends BaseElementContainer<Models.ArrowPrimitive> delete this.rotateInteraction; } - this._colorPicker.off("color", this._onColor, this); + this._lineColorPicker.off("color", this._onLineColor, this); + this._fillColorPicker.off("color", this._onFillColor, this); this._staticButton.off("button", this._onStaticButton, this); this._lineArrowButton.off("button", this._onLineArrowButton, this); this._removeButton.off("button", this._onRemoveButton, this); @@ -722,12 +754,18 @@ export class ArrowPrimitive extends BaseElementContainer<Models.ArrowPrimitive> */ } + const wedgeXAdjust = this._rectangle.width / this._wedgePointElement.position.x; + const wedgeYAdjust = this._rectangle.height / this._wedgePointElement.position.y; + // Element this._rectangle.width += dW; this._rectangle.height += dH; this.model.rectangle.width = this._rectangle.width / this.imageWidth; this.model.rectangle.height = this._rectangle.height / this.imageWidth; + this._wedgePointElement.position.x += dW / wedgeXAdjust; + this._wedgePointElement.position.y += dH / wedgeYAdjust; + // Position TODO not needed ?? // this.position.x += (dX + dW / 2) * Math.cos(this.rotation) - (dY + dH / 2) * Math.sin(this.rotation); // this.position.y += (dY + dH / 2) * Math.cos(this.rotation) + (dX + dW / 2) * Math.sin(this.rotation); @@ -840,9 +878,27 @@ export class ArrowPrimitive extends BaseElementContainer<Models.ArrowPrimitive> //</editor-fold> //<editor-fold desc="Configurations"> - protected _onColor(color: number): void { + protected _onLineColor(hasLine: boolean, color: number, alpha: number): void { + this.model.options.hasLine = hasLine; + + this.model.options.lineColor = color; + this._lineColor = this.model.options.lineColor; + + this.model.options.lineAlpha = alpha; + this._lineAlpha = this.model.options.lineAlpha; + + this.draw(); + } + + protected _onFillColor(hasFill: boolean, color: number, alpha: number): void { + this.model.options.hasFill = hasFill; + this.model.options.fillColor = color; this._fillColor = this.model.options.fillColor; + + this.model.options.fillAlpha = alpha; + this._fillAlpha = this.model.options.fillAlpha; + this.draw(); } diff --git a/src/lib/elements/primitives/EllipsePrimitive.ts b/src/lib/elements/primitives/EllipsePrimitive.ts index b82bdf29e70cc12c7c78d0335e39ab05926c2ded..c6e1e6fd4c093f5e9176508ef450e886794ad382 100644 --- a/src/lib/elements/primitives/EllipsePrimitive.ts +++ b/src/lib/elements/primitives/EllipsePrimitive.ts @@ -25,15 +25,17 @@ import {LegendTextPrimitive} from "./LegendTextPrimitive"; /** * Ellipse primitive - * TODO hasLine and hasFill */ export class EllipsePrimitive extends BaseElementContainer<Models.EllipsePrimitive> { /** * Members */ protected _ellipse: PIXI.Ellipse; - protected _fillColor: number; protected _strokeWidth: number; + protected _lineColor: number | undefined; + protected _lineAlpha: number | undefined; + protected _fillColor: number | undefined; + protected _fillAlpha: number | undefined; /** * Interactions @@ -56,7 +58,8 @@ export class EllipsePrimitive extends BaseElementContainer<Models.EllipsePrimiti /** * Configurations */ - protected _colorPicker: ColorElement; + protected _lineColorPicker: ColorElement; + protected _fillColorPicker: ColorElement; protected _staticButton: ButtonElement; protected _selftestButton: ButtonElement; protected _selftestChooseButton: ButtonElement; @@ -67,6 +70,15 @@ export class EllipsePrimitive extends BaseElementContainer<Models.EllipsePrimiti * Design */ protected readonly _strokeWidthDefault: number = 2; + + protected readonly _hasLineDefault: boolean = true; + protected readonly _lineAlphaDefault: number = 1; + protected readonly _lineColorDefault: number = 0x000000; + protected readonly _lineColorSelftest: number = 0xFFC67B; + protected readonly _lineColorSelftestSelected: number = 0x4ae29c; + protected readonly _lineColorSelftestUnselected: number = 0xF02C6B; + + protected readonly _hasFillDefault: boolean = false; protected readonly _fillAlphaDefault: number = 1; protected readonly _fillColorDefault: number = 0xFFFFFF; protected readonly _fillColorSelftest: number = 0xFFC67B; @@ -87,31 +99,34 @@ export class EllipsePrimitive extends BaseElementContainer<Models.EllipsePrimiti } if (!this.model.options) { this.model.options = { - hasLine: false, - hasFill: false, + hasLine: this._hasLineDefault, + hasFill: this._hasFillDefault, }; } - if (!this.model.options.fillColor) { - this.model.options.hasFill = true; - this.model.options.fillColor = this._fillColorDefault; + if (this.model.options.hasLine && !this.model.options.lineColor) { + this.model.options.lineColor = this._lineColorDefault; } - if (!this.model.options.fillAlpha) { - this.model.options.hasFill = true; - this.model.options.fillColor = this._fillColorDefault; - this.model.options.fillAlpha = this._fillAlphaDefault; + if (this.model.options.hasLine && !this.model.options.lineAlpha) { + this.model.options.fillAlpha = this._lineAlphaDefault; } // Setup this.zIndex = 300; // TODO how to implement moveToFront etc... + this._ellipse = new PIXI.Ellipse( 0, 0, this.model.ellipse.width / 2 * this.imageWidth, this.model.ellipse.height / 2 * this.imageWidth ); - this._fillColor = this.model.options.fillColor; + this._strokeWidth = this.model.strokeWidth * this.imageWidth; + this._lineColor = this.model.options.lineColor; + this._lineAlpha = this.model.options.lineAlpha; + + this._fillColor = this.model.options.fillColor; + this._fillAlpha = this.model.options.fillAlpha; // Position this.position.set( @@ -178,9 +193,14 @@ export class EllipsePrimitive extends BaseElementContainer<Models.EllipsePrimiti this._rotateMeasureElement = new RotateMeasureElement(this._rotateInteraction, true); // Configurations - this._colorPicker = new ColorElement(this.model.options.fillColor); - this._colorPicker.on("color", this._onColor, this); - this._configurationElement.addChild(this._colorPicker); + this._lineColorPicker = new ColorElement(this.model.options.lineColor, this.model.options.lineAlpha); + this._lineColorPicker.on("color", this._onLineColor, this); + this._configurationElement.addChild(this._lineColorPicker); + + // TODO how to handle empty stuff + this._fillColorPicker = new ColorElement(this.model.options.fillColor, this.model.options.fillAlpha); + this._fillColorPicker.on("color", this._onFillColor, this); + this._configurationElement.addChild(this._fillColorPicker); this._staticButton = new ButtonElement(this.model.isStatic ? "\uf3c1" : "\uf023"); this._staticButton.on("button", this._onStaticButton, this); @@ -256,14 +276,18 @@ export class EllipsePrimitive extends BaseElementContainer<Models.EllipsePrimiti //<editor-fold desc="Public functions"> public draw(): void { this._ellipseElement.clear(); - if (this._fillColor) { - this._ellipseElement.beginFill(this._fillColor); + if (this.model.options.hasLine) { + this._ellipseElement.lineStyle(this._strokeWidth, this._lineColor, this._lineAlpha); + } + if (this.model.options.hasFill) { + this._ellipseElement.beginFill(this._fillColor, this._fillAlpha); } this._ellipseElement.drawEllipse(this._ellipse.x, this._ellipse.y, this._ellipse.width, this._ellipse.height); this._ellipseElement.endFill(); // @ts-ignore - this._ellipseElement.hitArea = new PIXI.Polygon(this._ellipseElement.geometry.points); + // this._ellipseElement.hitArea = new PIXI.Polygon(this._ellipseElement.geometry.points); + this._ellipseElement.hitArea = this._ellipse; } public cleanUp(): void { @@ -317,7 +341,8 @@ export class EllipsePrimitive extends BaseElementContainer<Models.EllipsePrimiti delete this.rotateInteraction; } - this._colorPicker.off("color", this._onColor, this); + this._lineColorPicker.off("color", this._onLineColor, this); + this._fillColorPicker.off("color", this._onFillColor, this); this._staticButton.off("button", this._onStaticButton, this); this._lineArrowButton.off("button", this._onLineArrowButton, this); this._removeButton.off("button", this._onRemoveButton, this); @@ -795,9 +820,27 @@ export class EllipsePrimitive extends BaseElementContainer<Models.EllipsePrimiti //</editor-fold> //<editor-fold desc="Configurations"> - protected _onColor(color: number): void { + protected _onLineColor(hasLine: boolean, color: number, alpha: number): void { + this.model.options.hasLine = hasLine; + + this.model.options.lineColor = color; + this._lineColor = this.model.options.lineColor; + + this.model.options.lineAlpha = alpha; + this._lineAlpha = this.model.options.lineAlpha; + + this.draw(); + } + + protected _onFillColor(hasFill: boolean, color: number, alpha: number): void { + this.model.options.hasFill = hasFill; + this.model.options.fillColor = color; this._fillColor = this.model.options.fillColor; + + this.model.options.fillAlpha = alpha; + this._fillAlpha = this.model.options.fillAlpha; + this.draw(); } diff --git a/src/lib/elements/primitives/LegendTextPrimitive.ts b/src/lib/elements/primitives/LegendTextPrimitive.ts index f61da63ea0e6036fac7e823857d5158de4efe5d5..3c99ecc75288247c150ee124adc81ab0da111bd8 100644 --- a/src/lib/elements/primitives/LegendTextPrimitive.ts +++ b/src/lib/elements/primitives/LegendTextPrimitive.ts @@ -91,7 +91,7 @@ export class LegendTextPrimitive extends BaseElementContainer<Models.LegendItem> // Setup this.zIndex = 300; // TODO how to implement moveToFront etc... this._style = new PIXI.TextStyle(this.model.style); - this._style.fontSize *= this.imageWidth; + this._style.fontSize = Math.round(this._style.fontSize * this.imageWidth); this._startTextIndex = this.model.text.length; this._endTextIndex = this.model.text.length; @@ -166,7 +166,7 @@ export class LegendTextPrimitive extends BaseElementContainer<Models.LegendItem> // TODO also add here and set visible flag ??? // Configurations - this._colorPicker = new ColorElement(this.model.style.fill); + this._colorPicker = new ColorElement(this.model.style.fill, undefined, "text_picker"); this._colorPicker.on("color", this._onColor, this); this._configurationElement.addChild(this._colorPicker); @@ -672,7 +672,7 @@ export class LegendTextPrimitive extends BaseElementContainer<Models.LegendItem> //</editor-fold> //<editor-fold desc="Configurations"> - protected _onColor(color: number): void { + protected _onColor(hasFill: boolean, color: number): void { this.model.style.fill = color; this._style.fill = this.model.style.fill; this.draw(); diff --git a/src/lib/elements/primitives/RectanglePrimitive.ts b/src/lib/elements/primitives/RectanglePrimitive.ts index 5778d1e2d0487f4e256d513abc14bb5b38272ab8..bbe4feb501a324597109df8db26512905d27cd5e 100644 --- a/src/lib/elements/primitives/RectanglePrimitive.ts +++ b/src/lib/elements/primitives/RectanglePrimitive.ts @@ -25,15 +25,17 @@ import {LegendTextPrimitive} from "./LegendTextPrimitive"; /** * Rectangle primitive - * TODO hasLine and hasFill */ export class RectanglePrimitive extends BaseElementContainer<Models.RectanglePrimitive> { /** * Members */ protected _rectangle: PIXI.Rectangle; - protected _fillColor: number; protected _strokeWidth: number; + protected _lineColor: number | undefined; + protected _lineAlpha: number | undefined; + protected _fillColor: number | undefined; + protected _fillAlpha: number | undefined; /** * Interactions @@ -56,7 +58,8 @@ export class RectanglePrimitive extends BaseElementContainer<Models.RectanglePri /** * Configurations */ - protected _colorPicker: ColorElement; + protected _lineColorPicker: ColorElement; + protected _fillColorPicker: ColorElement; protected _staticButton: ButtonElement; protected _selftestButton: ButtonElement; protected _selftestChooseButton: ButtonElement; @@ -67,6 +70,15 @@ export class RectanglePrimitive extends BaseElementContainer<Models.RectanglePri * Design */ protected readonly _strokeWidthDefault: number = 2; + + protected readonly _hasLineDefault: boolean = true; + protected readonly _lineAlphaDefault: number = 1; + protected readonly _lineColorDefault: number = 0x000000; + protected readonly _lineColorSelftest: number = 0xFFC67B; + protected readonly _lineColorSelftestSelected: number = 0x4ae29c; + protected readonly _lineColorSelftestUnselected: number = 0xF02C6B; + + protected readonly _hasFillDefault: boolean = false; protected readonly _fillAlphaDefault: number = 1; protected readonly _fillColorDefault: number = 0xFFFFFF; protected readonly _fillColorSelftest: number = 0xFFC67B; @@ -87,31 +99,35 @@ export class RectanglePrimitive extends BaseElementContainer<Models.RectanglePri } if (!this.model.options) { this.model.options = { - hasLine: false, - hasFill: false, + hasLine: this._hasLineDefault, + hasFill: this._hasFillDefault, }; } - if (!this.model.options.fillColor) { - this.model.options.hasFill = true; - this.model.options.fillColor = this._fillColorDefault; + if (this.model.options.hasLine && !this.model.options.lineColor) { + this.model.options.lineColor = this._lineColorDefault; } - if (!this.model.options.fillAlpha) { - this.model.options.hasFill = true; - this.model.options.fillColor = this._fillColorDefault; - this.model.options.fillAlpha = this._fillAlphaDefault; + if (this.model.options.hasLine && !this.model.options.lineAlpha) { + this.model.options.fillAlpha = this._lineAlphaDefault; } // Setup this.zIndex = 300; // TODO how to implement moveToFront etc... + this._rectangle = new PIXI.Rectangle( 0, 0, this.model.rectangle.width * this.imageWidth, this.model.rectangle.height * this.imageWidth ); - this._fillColor = this.model.options.fillColor; + this._strokeWidth = this.model.strokeWidth * this.imageWidth; + this._lineColor = this.model.options.lineColor; + this._lineAlpha = this.model.options.lineAlpha; + + this._fillColor = this.model.options.fillColor; + this._fillAlpha = this.model.options.fillAlpha; + // Position this.position.set( this.model.rectangle.x * this.imageWidth, @@ -177,9 +193,14 @@ export class RectanglePrimitive extends BaseElementContainer<Models.RectanglePri this._rotateMeasureElement = new RotateMeasureElement(this._rotateInteraction); // Configurations - this._colorPicker = new ColorElement(this.model.options.fillColor); - this._colorPicker.on("color", this._onColor, this); - this._configurationElement.addChild(this._colorPicker); + this._lineColorPicker = new ColorElement(this.model.options.lineColor, this.model.options.lineAlpha); + this._lineColorPicker.on("color", this._onLineColor, this); + this._configurationElement.addChild(this._lineColorPicker); + + // TODO how to handle empty stuff + this._fillColorPicker = new ColorElement(this.model.options.fillColor, this.model.options.fillAlpha); + this._fillColorPicker.on("color", this._onFillColor, this); + this._configurationElement.addChild(this._fillColorPicker); this._staticButton = new ButtonElement(this.model.isStatic ? "\uf3c1" : "\uf023"); this._staticButton.on("button", this._onStaticButton, this); @@ -255,8 +276,11 @@ export class RectanglePrimitive extends BaseElementContainer<Models.RectanglePri //<editor-fold desc="Public functions"> public draw(): void { this._rectangleElement.clear(); - if (this._fillColor) { - this._rectangleElement.beginFill(this._fillColor); + if (this.model.options.hasLine) { + this._rectangleElement.lineStyle(this._strokeWidth, this._lineColor, this._lineAlpha); + } + if (this.model.options.hasFill) { + this._rectangleElement.beginFill(this._fillColor, this._fillAlpha); } this._rectangleElement.drawRect(this._rectangle.x, this._rectangle.y, this._rectangle.width, this._rectangle.height); this._rectangleElement.endFill(); @@ -317,7 +341,8 @@ export class RectanglePrimitive extends BaseElementContainer<Models.RectanglePri delete this.rotateInteraction; } - this._colorPicker.off("color", this._onColor, this); + this._lineColorPicker.off("color", this._onLineColor, this); + this._fillColorPicker.off("color", this._onFillColor, this); this._staticButton.off("button", this._onStaticButton, this); this._lineArrowButton.off("button", this._onLineArrowButton, this); this._removeButton.off("button", this._onRemoveButton, this); @@ -797,9 +822,27 @@ export class RectanglePrimitive extends BaseElementContainer<Models.RectanglePri //</editor-fold> //<editor-fold desc="Configurations"> - protected _onColor(color: number): void { + protected _onLineColor(hasLine: boolean, color: number, alpha: number): void { + this.model.options.hasLine = hasLine; + + this.model.options.lineColor = color; + this._lineColor = this.model.options.lineColor; + + this.model.options.lineAlpha = alpha; + this._lineAlpha = this.model.options.lineAlpha; + + this.draw(); + } + + protected _onFillColor(hasFill: boolean, color: number, alpha: number): void { + this.model.options.hasFill = hasFill; + this.model.options.fillColor = color; this._fillColor = this.model.options.fillColor; + + this.model.options.fillAlpha = alpha; + this._fillAlpha = this.model.options.fillAlpha; + this.draw(); } diff --git a/src/lib/elements/primitives/TextPrimitive.ts b/src/lib/elements/primitives/TextPrimitive.ts index 60402e408bc4b1c835f492d396994fb4fa2c345d..d2d7481b9d13a769d005e367f46521d0af6d11f2 100644 --- a/src/lib/elements/primitives/TextPrimitive.ts +++ b/src/lib/elements/primitives/TextPrimitive.ts @@ -36,14 +36,9 @@ export class TextPrimitive extends BaseElementContainer<Models.TextPrimitive> { * Members */ protected _style: any | PIXI.TextStyle; - // protected _color: number; - protected _strokeWidth: number; private _startTextIndex: number; private _endTextIndex: number; private _textSelection: boolean; - /* TODO remove - private _text: string; - */ /** * Interactions @@ -123,18 +118,25 @@ export class TextPrimitive extends BaseElementContainer<Models.TextPrimitive> { if (!this.model.style.fontSize) { this.model.style.fontSize = this._fontSizeDefault; } + if (!this.model.style.fontFamily) { + this.model.style.fontFamily = this._fontFamilyDefault; + } + if (!this.model.style.align) { + this.model.style.align = this._alignDefault; + } + if (!this.model.style.wordWrap) { + this.model.style.wordWrap = this._wordWrapDefault; + } // Setup this.zIndex = 300; // TODO how to implement moveToFront etc... + this._style = new PIXI.TextStyle(this.model.style); - this._style.fontSize *= this.imageWidth; + this._style.fontSize = Math.round(this._style.fontSize * this.imageWidth); this._startTextIndex = this.model.text.length; this._endTextIndex = this.model.text.length; this._textSelection = false; - /* TODO remove - this._text = text; - */ // Position this.position.set( @@ -216,7 +218,7 @@ export class TextPrimitive extends BaseElementContainer<Models.TextPrimitive> { // TODO also add here and set visible flag ??? // Configurations - this._colorPicker = new ColorElement(this.model.style.fill); + this._colorPicker = new ColorElement(this.model.style.fill, undefined, "text_picker"); this._colorPicker.on("color", this._onColor, this); this._configurationElement.addChild(this._colorPicker); @@ -907,7 +909,7 @@ export class TextPrimitive extends BaseElementContainer<Models.TextPrimitive> { //</editor-fold> //<editor-fold desc="Configurations"> - protected _onColor(color: number): void { + protected _onColor(hasFill: boolean, color: number): void { this.model.style.fill = color; this._style.fill = this.model.style.fill; this.draw(); diff --git a/src/public/index.html b/src/public/index.html index b18a8c34b15aee0de4dda9301a6a5b3d099733cf..feffeca98b6aefae697df5dd8fd6c5d0f9c5e881 100644 --- a/src/public/index.html +++ b/src/public/index.html @@ -3,6 +3,7 @@ <head> <meta charset="utf-8"> <title>MEDSURF PIXI</title> + <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/spectrum/1.8.0/spectrum.min.css"> <!-- style --> <script src="https://kit.fontawesome.com/4b2e35c716.js" crossorigin="anonymous"></script> <!-- <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.11.2/css/all.css" integrity="sha384-KA6wR/X5RY4zFAHpv/CnoG2UW1uogYfdnP67Uv7eULvTveboZJg0qUpmJZb5VqzN" crossorigin="anonymous">--> @@ -255,10 +256,31 @@ } </script> --> + <style type="text/css"> + .color_picker_div{ + position: absolute; + top: 50%; + left: 50%; + margin-top: -200px; + margin-left: -150px; + width: 300px; + height: 200px; + pointer-events: none; + } + + .color_picker { + opacity: 0; + } + </style> </head> <body> <canvas id="medsurf_canvas" width="1200" height="800" oncontextmenu="return false;"></canvas> - <input id="color_picker" type="color" style="display: none;" /> + <div class="color_picker_div"> + <input type="text" id="color_picker" /> + </div> + <div class="color_picker_div"> + <input type="text" id="text_picker" /> + </div> <button id="button_default">Default</button> <button id="button_marker">Marker</button> <button id="button_selftest">Selftest</button>