Skip to content

Commit

Permalink
feat: add hover high light
Browse files Browse the repository at this point in the history
  • Loading branch information
nonzzz committed May 29, 2024
1 parent 35dc708 commit 8e1a0e1
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 11 deletions.
13 changes: 10 additions & 3 deletions src/client/components/treemap/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,17 @@ export const Treemap = forwardRef((props: TreemapProps, ref: ForwardedRef<Treema
event.nativeEvent.preventDefault()
if (!event.module) return
handleMousemove({ ...event, module: null })
this.zoom(event.module)
this.zoom(event)
},
onMouseWheel: function onMouseWheel() {
//
onMouseWheel: function onMouseWheel(event) {
// wheelDelta has been deprecated
const { clientX, clientY, deltaY } = event.nativeEvent
const isZoomOut = deltaY > 0
if (isZoomOut) {
// this.zoomOut()
} else {
//
}
}
})
window.addEventListener('resize', resize)
Expand Down
51 changes: 43 additions & 8 deletions src/client/components/treemap/treemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,19 @@ export class Paint {
private layoutNodes: SquarifiedModule[]
private colorMapping: Record<string, string>
private options: PaintOptions
private currentNode: SquarifiedModule | null
private animationFrame: number | null
constructor(data: Module[]) {
this.mainEl = null
this.currentNode = null
this.data = data
this.layoutNodes = []
this.canvas = document.createElement('canvas')
this.context = this.canvas.getContext('2d')!
this.shape = { ...defaultShape }
this.colorMapping = {}
this.options = {}
this.animationFrame = null
}

private drawNodeBackground(node: SquarifiedModule) {
Expand All @@ -66,13 +70,19 @@ export class Paint {

private drawNodeForeground(node: SquarifiedModule) {
const [x, y, w, h] = node.layout

if (this.currentNode === node) {
this.context.fillStyle = 'rgba(255,255,255,0.5)'
this.context.fillRect(x, y, w, h)
}

this.context.strokeStyle = '#222'
this.context.strokeRect(x + 0.5, y + 0.5, w, h)

if (h > STYLES.HEAD_HEIGHT) {
this.context.fillStyle = '#000'
const maxWidth = w - STYLES.INSET_X
const textY = y + Math.round(STYLES.INSET_Y / 2) + 2
const textY = y + Math.round(STYLES.INSET_Y / 2) - 2
const ellipsisWidth = 3 * charCodeWidth(this.context, STYLES.DOT_CHAR_CODE)
const [text, width] = textOverflowEllipsis(this.context, node.node.label, maxWidth, ellipsisWidth)
const textX = x + Math.round((w - width) / 2)
Expand All @@ -94,8 +104,19 @@ export class Paint {
}
}

private smoothDrawing() {
if (!this.animationFrame) {
this.animationFrame = window.requestAnimationFrame(() => {
this.smoothDrawing()
})
}
this.draw()
}

private draw() {
this.animationFrame = null
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
this.context.textBaseline = 'middle'
for (const node of this.layoutNodes) {
this.drawNodeBackground(node)
}
Expand All @@ -104,7 +125,10 @@ export class Paint {
}
}

private eventHandler(e: MouseEvent | WheelEvent, handler: (event: PaintEvent<MouseEvent>) => void) {
private eventHandler<T extends MouseEvent | WheelEvent>(
e: T,
handler: (event: PaintEvent<T>) => void
) {
const layout = findRelativeNode(this.canvas, e, this.layoutNodes)
const event = {
nativeEvent: e,
Expand All @@ -113,6 +137,13 @@ export class Paint {
handler(event)
}

private changeHoverNode(node: SquarifiedModule | null) {
if (this.currentNode !== node) {
this.currentNode = node
this.smoothDrawing()
}
}

private updateColorMapping() {
const colorMapping: Record<string, string> = {}
const defaultSweepAngle = Math.PI * 2
Expand Down Expand Up @@ -142,19 +173,20 @@ export class Paint {
this.colorMapping = colorMapping
}

zoom(node: SquarifiedModule) {
//
zoom(node: PaintEvent<MouseEvent | WheelEvent>) {
}

dispose() {
if (!this.mainEl) return
this.mainEl.removeChild(this.canvas)
this.canvas = null!
this.context = null!
this.currentNode = null
this.shape = { ...defaultShape }
this.data = []
this.layoutNodes = []
this.colorMapping = {}
this.animationFrame = null
}

resize() {
Expand Down Expand Up @@ -188,24 +220,27 @@ export class Paint {
this.canvas.onmousemove = (e) =>
this.eventHandler(e, (evt) => {
this.canvas.style.cursor = 'pointer'
if (evt.module) this.changeHoverNode(evt.module)
this.options.onMousemove?.call(this, evt)
})
this.canvas.onclick = (e) =>
this.eventHandler(e, (evt) => {
this.canvas.style.cursor = 'default'
this.options.onClick?.call(this, evt)
})
this.canvas.onwheel = (e) =>
this.eventHandler(e, (evt) => {
e.preventDefault()
this.options.onMouseWheel?.call(this, evt)
})
this.canvas.onmouseout = () => this.changeHoverNode(null)
}

setup(options: PaintOptions) {
this.options = options
}
}

// manifest is the processed Module module but it's only a temporary data struct.
// It will be re desgined after squarify algorithm is implemented.
// In past we used @carrotsearch/Moduletree it neeed Module struct. But now we won't use it anymore.

export function createTreemap(manifest: Module[]) {
const panit = new Paint(manifest)
return panit
Expand Down

0 comments on commit 8e1a0e1

Please sign in to comment.