diff --git a/client/src/components/geoJS/LayerManager.vue b/client/src/components/geoJS/LayerManager.vue index 31de8d63..68c77e55 100644 --- a/client/src/components/geoJS/LayerManager.vue +++ b/client/src/components/geoJS/LayerManager.vue @@ -572,11 +572,14 @@ export default defineComponent({ speciesLayer?.setScaledDimensions(props.scaledWidth, props.scaledHeight); speciesSequenceLayer?.setScaledDimensions(props.scaledWidth, props.scaledHeight); sequenceAnnotationLayer?.setScaledDimensions(props.scaledWidth, props.scaledHeight); - if (timeLayer && layerVisibility.value.includes("time")) { + if (timeLayer && (layerVisibility.value.includes("time") || layerVisibility.value.includes('duration'))) { + if (layerVisibility.value.includes("time")) { + timeLayer.displayDuration = false; + } else { + timeLayer.displayDuration = true; + } timeLayer.formatData(annotations, sequenceAnnotations); timeLayer.redraw(); - } else { - timeLayer?.disable(); } if (freqLayer && layerVisibility.value.includes("freq")) { freqLayer.formatData(annotations); diff --git a/client/src/components/geoJS/layers/baseTextLayer.ts b/client/src/components/geoJS/layers/baseTextLayer.ts new file mode 100644 index 00000000..85c99e78 --- /dev/null +++ b/client/src/components/geoJS/layers/baseTextLayer.ts @@ -0,0 +1,136 @@ + + +/* eslint-disable class-methods-use-this */ +import { SpectroInfo } from "../geoJSUtils"; +import { LayerStyle } from "./types"; +import geo from "geojs"; + + + +export default abstract class BaseTextLayer { + textData: D[]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + textLayer: any; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + geoViewerRef: any; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + event: (name: string, data: any) => void; + + spectroInfo: SpectroInfo; + + textStyle: LayerStyle; + + scaledWidth: number; + scaledHeight: number; + + + + + textScaled: number | undefined; + + zoomLevel: number; + + xScale: number; + + compressedView: boolean; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + constructor( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + geoViewerRef: any, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + event: (name: string, data: any) => void, + spectroInfo: SpectroInfo + ) { + this.geoViewerRef = geoViewerRef; + this.spectroInfo = spectroInfo; + this.textData = []; + this.scaledWidth = 0; + this.scaledHeight = 0; + this.event = event; + this.xScale = 0; + this.compressedView = false; + //Only initialize once, prevents recreating Layer each edit + this.textStyle = this.createTextStyle(); + this.geoViewerRef.geoOn(geo.event.zoom, (event: {zoomLevel: number}) => this.onZoom(event)); + this.zoomLevel = this.geoViewerRef.camera().zoomLevel; + + } + + setScaledDimensions(newWidth: number, newHeight: number) { + this.scaledWidth = newWidth; + this.scaledHeight = newHeight; + if (this.spectroInfo.compressedWidth) { + this.xScale = newWidth / this.spectroInfo.compressedWidth; + this.compressedView = true; + } else { + this.xScale = newWidth / this.spectroInfo.width; + this.compressedView = false; + } + } + + onZoom(event: {zoomLevel: number}) { + this.zoomLevel = event.zoomLevel; + this.textScaled = undefined; + if ((this.zoomLevel || 0) < -1.5 ) { + this.textScaled = -1.5; + } else if ((this.zoomLevel || 0) > 0) { + this.textScaled = Math.sqrt(this.zoomLevel || 1); + } else { + this.textScaled = this.zoomLevel; + } + this.redraw(); + } + + + destroy() { + if (this.textLayer) { + this.geoViewerRef.deleteLayer(this.textLayer); + } + } + + + + redraw() { + // add some styles + this.textLayer.data(this.textData).style(this.createTextStyle()).draw(); + } + + disable() { + this.textLayer.data([]).draw(); + } + + getFontSize(fontA: number, fontB: number, xScale: number) { + if (xScale >= 2.5) { + return fontA; // clamp high + } else if (xScale <= 1.0) { + return fontB; // clamp low + } else { + const t = (xScale - 1.0) / (2.5 - 1.0); // normalized progress + return fontB + t * (fontA - fontB); // linear interpolation + } +} + + + createTextStyle(): LayerStyle { + return { + ...{ + strokeColor: "white", + strokeWidth: 2.0, + antialiasing: 0, + stroke: true, + uniformPolygon: true, + fill: false, + fontSize: () => this.xScale < 2.5 ? '12px' : '16px' + }, + color: () => { + return "white"; + }, + textScaled: this.textScaled, + textBaseline: 'middle', + }; + } + +} diff --git a/client/src/components/geoJS/layers/freqLayer.ts b/client/src/components/geoJS/layers/freqLayer.ts index 42dd970c..e1a2fc5f 100644 --- a/client/src/components/geoJS/layers/freqLayer.ts +++ b/client/src/components/geoJS/layers/freqLayer.ts @@ -1,6 +1,7 @@ /* eslint-disable class-methods-use-this */ import { SpectrogramAnnotation } from "../../../api/api"; import { SpectroInfo, spectroToGeoJSon } from "../geoJSUtils"; +import BaseTextLayer from "./baseTextLayer"; import { LayerStyle } from "./types"; interface LineData { @@ -17,32 +18,14 @@ interface TextData { offsetX?: number; } -export default class FreqLayer { +export default class FreqLayer extends BaseTextLayer { lineData: LineData[]; // eslint-disable-next-line @typescript-eslint/no-explicit-any lineLayer: any; - textData: TextData[]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - textLayer: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - geoViewerRef: any; - - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - event: (name: string, data: any) => void; - - spectroInfo: SpectroInfo; - - textStyle: LayerStyle; lineStyle: LayerStyle; - scaledWidth: number; - scaledHeight: number; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any constructor( // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -51,13 +34,8 @@ export default class FreqLayer { event: (name: string, data: any) => void, spectroInfo: SpectroInfo ) { - this.geoViewerRef = geoViewerRef; + super(geoViewerRef, event, spectroInfo); this.lineData = []; - this.spectroInfo = spectroInfo; - this.textData = []; - this.scaledWidth = 0; - this.scaledHeight = 0; - this.event = event; //Only initialize once, prevents recreating Layer each edit const layer = this.geoViewerRef.createLayer("feature", { features: ["text", "line"], @@ -73,11 +51,6 @@ export default class FreqLayer { this.lineStyle = this.createLineStyle(); } - setScaledDimensions(newWidth: number, newHeight: number) { - this.scaledWidth = newWidth; - this.scaledHeight = newHeight; - } - destroy() { if (this.textLayer) { this.geoViewerRef.deleteLayer(this.textLayer); @@ -196,6 +169,7 @@ export default class FreqLayer { stroke: true, uniformPolygon: true, fill: false, + fontSize: '16px', }, color: () => { return "white"; @@ -204,7 +178,9 @@ export default class FreqLayer { x: data.offsetX || 0, y: data.offsetY || 0, }), - textAlign: 'starts', + textAlign: 'start', + textScaled: this.textScaled, + textBaseline: 'bottom', }; } } diff --git a/client/src/components/geoJS/layers/legendLayer.ts b/client/src/components/geoJS/layers/legendLayer.ts index cc4b800f..d3ee8109 100644 --- a/client/src/components/geoJS/layers/legendLayer.ts +++ b/client/src/components/geoJS/layers/legendLayer.ts @@ -1,5 +1,6 @@ /* eslint-disable class-methods-use-this */ import { SpectroInfo } from "../geoJSUtils"; +import BaseTextLayer from "./baseTextLayer"; import { LayerStyle } from "./types"; import geo from "geojs"; @@ -15,9 +16,13 @@ interface TextData { y: number; offsetY?: number; offsetX?: number; + type: 'time' | 'freq', + textAlign?: 'left' | 'center' | 'right'; + textBaseline?: 'top' | 'middle' | 'bottom'; + textScaled?: number | undefined; } -export default class LegendLayer { +export default class LegendLayer extends BaseTextLayer { lineDataX: LineData[]; lineDataY: LineData[]; @@ -32,14 +37,8 @@ export default class LegendLayer { // eslint-disable-next-line @typescript-eslint/no-explicit-any textLayer: any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - geoViewerRef: any; - gridLines: LineData[]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - event: (name: string, data: any) => void; - spectroInfo: SpectroInfo; textStyle: LayerStyle; @@ -49,9 +48,6 @@ export default class LegendLayer { gridEnabled: boolean; - scaledWidth: number; - - scaledHeight: number; // eslint-disable-next-line @typescript-eslint/no-explicit-any constructor( @@ -61,7 +57,8 @@ export default class LegendLayer { event: (name: string, data: any) => void, spectroInfo: SpectroInfo ) { - this.geoViewerRef = geoViewerRef; + + super(geoViewerRef, event, spectroInfo); this.lineDataX = []; this.lineDataY = []; this.spectroInfo = spectroInfo; @@ -70,7 +67,6 @@ export default class LegendLayer { this.axisBuffer = 5; this.scaledHeight = -1; this.scaledWidth = -1; - this.event = event; this.gridEnabled = false; //Only initialize once, prevents recreating Layer each edit const layer = this.geoViewerRef.createLayer("feature", { @@ -88,11 +84,13 @@ export default class LegendLayer { this.lineStyle = this.createLineStyle(); this.gridLines = []; this.geoViewerRef.geoOn(geo.event.pan, () => this.onPan()); + this.geoViewerRef.geoOn(geo.event.zoom, (event: {zoomLevel: number}) => this.onZoom(event)); this.createLabels(); this.calcGridLines(); } + onPan() { const bounds = this.geoViewerRef.camera().bounds; const { left, bottom, top } = bounds; @@ -109,8 +107,7 @@ export default class LegendLayer { } setScaledDimensions( width: number, height: number) { - this.scaledWidth = width; - this.scaledHeight = height; + super.setScaledDimensions(width, height); this.createLabels(); this.calcGridLines(); if (this.gridEnabled) { @@ -157,10 +154,12 @@ export default class LegendLayer { }); this.textDataX.push({ text: `${i}ms`, + type: 'time', x: i * timeToPixels, y: baseYPos + length, offsetX: 3, offsetY: yOffset === 0 ? 8 : -8, + textScaled: this.textScaled, }); } } @@ -185,7 +184,7 @@ export default class LegendLayer { const yBuffer = yOffset === 0 ? this.axisBuffer : this.axisBuffer * -0.5; const baseYPos = yOffset === 0 ? adjustedHeight : yOffset; const baseTopPos = topOffset === 0 ? 0 : -topOffset; - const topBuffer = topOffset === 0 ? this.axisBuffer * 3 : this.axisBuffer * -0.5; + const topBuffer = topOffset === 0 ? this.axisBuffer * 3 : this.axisBuffer * -3; const { start_times, end_times, widths, compressedWidth } = this.spectroInfo; if (!compressedWidth) { @@ -199,8 +198,8 @@ export default class LegendLayer { const start_time = start_times[i]; const end_time = end_times[i]; const width = this.scaledWidth > compressedWidth ? (this.scaledWidth / compressedWidth) * widths[i] : widths[i]; - const bottomWithinYAxisStart = (pixelOffset) < (leftOffset + 50) && leftOffset !== 0 && yOffset !== 0; - const topWithinYAxisEnd = (pixelOffset+width) < (leftOffset + 50) && leftOffset !== 0 && topOffset !== 0; + const bottomWithinYAxisStart = (pixelOffset) < (leftOffset + 150) && leftOffset !== 0 && yOffset !== 0; + const topWithinYAxisEnd = (pixelOffset+width) < (leftOffset + 150) && leftOffset !== 0 && topOffset !== 0; if (!bottomWithinYAxisStart) { @@ -262,20 +261,21 @@ export default class LegendLayer { if (!bottomWithinYAxisStart) { this.textDataX.push({ text: `${start_time}ms`, + type: 'time', x: 0 + pixelOffset, - y: baseYPos + length, - offsetX: 3, - offsetY: yOffset === 0 ? 16 : -16, + y: baseYPos + length + (yOffset === 0 ? 18 : -12), + textScaled: this.textScaled, }); } if (!topWithinYAxisEnd) { this.textDataX.push({ text: `${end_time}ms`, + type: 'time', x: width + pixelOffset, - y: baseTopPos, - offsetX: 3, - offsetY: baseTopPos === 0 ? -16 : 16, + y: baseTopPos + (baseTopPos === 0 ? -16 : 16), + textBaseline: baseTopPos === 0 ? 'bottom' : 'top', + textScaled: this.textScaled, }); } pixelOffset += width; @@ -362,12 +362,15 @@ export default class LegendLayer { }, thicker: i % 10000 === 0, }); + this.textDataY.push({ text: `${(i + this.spectroInfo.low_freq) / 1000}KHz`, - x: offset - xBuffer - length, + x: offset - xBuffer + (offset === 0 ? -45 : 10), y: adjustedHeight - i * hzToPixels, - offsetX: offset === 0 ? -25 : 25, + textAlign: offset === 0 ? 'right' : 'left', offsetY: 0, + type: 'freq', + textScaled: this.textScaled, }); } } @@ -424,7 +427,6 @@ export default class LegendLayer { } redraw() { - // add some styles const combinedLineData = this.lineDataX.concat(this.lineDataY); this.lineLayer .data(combinedLineData) @@ -491,6 +493,7 @@ export default class LegendLayer { stroke: true, uniformPolygon: true, fill: false, + fontSize: `${this.getFontSize(20, 12, this.xScale)}px` }, color: () => { return "white"; @@ -499,6 +502,10 @@ export default class LegendLayer { x: data.offsetX || 0, y: data.offsetY || 0, }), + textBaseline: (data) => data.textBaseline || 'middle', + textAlign: (data) => (data.textAlign || "center"), + textScaled: (data) => (data.textScaled), + fontSize: (data) => data.type === 'time' && this.compressedView ? `${this.getFontSize(16, 10, this.xScale)}px` : `20px`, }; } } diff --git a/client/src/components/geoJS/layers/sequenceLayer.ts b/client/src/components/geoJS/layers/sequenceLayer.ts index 81964da4..60ad23f2 100644 --- a/client/src/components/geoJS/layers/sequenceLayer.ts +++ b/client/src/components/geoJS/layers/sequenceLayer.ts @@ -133,7 +133,7 @@ export default class SequenceLayer { yScale = 1, ) { const arr: RectGeoJSData[] = []; - const compressedView = !!(this.spectroInfo.start_times && this.spectroInfo.end_times); + const compressedView = !!(this.spectroInfo.compressedWidth); const offsetY = compressedView ? -80 : 0; annotationData.forEach((annotation: SpectrogramSequenceAnnotation) => { const polygon = spectroSequenceToGeoJSon( diff --git a/client/src/components/geoJS/layers/speciesLayer.ts b/client/src/components/geoJS/layers/speciesLayer.ts index 41b58454..75a54512 100644 --- a/client/src/components/geoJS/layers/speciesLayer.ts +++ b/client/src/components/geoJS/layers/speciesLayer.ts @@ -1,6 +1,7 @@ /* eslint-disable class-methods-use-this */ import { SpectrogramAnnotation } from "../../../api/api"; import { SpectroInfo, spectroToGeoJSon } from "../geoJSUtils"; +import BaseTextLayer from "./baseTextLayer"; import { LayerStyle } from "./types"; interface TextData { @@ -11,26 +12,9 @@ interface TextData { offsetX?: number; } -export default class SpeciesLayer { - - textData: TextData[]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - textLayer: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - geoViewerRef: any; +export default class SpeciesLayer extends BaseTextLayer { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - event: (name: string, data: any) => void; - - spectroInfo: SpectroInfo; - - textStyle: LayerStyle; - - scaledWidth: number; - scaledHeight: number; - // eslint-disable-next-line @typescript-eslint/no-explicit-any constructor( // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -39,12 +23,7 @@ export default class SpeciesLayer { event: (name: string, data: any) => void, spectroInfo: SpectroInfo ) { - this.geoViewerRef = geoViewerRef; - this.spectroInfo = spectroInfo; - this.textData = []; - this.event = event; - this.scaledWidth = 0; - this.scaledHeight = 0; + super(geoViewerRef, event, spectroInfo); //Only initialize once, prevents recreating Layer each edit const layer = this.geoViewerRef.createLayer("feature", { features: ["text"], @@ -53,23 +32,8 @@ export default class SpeciesLayer { .createFeature("text") .text((data: TextData) => data.text) .position((data: TextData) => ({ x: data.x, y: data.y })); - - - this.textStyle = this.createTextStyle(); - } - - setScaledDimensions(newWidth: number, newHeight: number) { - this.scaledWidth = newWidth; - this.scaledHeight = newHeight; } - destroy() { - if (this.textLayer) { - this.geoViewerRef.deleteLayer(this.textLayer); - } - } - - formatData(annotationData: SpectrogramAnnotation[]) { this.textData = []; @@ -91,28 +55,16 @@ export default class SpeciesLayer { const specie = species[i]; this.textData.push({ text: `${specie.species_code || specie.common_name}`, - x: xmin + (xmax-xmin) /2.0, - y: ymax , - offsetX:0, - offsetY: -5 + textOffset, + x: xmin + (xmax - xmin) / 2.0, + y: ymax + textOffset, }); - textOffset -= 15; + textOffset -= 40; } } }); } - redraw() { - // add some styles - this.textLayer.data(this.textData).style(this.createTextStyle()).draw(); - } - - disable() { - this.textLayer.data([]).draw(); - } - - createTextStyle(): LayerStyle { return { ...{ @@ -122,6 +74,7 @@ export default class SpeciesLayer { stroke: true, uniformPolygon: true, fill: false, + fontSize: '18px', }, color: () => { return "white"; @@ -131,6 +84,8 @@ export default class SpeciesLayer { y: data.offsetY || 0, }), textAlign: 'center', + textBaseline: 'bottom', + textScaled: this.textScaled }; } } diff --git a/client/src/components/geoJS/layers/speciesSequenceLayer.ts b/client/src/components/geoJS/layers/speciesSequenceLayer.ts index 86c98055..095a110a 100644 --- a/client/src/components/geoJS/layers/speciesSequenceLayer.ts +++ b/client/src/components/geoJS/layers/speciesSequenceLayer.ts @@ -1,6 +1,7 @@ /* eslint-disable class-methods-use-this */ import { SpectrogramSequenceAnnotation } from "../../../api/api"; import { SpectroInfo, spectroSequenceToGeoJSon } from "../geoJSUtils"; +import BaseTextLayer from "./baseTextLayer"; import { LayerStyle } from "./types"; interface TextData { @@ -12,23 +13,7 @@ interface TextData { textType: "species" | "type"; } -export default class SpeciesSequenceLayer { - textData: TextData[]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - textLayer: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - geoViewerRef: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - event: (name: string, data: any) => void; - - spectroInfo: SpectroInfo; - - textStyle: LayerStyle; - - scaledWidth: number; - scaledHeight: number; +export default class SpeciesSequenceLayer extends BaseTextLayer { // eslint-disable-next-line @typescript-eslint/no-explicit-any constructor( @@ -38,13 +23,7 @@ export default class SpeciesSequenceLayer { event: (name: string, data: any) => void, spectroInfo: SpectroInfo ) { - this.geoViewerRef = geoViewerRef; - this.spectroInfo = spectroInfo; - this.textData = []; - this.scaledWidth = 0; - this.scaledHeight = 0; - this.event = event; - //Only initialize once, prevents recreating Layer each edit + super(geoViewerRef, event, spectroInfo); const layer = this.geoViewerRef.createLayer("feature", { features: ["text"], }); @@ -53,24 +32,12 @@ export default class SpeciesSequenceLayer { .text((data: TextData) => data.text) .position((data: TextData) => ({ x: data.x, y: data.y })); - this.textStyle = this.createTextStyle(); - } - - setScaledDimensions(newWidth: number, newHeight: number) { - this.scaledWidth = newWidth; - this.scaledHeight = newHeight; - } - - destroy() { - if (this.textLayer) { - this.geoViewerRef.deleteLayer(this.textLayer); - } } formatData(annotationData: SpectrogramSequenceAnnotation[]) { this.textData = []; - const compressedView = !!(this.spectroInfo.start_times && this.spectroInfo.end_times); - const offsetY = compressedView ? -100 : 0; + const compressedView = !!(this.spectroInfo.compressedWidth); + const offsetY = compressedView ? -100 : -20; annotationData.forEach((annotation: SpectrogramSequenceAnnotation) => { const polygon = spectroSequenceToGeoJSon( annotation, @@ -90,45 +57,33 @@ export default class SpeciesSequenceLayer { if (xmax === -1 && ymin === -1 && ymax === -1 && xmin === -1) { return; } - let textOffset = 0; + let textOffset = -40 + offsetY; const species = annotation.species; const type = annotation.type; if (species) { + if (type) { + this.textData.push({ + text: `${type}`, + x: xmin + (xmax - xmin) / 2.0, + y: ymin + textOffset, + textType: "type", + }); + textOffset -= 40; + } for (let i = 0; i < species.length; i += 1) { const specie = species[i]; this.textData.push({ text: `${specie.species_code || specie.common_name}`, x: xmin + (xmax - xmin) / 2.0, - y: ymax, - offsetX: 0, - offsetY: -30 + textOffset, + y: ymin + textOffset, textType: "species", }); - textOffset -= 15; + textOffset -= 40; } } - if (type) { - this.textData.push({ - text: `${type}`, - x: xmin + (xmax - xmin) / 2.0, - y: ymin, - offsetX: 0, - offsetY: 10 + offsetY, - textType: "type", - }); - } }); } - redraw() { - // add some styles - this.textLayer.data(this.textData).style(this.createTextStyle()).draw(); - } - - disable() { - this.textLayer.data([]).draw(); - } - createTextStyle(): LayerStyle { return { ...{ @@ -138,6 +93,7 @@ export default class SpeciesSequenceLayer { stroke: true, uniformPolygon: true, fill: false, + fontSize: '18px', }, color: (d) => { if (d.textType === "type") { @@ -150,6 +106,7 @@ export default class SpeciesSequenceLayer { y: data.offsetY || 0, }), textAlign: "center", + textScaled: this.textScaled, }; } } diff --git a/client/src/components/geoJS/layers/timeLayer.ts b/client/src/components/geoJS/layers/timeLayer.ts index 61dd9337..5f92676a 100644 --- a/client/src/components/geoJS/layers/timeLayer.ts +++ b/client/src/components/geoJS/layers/timeLayer.ts @@ -1,6 +1,7 @@ /* eslint-disable class-methods-use-this */ import { SpectrogramAnnotation, SpectrogramSequenceAnnotation } from "../../../api/api"; import { SpectroInfo, spectroSequenceToGeoJSon, spectroToGeoJSon } from "../geoJSUtils"; +import BaseTextLayer from "./baseTextLayer"; import { LayerStyle } from "./types"; interface LineData { @@ -15,32 +16,18 @@ interface TextData { y: number; offsetY?: number; offsetX?: number; + textScaled?: undefined | number; + textBaseline?: 'middle' | 'top' | 'bottom'; } -export default class TimeLayer { +export default class TimeLayer extends BaseTextLayer { lineData: LineData[]; // eslint-disable-next-line @typescript-eslint/no-explicit-any lineLayer: any; - textData: TextData[]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - textLayer: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - geoViewerRef: any; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - event: (name: string, data: any) => void; - - spectroInfo: SpectroInfo; - - textStyle: LayerStyle; lineStyle: LayerStyle; - scaledWidth: number; - scaledHeight: number; - displayDuration: boolean; displaying: { sequence: boolean; pulse: boolean }; @@ -53,14 +40,11 @@ export default class TimeLayer { event: (name: string, data: any) => void, spectroInfo: SpectroInfo ) { - this.geoViewerRef = geoViewerRef; + super(geoViewerRef, event, spectroInfo); this.lineData = []; - this.spectroInfo = spectroInfo; this.textData = []; - this.scaledWidth = 0; - this.scaledHeight = 0; + this.displayDuration = true; this.displaying = { sequence: true, pulse: true }; - this.event = event; //Only initialize once, prevents recreating Layer each edit const layer = this.geoViewerRef.createLayer("feature", { features: ["text", "line"], @@ -72,15 +56,9 @@ export default class TimeLayer { this.lineLayer = layer.createFeature("line"); this.displayDuration = true; - this.textStyle = this.createTextStyle(); this.lineStyle = this.createLineStyle(); } - setScaledDimensions(newWidth: number, newHeight: number) { - this.scaledWidth = newWidth; - this.scaledHeight = newHeight; - } - destroy() { if (this.textLayer) { this.geoViewerRef.deleteLayer(this.textLayer); @@ -141,21 +119,19 @@ export default class TimeLayer { this.textData.push({ text: `${start_time}ms`, x: xmin, - y: ymin + lineDist, - offsetX: 0, - offsetY: 5, + y: ymin + lineDist + 5, + textBaseline: 'top', }); this.textData.push({ text: `${end_time}ms`, x: xmax, - y: ymin + lineDist, - offsetX: 0, - offsetY: 5, + y: ymin + lineDist + 5, + textBaseline: 'top', }); }); } - const compressedView = !!(this.spectroInfo.start_times && this.spectroInfo.end_times); - const offsetY = compressedView ? -30 : 0; + const compressedView = !!(this.spectroInfo.compressedWidth); + const offsetY = compressedView ? -80 : 0; if (this.displaying.sequence) { sequenceData.forEach((annotation: SpectrogramSequenceAnnotation) => { const polygon = spectroSequenceToGeoJSon( @@ -165,7 +141,8 @@ export default class TimeLayer { -50, 1, this.scaledWidth, - this.scaledHeight + this.scaledHeight, + offsetY ); const { start_time, end_time } = annotation; const [xmin, ymin] = polygon.coordinates[0][0]; @@ -182,8 +159,8 @@ export default class TimeLayer { line: { type: "LineString", coordinates: [ - [xmin, ymax + offsetY], - [xmin, ymax - lineDist + offsetY], + [xmin, ymax], + [xmin, ymax - lineDist], ], }, thicker: true, @@ -192,8 +169,8 @@ export default class TimeLayer { line: { type: "LineString", coordinates: [ - [xmax, ymax + offsetY], - [xmax, ymax - lineDist + offsetY], + [xmax, ymax], + [xmax, ymax - lineDist], ], }, thicker: true, @@ -202,16 +179,12 @@ export default class TimeLayer { this.textData.push({ text: `${start_time}ms`, x: xmin, - y: ymax - lineDist + offsetY, - offsetX: 0, - offsetY: -5 + offsetY, + y: ymax - lineDist, }); this.textData.push({ text: `${end_time}ms`, x: xmax, - y: ymax - lineDist + offsetY, - offsetX: 0, - offsetY: -5 + offsetY, + y: ymax - lineDist, }); }); } @@ -250,13 +223,11 @@ export default class TimeLayer { text: `${end_time - start_time}ms`, x: xpos, y: ypos + lineDist, - offsetX: 0, - offsetY: 0, }); }); } - const compressedView = !!(this.spectroInfo.start_times && this.spectroInfo.end_times); - const offsetY = compressedView ? -30 : 0; + const compressedView = !!(this.spectroInfo.compressedWidth); + const offsetY = compressedView ? -50 : 30; if (this.displaying.sequence) { sequenceData.forEach((annotation: SpectrogramSequenceAnnotation) => { const polygon = spectroSequenceToGeoJSon( @@ -283,9 +254,7 @@ export default class TimeLayer { this.textData.push({ text: `${end_time - start_time}ms`, x: xpos, - y: (ymax - ymin) / 2.0, - offsetX: 0, - offsetY: -5 + offsetY, + y: ((ymax - ymin) / 2.0) + -35 + offsetY, }); }); } @@ -355,6 +324,7 @@ export default class TimeLayer { stroke: true, uniformPolygon: true, fill: false, + fontSize: `${this.getFontSize(16, 12, this.xScale)}px`, }, color: () => { return "white"; @@ -363,6 +333,8 @@ export default class TimeLayer { x: data.offsetX || 0, y: data.offsetY || 0, }), + textScaled: this.textScaled, + textBaseline: 'middle', }; } diff --git a/client/src/components/geoJS/layers/types.ts b/client/src/components/geoJS/layers/types.ts index d0fec292..22cc59b3 100644 --- a/client/src/components/geoJS/layers/types.ts +++ b/client/src/components/geoJS/layers/types.ts @@ -12,11 +12,12 @@ export interface LayerStyle { position?: (point: [number, number]) => { x: number; y: number }; color?: (data: D) => string; textOpacity?: (data: D) => number; - fontSize?: (data: D) => string | undefined; + fontSize?: string | ((data: D) => string | undefined); offset?: (data: D) => { x: number; y: number }; fill?: ObjectFunction | boolean; radius?: PointFunction | number; textAlign?: ((data: D) => string) | string; + textBaseline?: ((data: D) => string) | string; textScaled?: ((data: D) => number | undefined) | number | undefined; [x: string]: unknown; } diff --git a/prod/client.Dockerfile b/prod/client.Dockerfile index 75286265..fd3358f6 100644 --- a/prod/client.Dockerfile +++ b/prod/client.Dockerfile @@ -46,7 +46,7 @@ COPY --from=build-stage /app/dist /tmp/dist # If DJANGO_BATAI_URL_PATH is set, copy dist to subfolder and rewrite nginx config COPY prod/nginx/nginx.subpath.template /nginx.subpath.template COPY prod/nginx/nginx.subpath.nominio.template /nginx.subpath.nominio.template -COPY prod/nginx/nginx.minio.template /nginx.minio.template +COPY prod/nginx/nginx.nominio.template /nginx.nominio.template COPY prod/nginx/nginx.template /nginx.template # hadolint ignore=SC2016