Skip to content

Commit 13943e1

Browse files
committed
Working(?) canvas interaction component
1 parent c1615d0 commit 13943e1

File tree

8 files changed

+480
-423
lines changed

8 files changed

+480
-423
lines changed

src/components/InteractionLayer.tsx

Lines changed: 40 additions & 354 deletions
Large diffs are not rendered by default.

src/components/VisualizationLayer.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,6 @@ class VisualizationLayer extends React.PureComponent<Props, State> {
235235
}
236236
else {
237237
const RoughCanvas = sketchyRenderingEngine.canvas
238-
console.log("RoughCanvas", RoughCanvas)
239238
if (!RoughCanvas) {
240239
console.error("The sketchyRenderingEngine you specify does not expose a prop `RoughCanvas` and so cannot render sketchy HTML5 Canvas graphics")
241240
} else {

src/components/XYFrame.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ class XYFrame extends React.Component<XYFrameProps, XYFrameState> {
255255
!!xyFrameDataProps.find(d => props[d] !== nextProps[d])
256256
return calculateXYFrame(nextProps, prevState, dataChanged)
257257
}
258+
return null
258259
}
259260

260261
defaultXYSVGRule = ({
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import * as React from "react"
2+
import { canvasEvent } from "../svg/frameFunctions"
3+
4+
type InteractionCanvasProps = {
5+
height: number,
6+
width: number,
7+
overlayRegions: any,
8+
margin: any,
9+
voronoiHover: Function
10+
}
11+
12+
type InteractionCanvasState = {
13+
ref: any,
14+
interactionContext: any,
15+
overlayRegions: any,
16+
margin: any
17+
}
18+
19+
class InteractionCanvas extends React.Component<InteractionCanvasProps, InteractionCanvasState> {
20+
constructor(props: InteractionCanvasProps) {
21+
super(props)
22+
23+
const {
24+
overlayRegions,
25+
margin } = props
26+
27+
this.state = {
28+
ref: null,
29+
interactionContext: null,
30+
overlayRegions,
31+
margin
32+
}
33+
}
34+
35+
canvasMap: Map<string, number> = new Map()
36+
37+
componentDidMount() {
38+
this.canvasRendering()
39+
}
40+
41+
componentDidUpdate(prevProps: InteractionCanvasProps, prevState: InteractionCanvasState) {
42+
if (this.state.overlayRegions !== prevState.overlayRegions) {
43+
// this.canvasRendering()
44+
}
45+
}
46+
47+
48+
canvasRendering = () => {
49+
50+
const canvasMap = this.canvasMap
51+
const { overlayRegions, interactionContext } = this.state
52+
if (interactionContext === null || !overlayRegions) return
53+
54+
const { height, width } = this.props
55+
const { margin } = this.state
56+
57+
canvasMap.clear()
58+
59+
const interactionContext2D = interactionContext.getContext("2d")
60+
61+
interactionContext2D.imageSmoothingEnabled = false
62+
interactionContext2D.setTransform(1, 0, 0, 1, margin.left, margin.top)
63+
interactionContext2D.clearRect(
64+
-margin.left,
65+
-margin.top,
66+
width,
67+
height
68+
)
69+
70+
interactionContext2D.lineWidth = 1
71+
72+
overlayRegions.forEach((overlay, oi) => {
73+
const interactionRGBA = `rgba(${Math.floor(
74+
Math.random() * 255
75+
)},${Math.floor(Math.random() * 255)},${Math.floor(
76+
Math.random() * 255
77+
)},255)`
78+
79+
canvasMap.set(interactionRGBA, oi)
80+
81+
interactionContext2D.fillStyle = interactionRGBA
82+
interactionContext2D.strokeStyle = interactionRGBA
83+
84+
const p = new Path2D(overlay.props.d)
85+
interactionContext2D.stroke(p)
86+
interactionContext2D.fill(p)
87+
})
88+
}
89+
90+
91+
render() {
92+
const { width, height, voronoiHover } = this.props
93+
const { overlayRegions } = this.state
94+
95+
96+
return <canvas
97+
className="frame-canvas-interaction"
98+
ref={(canvasContext: any) => {
99+
const boundCanvasEvent = canvasEvent.bind(
100+
null,
101+
canvasContext,
102+
overlayRegions,
103+
this.canvasMap
104+
)
105+
if (canvasContext) {
106+
canvasContext.onmousemove = e => {
107+
const overlay = boundCanvasEvent(e)
108+
if (overlay && overlay.props) {
109+
overlay.props.onMouseEnter()
110+
} else {
111+
voronoiHover(null)
112+
}
113+
}
114+
canvasContext.onclick = e => {
115+
const overlay = boundCanvasEvent(e)
116+
if (overlay && overlay.props) {
117+
overlay.props.onClick()
118+
}
119+
}
120+
canvasContext.ondblclick = e => {
121+
const overlay = boundCanvasEvent(e)
122+
if (overlay && overlay.props) {
123+
overlay.props.onDoubleClick()
124+
}
125+
}
126+
}
127+
this.setState({ interactionContext: canvasContext })
128+
}}
129+
style={{
130+
position: "absolute",
131+
left: `0px`,
132+
top: `0px`,
133+
imageRendering: "pixelated",
134+
pointerEvents: "all",
135+
opacity: 0
136+
}}
137+
width={width}
138+
height={height}
139+
/>
140+
}
141+
}
142+
143+
export default InteractionCanvas

0 commit comments

Comments
 (0)