Optimize canvas highlight rendering
This commit is contained in:
parent
d773682eeb
commit
6fb6503e73
92
service.js
92
service.js
@ -279,7 +279,6 @@ class BesService {
|
|||||||
// Scroll panel is "position: absolute", we need to keep it aligned with the host element.
|
// Scroll panel is "position: absolute", we need to keep it aligned with the host element.
|
||||||
this.scrollPanel.style.top = `${-this.hostElement.scrollTop}px`
|
this.scrollPanel.style.top = `${-this.hostElement.scrollTop}px`
|
||||||
this.scrollPanel.style.left = `${-this.hostElement.scrollLeft}px`
|
this.scrollPanel.style.left = `${-this.hostElement.scrollLeft}px`
|
||||||
|
|
||||||
if (this.hostElement !== this.textElement) {
|
if (this.hostElement !== this.textElement) {
|
||||||
this.textElement.scrollTop = this.hostElement.scrollTop
|
this.textElement.scrollTop = this.hostElement.scrollTop
|
||||||
this.textElement.scrollLeft = this.hostElement.scrollLeft
|
this.textElement.scrollLeft = this.hostElement.scrollLeft
|
||||||
@ -332,44 +331,31 @@ class BesService {
|
|||||||
*/
|
*/
|
||||||
addMistakeMarkup(range, ruleId) {
|
addMistakeMarkup(range, ruleId) {
|
||||||
const canvasPanelRect = this.canvasPanel.getBoundingClientRect()
|
const canvasPanelRect = this.canvasPanel.getBoundingClientRect()
|
||||||
console.log(canvasPanelRect)
|
|
||||||
const highlights = []
|
const highlights = []
|
||||||
this.canvasPanel.classList.add('bes-canvas')
|
this.canvasPanel.classList.add('bes-canvas')
|
||||||
const ctx = this.canvasPanel.getContext('2d')
|
const ctx = this.canvasPanel.getContext('2d')
|
||||||
ctx.lineWidth = 2
|
ctx.lineWidth = 1
|
||||||
ctx.strokeStyle = ruleId.startsWith('MORFOLOGIK_RULE')
|
ctx.strokeStyle = ruleId.startsWith('MORFOLOGIK_RULE')
|
||||||
? '#e91313'
|
? '#e91313'
|
||||||
: '#269b26'
|
: '#269b26'
|
||||||
|
|
||||||
// Set the canvas dimensions and scale the context only once
|
this.setCanvasDpr()
|
||||||
if (!this.canvasInitialized) {
|
|
||||||
const dpr = window.devicePixelRatio || 1
|
|
||||||
this.canvasPanel.width = canvasPanelRect.width * dpr
|
|
||||||
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()) {
|
for (let rect of range.getClientRects()) {
|
||||||
console.log(rect)
|
|
||||||
const x = rect.left - canvasPanelRect.left
|
const x = rect.left - canvasPanelRect.left
|
||||||
const y = rect.top - canvasPanelRect.top + rect.height
|
const y = rect.top - canvasPanelRect.top + rect.height
|
||||||
const width = rect.width
|
const width = rect.width
|
||||||
|
const height = rect.height
|
||||||
|
|
||||||
console.log('rect.left: ', rect.left)
|
const globalX = rect.left + window.scrollX
|
||||||
console.log('canvasPanelRect.left: ', canvasPanelRect.left)
|
const globalY = rect.top + window.scrollY
|
||||||
console.log('x: ', x)
|
|
||||||
console.log('y: ', y)
|
|
||||||
console.log('width: ', width)
|
|
||||||
|
|
||||||
// Draw the underline
|
// Draw the underline
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
ctx.moveTo(x, y)
|
ctx.moveTo(x, y)
|
||||||
ctx.lineTo(x + width, y)
|
ctx.lineTo(x + width, y)
|
||||||
ctx.stroke()
|
ctx.stroke()
|
||||||
|
const rectCoords = { x, y, width, height, globalX, globalY }
|
||||||
|
highlights.push(rectCoords)
|
||||||
}
|
}
|
||||||
|
|
||||||
return highlights
|
return highlights
|
||||||
@ -410,7 +396,15 @@ class BesService {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
static isPointInRect(x, y, rect) {
|
static isPointInRect(x, y, rect) {
|
||||||
return rect.left <= x && x < rect.right && rect.top <= y && y < rect.bottom
|
const globalWidth = rect.globalX + rect.width
|
||||||
|
const globalHeight = rect.globalY + rect.height
|
||||||
|
return (
|
||||||
|
rect.globalX <= x &&
|
||||||
|
x < globalWidth &&
|
||||||
|
rect.globalY <= y &&
|
||||||
|
y < globalHeight
|
||||||
|
)
|
||||||
|
// return rect.left <= x && x < rect.right && rect.top <= y && y < rect.bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -460,6 +454,7 @@ class BesService {
|
|||||||
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.width = `${this.hostElement.scrollWidth}px`
|
||||||
this.canvasPanel.style.height = `${this.hostElement.scrollHeight}px`
|
this.canvasPanel.style.height = `${this.hostElement.scrollHeight}px`
|
||||||
|
this.setCanvasDpr()
|
||||||
if (this.isHostElementInline()) {
|
if (this.isHostElementInline()) {
|
||||||
const totalWidth =
|
const totalWidth =
|
||||||
parseFloat(styles.paddingLeft) +
|
parseFloat(styles.paddingLeft) +
|
||||||
@ -475,6 +470,18 @@ class BesService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets canvas panel device pixel ratio.
|
||||||
|
*/
|
||||||
|
setCanvasDpr() {
|
||||||
|
const ctx = this.canvasPanel.getContext('2d')
|
||||||
|
const dpr = window.devicePixelRatio || 1
|
||||||
|
const canvasPanelRect = this.canvasPanel.getBoundingClientRect()
|
||||||
|
this.canvasPanel.width = canvasPanelRect.width * dpr
|
||||||
|
this.canvasPanel.height = canvasPanelRect.height * dpr
|
||||||
|
ctx.scale(dpr, dpr)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays correction panel.
|
* Displays correction panel.
|
||||||
*
|
*
|
||||||
@ -496,12 +503,12 @@ class BesService {
|
|||||||
* @param {*} match Grammar checking rule match
|
* @param {*} match Grammar checking rule match
|
||||||
*/
|
*/
|
||||||
highlightMistake(match) {
|
highlightMistake(match) {
|
||||||
document.querySelectorAll('.bes-mistake-highlight-selected').forEach(el => {
|
// document.querySelectorAll('.bes-mistake-highlight-selected').forEach(el => {
|
||||||
el.classList.remove('bes-mistake-highlight-selected')
|
// el.classList.remove('bes-mistake-highlight-selected')
|
||||||
})
|
// })
|
||||||
match.highlights.forEach(h =>
|
// match.highlights.forEach(h =>
|
||||||
h.classList.add('bes-mistake-highlight-selected')
|
// h.classList.add('bes-mistake-highlight-selected')
|
||||||
)
|
// )
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -522,9 +529,18 @@ class BesService {
|
|||||||
* Updates all grammar mistake markup positions.
|
* Updates all grammar mistake markup positions.
|
||||||
*/
|
*/
|
||||||
repositionAllMarkup() {
|
repositionAllMarkup() {
|
||||||
|
const ctx = this.canvasPanel.getContext('2d')
|
||||||
|
|
||||||
this.results.forEach(result => {
|
this.results.forEach(result => {
|
||||||
result.matches.forEach(match => {
|
result.matches.forEach(match => {
|
||||||
if (match.highlights) match.highlights.forEach(h => h.remove())
|
if (match.highlights) {
|
||||||
|
match.highlights.forEach(h => {
|
||||||
|
ctx.clearRect(h.x - 2, h.y - 2, h.width + 4, h.height)
|
||||||
|
})
|
||||||
|
|
||||||
|
delete match.highlights
|
||||||
|
// match.highlights.forEach(h => h.remove())
|
||||||
|
}
|
||||||
match.highlights = this.addMistakeMarkup(
|
match.highlights = this.addMistakeMarkup(
|
||||||
match.range,
|
match.range,
|
||||||
match.match.rule.id
|
match.match.rule.id
|
||||||
@ -783,12 +799,20 @@ class BesTreeService extends BesService {
|
|||||||
* @param {Element} el DOM element we want to clean markup for
|
* @param {Element} el DOM element we want to clean markup for
|
||||||
*/
|
*/
|
||||||
clearMarkup(el) {
|
clearMarkup(el) {
|
||||||
|
const ctx = this.canvasPanel.getContext('2d')
|
||||||
|
|
||||||
this.results
|
this.results
|
||||||
.filter(result => BesTreeService.isSameParagraph(result.element, el))
|
.filter(result => BesTreeService.isSameParagraph(result.element, el))
|
||||||
.forEach(result =>
|
.forEach(result =>
|
||||||
result.matches.forEach(match => {
|
result.matches.forEach(match => {
|
||||||
|
console.log(match)
|
||||||
if (match.highlights) {
|
if (match.highlights) {
|
||||||
match.highlights.forEach(h => h.remove())
|
// match.highlights.forEach(h => h.remove())
|
||||||
|
match.highlights.forEach(h => {
|
||||||
|
console.log(h)
|
||||||
|
// Figure out why i need to add 2px to width
|
||||||
|
ctx.clearRect(h.x - 2, h.y - 2, h.width + 4, h.height)
|
||||||
|
})
|
||||||
delete match.highlights
|
delete match.highlights
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -932,13 +956,7 @@ class BesTreeService extends BesService {
|
|||||||
for (let result of this.results) {
|
for (let result of this.results) {
|
||||||
for (let m of result.matches) {
|
for (let m of result.matches) {
|
||||||
for (let h of m.highlights) {
|
for (let h of m.highlights) {
|
||||||
if (
|
if (BesService.isPointInRect(source.clientX, source.clientY, h)) {
|
||||||
BesService.isPointInRect(
|
|
||||||
source.clientX,
|
|
||||||
source.clientY,
|
|
||||||
h.getBoundingClientRect()
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
this.popupCorrectionPanel(el, m, source)
|
this.popupCorrectionPanel(el, m, source)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user