Skip to content

Commit

Permalink
Use two canvases, one for the slider and one for the text
Browse files Browse the repository at this point in the history
  • Loading branch information
smolck committed May 11, 2021
1 parent 802b3d1 commit 44ff64a
Showing 1 changed file with 54 additions and 32 deletions.
86 changes: 54 additions & 32 deletions src/renderer/components/extensions/minimap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,20 @@ const Minimap = ({ visible }: { visible: boolean }) => {
<PluginRight
visible={visible}
setBackground={false}
extraStyle={{ background: colors.background }}
extraStyle={{ background: colors.background, position: 'relative' }}
width={'150px'}
>
<canvas id="minimap-canvas" style="height: 100%;"/>
<canvas id="minimap-canvas" style={{
'z-index': 1,
height: '100%',
}}/>
<canvas id="minimap-canvas-viewport-slider" style={{
'z-index': 2,
top: 0,
left: 0,
height: '100%',
position: 'absolute',
}}/>
</PluginRight>
)
}
Expand All @@ -51,65 +61,77 @@ const container = document.createElement('div')
container.id = 'minimap'
document.getElementById('plugins')!.appendChild(container)

let ctxCache: CanvasRenderingContext2D
let canvasCache: HTMLCanvasElement
let ctx: CanvasRenderingContext2D
let canvas: HTMLCanvasElement
let linesAndHighlightsCache: any[]

// https://stackoverflow.com/a/18053642
const onClick = (event: MouseEvent) => {
const rect = canvasCache.getBoundingClientRect()
const rect = canvas.getBoundingClientRect()
// const x = event.clientX - rect.left
const y = event.clientY - rect.top

const height = canvasCache.height / 200
const height = canvas.height / 200
const row = Math.floor(y / height)
window.api.invoke(Invokables.nvimJumpTo, { line: row })
}

const update = (viewport: any, linesAndHighlights?: any[]) => {
const update = (linesAndHighlights?: any[]) => {
if (linesAndHighlights) linesAndHighlightsCache = linesAndHighlights

if (!isVisible) render(<Minimap visible={true} />, container)
if (!ctxCache || !canvasCache) {
const canvas = (document.getElementById('minimap-canvas') as HTMLCanvasElement)
const ctx = canvas.getContext('2d')!!
ctxCache = ctx
canvasCache = canvas
ctxCache.scale(window.devicePixelRatio, window.devicePixelRatio)
if (!ctx || !canvas) {
canvas = document.getElementById('minimap-canvas') as HTMLCanvasElement
ctx = canvas.getContext('2d')!!
ctx.scale(window.devicePixelRatio, window.devicePixelRatio)

// https://stackoverflow.com/a/48309022
canvas.width = canvas.getBoundingClientRect().width;
canvas.height = canvas.getBoundingClientRect().height;

canvas.addEventListener('click', onClick)
}

// Background
ctxCache.beginPath()
ctxCache.fillStyle = colors.background
ctxCache.fillRect(0, 0, canvasCache.width, canvasCache.height)

const width = canvasCache.width / 80
const height = canvasCache.height / 200
ctx.beginPath()
ctx.fillStyle = colors.background
ctx.fillRect(0, 0, canvas.width, canvas.height)

// Viewport
ctxCache.beginPath()
ctxCache.fillStyle = lightenOrDarkenColor(colors.background, 30)
ctxCache.fillRect(0, viewport.topline * height, canvasCache.width,
(viewport.botline * height) - (viewport.topline * height))
const width = canvas.width / 80
const height = canvas.height / 200

ctxCache.beginPath()
ctx.beginPath()
linesAndHighlightsCache.forEach((line: any[], row) => {
line.forEach((char, col) => {
ctxCache.fillStyle = (char.hl ? asColor(char.hl.foreground) : colors.background)!!
ctxCache.font = `2px ${font.face}`
ctxCache.fillText(char, col * width, row * height, width)
ctx.fillStyle = (char.hl ? asColor(char.hl.foreground) : colors.background)!!
ctx.font = `2px ${font.face}`
ctx.fillText(char, col * width, row * height, width)
})
})
}

window.api.on(Events.minimap, (linesAndHighlights: any[], viewport) => update(viewport, linesAndHighlights))
window.api.on(Events.minimapUpdate, (viewport) => update(viewport))
let sliderCtx: CanvasRenderingContext2D
let sliderCanvas: HTMLCanvasElement
const updateViewport = (viewport: any) => {
if (!sliderCtx || !sliderCanvas) {
sliderCanvas = document.getElementById('minimap-canvas-viewport-slider') as HTMLCanvasElement
sliderCtx = sliderCanvas.getContext('2d')!!
sliderCanvas.width = sliderCanvas.getBoundingClientRect().width
sliderCanvas.height = sliderCanvas.getBoundingClientRect().height
sliderCanvas.addEventListener('click', onClick)
}

const height = canvas.height / 200
sliderCtx.clearRect(0, 0, sliderCanvas.width, sliderCanvas.height)

// Viewport
sliderCtx.beginPath()
sliderCtx.globalAlpha = 0.8
sliderCtx.fillStyle = lightenOrDarkenColor(colors.background, 30)
sliderCtx.fillRect(0, viewport.topline * height, canvas.width, (viewport.botline * height) - (viewport.topline * height))
}

window.api.on(Events.minimap, (linesAndHighlights: any[], viewport) =>
(update(linesAndHighlights), updateViewport(viewport)))
window.api.on(Events.minimapUpdate, (viewport) => updateViewport(viewport))

window.api.on(Events.minimapHide, () =>
render(<Minimap visible={false} />, container)
Expand Down

0 comments on commit 44ff64a

Please sign in to comment.