Implement canvas-based mistake highlighting in BesService

- There's still a work to be done, but IMO it is a step inthe right direction
This commit is contained in:
Aljaž Grilc 2025-02-12 18:17:12 +01:00
parent c68e512496
commit d773682eeb
2 changed files with 77 additions and 15 deletions

View File

@ -331,25 +331,76 @@ class BesService {
* @returns {Array} Grammar mistake highlight elements * @returns {Array} Grammar mistake highlight elements
*/ */
addMistakeMarkup(range, ruleId) { addMistakeMarkup(range, ruleId) {
const scrollPanelRect = this.scrollPanel.getBoundingClientRect() const canvasPanelRect = this.canvasPanel.getBoundingClientRect()
let highlights = [] console.log(canvasPanelRect)
for (let rect of range.getClientRects()) { const highlights = []
const highlight = document.createElement('div') this.canvasPanel.classList.add('bes-canvas')
highlight.classList.add( const ctx = this.canvasPanel.getContext('2d')
ruleId.startsWith('MORFOLOGIK_RULE') ctx.lineWidth = 2
? 'bes-spelling-mistake' ctx.strokeStyle = ruleId.startsWith('MORFOLOGIK_RULE')
: 'bes-grammar-mistake' ? '#e91313'
) : '#269b26'
highlight.style.left = `${rect.left - scrollPanelRect.left}px`
highlight.style.top = `${rect.top - scrollPanelRect.top}px` // Set the canvas dimensions and scale the context only once
highlight.style.width = `${rect.width}px` if (!this.canvasInitialized) {
highlight.style.height = `${rect.height}px` const dpr = window.devicePixelRatio || 1
this.scrollPanel.appendChild(highlight) this.canvasPanel.width = canvasPanelRect.width * dpr
highlights.push(highlight) this.canvasPanel.height = canvasPanelRect.height * dpr
this.canvasPanel.style.width = `${canvasPanelRect.width}px`
this.canvasPanel.style.height = `${canvasPanelRect.height}px`
const ctx = this.canvasPanel.getContext('2d')
ctx.scale(dpr, dpr)
this.canvasInitialized = true
} }
for (let rect of range.getClientRects()) {
console.log(rect)
const x = rect.left - canvasPanelRect.left
const y = rect.top - canvasPanelRect.top + rect.height
const width = rect.width
console.log('rect.left: ', rect.left)
console.log('canvasPanelRect.left: ', canvasPanelRect.left)
console.log('x: ', x)
console.log('y: ', y)
console.log('width: ', width)
// Draw the underline
ctx.beginPath()
ctx.moveTo(x, y)
ctx.lineTo(x + width, y)
ctx.stroke()
}
return highlights return highlights
} }
// addMistakeMarkup(range, ruleId) {
// const scrollPanelRect = this.scrollPanel.getBoundingClientRect()
// let highlights = []
// for (let rect of range.getClientRects()) {
// const highlight = document.createElement('div')
// highlight.classList.add(
// ruleId.startsWith('MORFOLOGIK_RULE')
// ? 'bes-spelling-mistake'
// : 'bes-grammar-mistake'
// )
// highlight.style.left = `${rect.left - scrollPanelRect.left}px`
// highlight.style.top = `${rect.top - scrollPanelRect.top}px`
// highlight.style.width = `${rect.width}px`
// highlight.style.height = `${rect.height}px`
// this.scrollPanel.appendChild(highlight)
// highlights.push(highlight)
// }
// return highlights
// }
// highlight.style.left = `${rect.left - scrollPanelRect.left}px`
// highlight.style.top = `${rect.top - scrollPanelRect.top}px`
// highlight.style.width = `${rect.width}px`
// highlight.style.height = `${rect.height}px`
// this.scrollPanel.appendChild(highlight)
// highlights.push(highlight)
/** /**
* Tests if given coordinate is inside of a rectangle. * Tests if given coordinate is inside of a rectangle.
* *
@ -375,8 +426,11 @@ class BesService {
this.scrollPanel = document.createElement('div') this.scrollPanel = document.createElement('div')
this.scrollPanel.classList.add('bes-correction-panel-scroll') this.scrollPanel.classList.add('bes-correction-panel-scroll')
this.canvasPanel = document.createElement('canvas')
panelParent.appendChild(this.correctionPanel) panelParent.appendChild(this.correctionPanel)
this.correctionPanel.appendChild(this.scrollPanel) this.correctionPanel.appendChild(this.scrollPanel)
this.scrollPanel.appendChild(this.canvasPanel)
this.textElement.parentElement.insertBefore(panelParent, this.textElement) this.textElement.parentElement.insertBefore(panelParent, this.textElement)
this.setCorrectionPanelSize() this.setCorrectionPanelSize()
} }
@ -404,6 +458,8 @@ class BesService {
this.correctionPanel.style.paddingBottom = styles.paddingBottom this.correctionPanel.style.paddingBottom = styles.paddingBottom
this.scrollPanel.style.width = `${this.hostElement.scrollWidth}px` this.scrollPanel.style.width = `${this.hostElement.scrollWidth}px`
this.scrollPanel.style.height = `${this.hostElement.scrollHeight}px` this.scrollPanel.style.height = `${this.hostElement.scrollHeight}px`
this.canvasPanel.style.width = `${this.hostElement.scrollWidth}px`
this.canvasPanel.style.height = `${this.hostElement.scrollHeight}px`
if (this.isHostElementInline()) { if (this.isHostElementInline()) {
const totalWidth = const totalWidth =
parseFloat(styles.paddingLeft) + parseFloat(styles.paddingLeft) +

View File

@ -15,6 +15,12 @@
cursor: text; cursor: text;
} }
.bes-canvas {
position: relative;
z-index: 3;
cursor: text;
}
.bes-spelling-mistake.bes-mistake-highlight-selected { .bes-spelling-mistake.bes-mistake-highlight-selected {
background: #cc7024; background: #cc7024;
opacity: 0.5; opacity: 0.5;