diff --git a/packages/text-annotator/src/TextAnnotator.css b/packages/text-annotator/src/TextAnnotator.css index 18ddc567..abfab129 100644 --- a/packages/text-annotator/src/TextAnnotator.css +++ b/packages/text-annotator/src/TextAnnotator.css @@ -15,19 +15,10 @@ html, body { cursor: pointer; } -.r6o-highlight-layer { - left: 0; - position: fixed; - top: 0; - bottom: 0; - width: 100vw; - pointer-events: none; -} - *::selection, ::selection { background: rgba(0, 128, 255, 0.18); } ::-moz-selection, ::-moz-selection{ background: rgba(0, 128, 255, 0.18); -} \ No newline at end of file +} diff --git a/packages/text-annotator/src/highlight/canvas/canvasRenderer.css b/packages/text-annotator/src/highlight/canvas/canvasRenderer.css new file mode 100644 index 00000000..46bf16eb --- /dev/null +++ b/packages/text-annotator/src/highlight/canvas/canvasRenderer.css @@ -0,0 +1,14 @@ +.r6o-canvas-highlight-layer { + position: fixed; + top: 0; + bottom: 0; + left: 0; + width: 100vw; + height: 100vh; + pointer-events: none; +} + +.r6o-canvas-highlight-layer.bg { + mix-blend-mode: multiply; + z-index: 1; +} diff --git a/packages/text-annotator/src/highlight/canvas/canvasRenderer.ts b/packages/text-annotator/src/highlight/canvas/canvasRenderer.ts index 9e7d957b..76237351 100644 --- a/packages/text-annotator/src/highlight/canvas/canvasRenderer.ts +++ b/packages/text-annotator/src/highlight/canvas/canvasRenderer.ts @@ -1,18 +1,20 @@ -import type { ViewportBounds } from '../viewport'; +import type { ViewportState } from '@annotorious/core'; +import type { TextAnnotatorState } from '../../state'; import { debounce } from '../../utils'; +import type { ViewportBounds } from '../viewport'; import type { HighlightStyle } from '../HighlightStyle'; import { DEFAULT_SELECTED_STYLE, DEFAULT_STYLE, HighlightStyleExpression } from '../HighlightStyle'; import type { HighlightPainter } from '../HighlightPainter'; import { createBaseRenderer, type RendererImplementation } from '../baseRenderer'; import type { Highlight } from '../Highlight'; -import type { TextAnnotatorState } from 'src/state'; -import type { ViewportState } from '@annotorious/core'; + +import './canvasRenderer.css'; const createCanvas = () => { const canvas = document.createElement('canvas'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; - canvas.className = 'r6o-highlight-layer bg'; + canvas.className = 'r6o-canvas-highlight-layer bg'; return canvas; } @@ -35,10 +37,10 @@ const createRenderer = (container: HTMLElement): RendererImplementation => { const canvas = createCanvas(); const ctx = canvas.getContext('2d'); - container.insertBefore(canvas, container.firstChild); + document.body.appendChild(canvas); - const redraw = ( - highlights: Highlight[], + const redraw = ( + highlights: Highlight[], viewportBounds: ViewportBounds, currentStyle?: HighlightStyleExpression, currentPainter?: HighlightPainter @@ -65,7 +67,7 @@ const createRenderer = (container: HTMLElement): RendererImplementation => { const { annotation: { target: { created: createdA } } } = highlightA; const { annotation: { target: { created: createdB } } } = highlightB; return createdA.getTime() - createdB.getTime(); - }) + }); highlightsByCreation.forEach(h => { const base: HighlightStyle = currentStyle @@ -90,19 +92,8 @@ const createRenderer = (container: HTMLElement): RendererImplementation => { ctx.fillStyle = style.fill; ctx.globalAlpha = style.fillOpacity || 1; - - /** - * The default browser's selection highlight is a bit taller than the text itself. - * To match it, we need to draw the highlight a bit taller as well. - */ - const selectionHighlightCompensation = 5; offsetRects.forEach(({ x, y, width, height }) => - ctx.fillRect( - x, - y - selectionHighlightCompensation / 2, - width, - height + selectionHighlightCompensation - ) + ctx.fillRect(x, y, width, height) ); if (style.underlineColor) { @@ -111,7 +102,7 @@ const createRenderer = (container: HTMLElement): RendererImplementation => { ctx.lineWidth = style.underlineThickness ?? 1; // Place the underline below the highlighted text + an optional offset - const underlineOffset = selectionHighlightCompensation / 2 + (style.underlineOffset ?? 0); + const underlineOffset = style.underlineOffset ?? 0; offsetRects.forEach(({ x, y, width, height }) => { ctx.beginPath(); @@ -136,7 +127,7 @@ const createRenderer = (container: HTMLElement): RendererImplementation => { } const destroy = () => { - container.removeChild(canvas); + canvas.remove(); window.removeEventListener('resize', onResize); } @@ -145,12 +136,12 @@ const createRenderer = (container: HTMLElement): RendererImplementation => { destroy, setVisible, redraw - } + }; -} +}; export const createCanvasRenderer = ( - container: HTMLElement, + container: HTMLElement, state: TextAnnotatorState, viewport: ViewportState ) => createBaseRenderer(container, state, viewport, createRenderer(container)); diff --git a/packages/text-annotator/src/highlight/highlights/highlightsRenderer.ts b/packages/text-annotator/src/highlight/highlights/highlightsRenderer.ts index 7bb9f2d6..fce33f4a 100644 --- a/packages/text-annotator/src/highlight/highlights/highlightsRenderer.ts +++ b/packages/text-annotator/src/highlight/highlights/highlightsRenderer.ts @@ -30,7 +30,7 @@ export const createRenderer = (): RendererImplementation => { let currentRendered = new Set(); const redraw = ( - highlights: Highlight[], + highlights: Highlight[], viewportBounds: ViewportBounds, currentStyle?: HighlightStyleExpression, painter?: HighlightPainter @@ -46,10 +46,10 @@ export const createRenderer = (): RendererImplementation => { // For simplicity, re-generate the whole stylesheet const updatedCSS = highlights.map(h => { - const base = currentStyle - ? typeof currentStyle === 'function' - ? currentStyle(h.annotation, h.state) - : currentStyle + const base = currentStyle + ? typeof currentStyle === 'function' + ? currentStyle(h.annotation, h.state) + : currentStyle : h.state?.selected ? DEFAULT_SELECTED_STYLE : DEFAULT_STYLE; // Trigger the custom painter (if any) as a side-effect @@ -70,7 +70,7 @@ export const createRenderer = (): RendererImplementation => { // Could be improved further by (re-)setting only annotations that // have changes. - highlights.forEach(({ annotation }) => { + highlights.forEach(({ annotation }) => { const ranges = annotation.target.selector.map(s => s.range); // @ts-ignore @@ -100,12 +100,12 @@ export const createRenderer = (): RendererImplementation => { destroy, setVisible, redraw - } + }; } export const createHighlightsRenderer = ( - container: HTMLElement, + container: HTMLElement, state: TextAnnotatorState, viewport: ViewportState -) => createBaseRenderer(container, state, viewport, createRenderer()); \ No newline at end of file +) => createBaseRenderer(container, state, viewport, createRenderer()); diff --git a/packages/text-annotator/src/highlight/span/spansRenderer.css b/packages/text-annotator/src/highlight/span/spansRenderer.css index 611a46ba..9492abd3 100644 --- a/packages/text-annotator/src/highlight/span/spansRenderer.css +++ b/packages/text-annotator/src/highlight/span/spansRenderer.css @@ -1,10 +1,10 @@ .r6o-annotatable .r6o-span-highlight-layer { - height: 100%; - left: 0; - pointer-events: none; position: absolute; top: 0; + left: 0; width: 100%; + height: 100%; + pointer-events: none; } .r6o-annotatable .r6o-span-highlight-layer.hidden { diff --git a/packages/text-annotator/src/presence/PresencePainter.css b/packages/text-annotator/src/presence/PresencePainter.css new file mode 100644 index 00000000..f665f91f --- /dev/null +++ b/packages/text-annotator/src/presence/PresencePainter.css @@ -0,0 +1,8 @@ +.r6o-presence-layer { + left: 0; + position: fixed; + top: 0; + bottom: 0; + width: 100vw; + pointer-events: none; +} \ No newline at end of file diff --git a/packages/text-annotator/src/presence/PresencePainter.ts b/packages/text-annotator/src/presence/PresencePainter.ts index 61c4d466..541d189d 100644 --- a/packages/text-annotator/src/presence/PresencePainter.ts +++ b/packages/text-annotator/src/presence/PresencePainter.ts @@ -1,17 +1,18 @@ import type { Color, PresenceProvider, PresentUser } from '@annotorious/core'; import type { AnnotationRects } from '../state'; -import type { HighlightStyle } from '../highlight/HighlightStyle'; -import type { HighlightPainter } from '../highlight/HighlightPainter'; -import type { PresencePainterOptions } from 'src/presence'; +import type { HighlightStyle, HighlightPainter } from '../highlight'; +import type { PresencePainterOptions } from '../presence'; import type { ViewportBounds } from '../highlight/viewport'; +import './PresencePainter.css'; + const createCanvas = () => { const canvas = document.createElement('canvas'); // Retina resolution for crisp font rendering canvas.width = 2 * window.innerWidth; canvas.height = 2 * window.innerHeight; - canvas.className = 'r6o-highlight-layer presence'; + canvas.className = 'r6o-presence-layer'; const context = canvas.getContext('2d'); context.scale(2, 2); @@ -30,7 +31,7 @@ export const createPresencePainter = ( const ctx = canvas.getContext('2d'); - container.appendChild(canvas); + document.body.appendChild(canvas); const trackedAnnotations = new Map(); @@ -115,4 +116,4 @@ export const createPresencePainter = ( reset } -} \ No newline at end of file +} diff --git a/packages/text-annotator/test/annotations.w3c.json b/packages/text-annotator/test/annotations.w3c.json index a2c81216..96c888dd 100644 --- a/packages/text-annotator/test/annotations.w3c.json +++ b/packages/text-annotator/test/annotations.w3c.json @@ -143,4 +143,4 @@ } ] } -] \ No newline at end of file +]