From c78dafd4289fb32d5c7e256b7d481866cd5f4a55 Mon Sep 17 00:00:00 2001 From: Shashank B R Date: Tue, 5 Nov 2024 16:05:40 +0000 Subject: [PATCH] Draw background on genes (#464) * 1. Add backgroud color for topLevelFeature 2. Fix featureInThisRow not Iterable * background for gene * Lighten instead of darken background * Fix strand fill for dark mode --------- Co-authored-by: Garrett Stevens --- .../LinearApolloDisplay/glyphs/GeneGlyph.ts | 100 ++++++++++++------ 1 file changed, 70 insertions(+), 30 deletions(-) diff --git a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/GeneGlyph.ts b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/GeneGlyph.ts index 25b34b32..f8e01be7 100644 --- a/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +++ b/packages/jbrowse-plugin-apollo/src/LinearApolloDisplay/glyphs/GeneGlyph.ts @@ -13,35 +13,49 @@ import { Glyph } from './Glyph' import { boxGlyph } from './BoxGlyph' import { LinearApolloDisplayRendering } from '../stateModel/rendering' -let forwardFill: CanvasPattern | null = null -let backwardFill: CanvasPattern | null = null +let forwardFillLight: CanvasPattern | null = null +let backwardFillLight: CanvasPattern | null = null +let forwardFillDark: CanvasPattern | null = null +let backwardFillDark: CanvasPattern | null = null if ('document' in window) { for (const direction of ['forward', 'backward']) { - const canvas = document.createElement('canvas') - const canvasSize = 10 - canvas.width = canvas.height = canvasSize - const ctx = canvas.getContext('2d') - if (ctx) { - const stripeColor1 = 'rgba(0,0,0,0)' - const stripeColor2 = 'rgba(255,255,255,0.25)' - const gradient = - direction === 'forward' - ? ctx.createLinearGradient(0, canvasSize, canvasSize, 0) - : ctx.createLinearGradient(0, 0, canvasSize, canvasSize) - gradient.addColorStop(0, stripeColor1) - gradient.addColorStop(0.25, stripeColor1) - gradient.addColorStop(0.25, stripeColor2) - gradient.addColorStop(0.5, stripeColor2) - gradient.addColorStop(0.5, stripeColor1) - gradient.addColorStop(0.75, stripeColor1) - gradient.addColorStop(0.75, stripeColor2) - gradient.addColorStop(1, stripeColor2) - ctx.fillStyle = gradient - ctx.fillRect(0, 0, 10, 10) - if (direction === 'forward') { - forwardFill = ctx.createPattern(canvas, 'repeat') - } else { - backwardFill = ctx.createPattern(canvas, 'repeat') + for (const themeMode of ['light', 'dark']) { + const canvas = document.createElement('canvas') + const canvasSize = 10 + canvas.width = canvas.height = canvasSize + const ctx = canvas.getContext('2d') + if (ctx) { + const stripeColor1 = + themeMode === 'light' ? 'rgba(0,0,0,0)' : 'rgba(0,0,0,0.75)' + const stripeColor2 = + themeMode === 'light' ? 'rgba(255,255,255,0.25)' : 'rgba(0,0,0,0.50)' + const gradient = + direction === 'forward' + ? ctx.createLinearGradient(0, canvasSize, canvasSize, 0) + : ctx.createLinearGradient(0, 0, canvasSize, canvasSize) + gradient.addColorStop(0, stripeColor1) + gradient.addColorStop(0.25, stripeColor1) + gradient.addColorStop(0.25, stripeColor2) + gradient.addColorStop(0.5, stripeColor2) + gradient.addColorStop(0.5, stripeColor1) + gradient.addColorStop(0.75, stripeColor1) + gradient.addColorStop(0.75, stripeColor2) + gradient.addColorStop(1, stripeColor2) + ctx.fillStyle = gradient + ctx.fillRect(0, 0, 10, 10) + if (direction === 'forward') { + if (themeMode === 'light') { + forwardFillLight = ctx.createPattern(canvas, 'repeat') + } else { + forwardFillDark = ctx.createPattern(canvas, 'repeat') + } + } else { + if (themeMode === 'light') { + backwardFillLight = ctx.createPattern(canvas, 'repeat') + } else { + backwardFillDark = ctx.createPattern(canvas, 'repeat') + } + } } } } @@ -61,13 +75,34 @@ function draw( const rowHeight = apolloRowHeight const exonHeight = Math.round(0.6 * rowHeight) const cdsHeight = Math.round(0.9 * rowHeight) - const { strand } = feature - const { children } = feature + const { children, min, strand } = feature if (!children) { return } const { apolloSelectedFeature } = session + // Draw background for gene + const topLevelFeatureMinX = + (lgv.bpToPx({ + refName, + coord: min, + regionNumber: displayedRegionIndex, + })?.offsetPx ?? 0) - offsetPx + const topLevelFeatureWidthPx = feature.length / bpPerPx + const topLevelFeatureStartPx = reversed + ? topLevelFeatureMinX - topLevelFeatureWidthPx + : topLevelFeatureMinX + const topLevelFeatureTop = row * rowHeight + const topLevelFeatureHeight = getRowCount(feature) * rowHeight + + ctx.fillStyle = alpha(theme?.palette.background.paper ?? '#ffffff', 0.6) + ctx.fillRect( + topLevelFeatureStartPx, + topLevelFeatureTop, + topLevelFeatureWidthPx, + topLevelFeatureHeight, + ) + // Draw lines on different rows for each mRNA let currentRow = 0 for (const [, mrna] of children) { @@ -102,6 +137,10 @@ function draw( } } + const forwardFill = + theme?.palette.mode === 'dark' ? forwardFillDark : forwardFillLight + const backwardFill = + theme?.palette.mode === 'dark' ? backwardFillDark : backwardFillLight // Draw exon and CDS for each mRNA currentRow = 0 for (const [, child] of children) { @@ -289,7 +328,8 @@ function getFeatureFromLayout( bp: number, row: number, ): AnnotationFeature | undefined { - const featureInThisRow: AnnotationFeature[] = featuresForRow(feature)[row] + const featureInThisRow: AnnotationFeature[] = + featuresForRow(feature)[row] || [] for (const f of featureInThisRow) { let featureObj if (bp >= f.min && bp <= f.max && f.parent) {