@@ -42,22 +42,99 @@ type Props = {
4242 customDoubleClickBehavior ?: Function ,
4343 customClickBehavior ?: Function ,
4444 customHoverBehavior ?: Function ,
45- voronoiHover : Function
45+ voronoiHover : Function ,
46+ canvasRendering ?: boolean
4647}
4748
4849type State = {
49- overlayRegions : Node
50+ overlayRegions : Array < Node > ,
51+ interactionCanvas : Node
5052}
5153
5254class InteractionLayer extends React . Component < Props , State > {
5355 constructor ( props : Props ) {
5456 super ( props )
5557
58+ // $FlowFixMe
5659 this . state = {
57- overlayRegions : this . calculateOverlay ( props )
60+ overlayRegions : this . calculateOverlay ( props ) ,
61+ interactionCanvas : (
62+ < canvas
63+ className = "frame-canvas-interaction"
64+ ref = { canvasContext => {
65+ if ( canvasContext ) {
66+ canvasContext . onmousemove = e => {
67+ const interactionContext = canvasContext . getContext ( "2d" )
68+ const hoverPoint = interactionContext . getImageData (
69+ e . offsetX ,
70+ e . offsetY ,
71+ 1 ,
72+ 1
73+ )
74+
75+ const mostCommonRGB = `rgba(${ hoverPoint . data [ 0 ] } ,${
76+ hoverPoint . data [ 1 ]
77+ } ,${ hoverPoint . data [ 2 ] } ,255)`
78+
79+ // $FlowFixMe
80+ let overlay = this . state . overlayRegions [
81+ this . canvasMap . get ( mostCommonRGB )
82+ ]
83+ if ( ! overlay ) {
84+ const hoverArea = interactionContext . getImageData (
85+ e . offsetX - 2 ,
86+ e . offsetY - 2 ,
87+ 5 ,
88+ 5
89+ )
90+ let x = 0
91+
92+ while ( ! overlay && x < 100 ) {
93+ // $FlowFixMe
94+ overlay = this . state . overlayRegions [
95+ this . canvasMap . get (
96+ `rgba(${ hoverArea . data [ x ] } ,${ hoverArea . data [ x + 1 ] } ,${
97+ hoverArea . data [ x + 2 ]
98+ } ,255)`
99+ )
100+ ]
101+ x += 4
102+ }
103+ }
104+
105+ // $FlowFixMe
106+ if ( overlay && overlay . props ) {
107+ overlay . props . onMouseEnter ( )
108+ } else {
109+ this . changeVoronoi ( )
110+ }
111+ }
112+ }
113+ this . interactionContext = canvasContext
114+ } }
115+ style = { {
116+ position : "absolute" ,
117+ left : `0px` ,
118+ top : `0px` ,
119+ imageRendering : "pixelated" ,
120+ pointerEvents : "all" ,
121+ opacity : 0
122+ } }
123+ width = { props . svgSize [ 0 ] }
124+ height = { props . svgSize [ 1 ] }
125+ />
126+ )
58127 }
59128 }
60129
130+ static defaultProps = {
131+ svgSize : [ 500 , 500 ]
132+ }
133+
134+ interactionContext = null
135+
136+ canvasMap : Map < string , number > = new Map ( )
137+
61138 changeVoronoi = ( d ? : Object , customHoverTypes ? : CustomHoverType ) => {
62139 //Until semiotic 2
63140 const dataObject = d && d . data ? { ...d . data , ...d } : d
@@ -427,6 +504,55 @@ class InteractionLayer extends React.Component<Props, State> {
427504 }
428505 }
429506
507+ componentDidMount ( ) {
508+ this . canvasRendering ( )
509+ }
510+
511+ componentDidUpdate(prevProps: Props, prevState: State) {
512+ if ( this . state . overlayRegions !== prevState . overlayRegions ) {
513+ this . canvasRendering ( )
514+ }
515+ }
516+
517+ canvasRendering = ( ) => {
518+ if ( this . interactionContext === null || ! this . state . overlayRegions ) return
519+
520+ const { svgSize , margin } = this.props
521+ const { overlayRegions } = this.state
522+
523+ this.canvasMap.clear()
524+
525+ // $FlowFixMe
526+ const interactionContext = this.interactionContext.getContext("2d")
527+
528+ interactionContext.imageSmoothingEnabled = false
529+ interactionContext.setTransform(1, 0, 0, 1, margin.left, margin.top)
530+ interactionContext.clearRect(
531+ -margin.left,
532+ -margin.top,
533+ svgSize[0],
534+ svgSize[1]
535+ )
536+
537+ interactionContext.lineWidth = 1
538+
539+ overlayRegions.forEach((overlay, oi) => {
540+ const interactionRGBA = `rgba(${ parseInt ( Math . random ( ) * 255 ) } ,${ parseInt (
541+ Math . random ( ) * 255
542+ ) } ,${ parseInt ( Math . random ( ) * 255 ) } ,255)`
543+
544+ this . canvasMap . set ( interactionRGBA , oi )
545+
546+ interactionContext . fillStyle = interactionRGBA
547+ interactionContext . strokeStyle = interactionRGBA
548+
549+ // $FlowFixMe
550+ const p = new Path2D ( overlay . props . d )
551+ interactionContext . stroke ( p )
552+ interactionContext . fill ( p )
553+ } )
554+ }
555+
430556 createColumnsBrush = ( interaction : Object ) => {
431557 const { projection, rScale, size, oColumns } = this . props
432558
@@ -510,7 +636,13 @@ class InteractionLayer extends React.Component<Props, State> {
510636
511637 render ( ) {
512638 let semioticBrush = null
513- const { interaction , svgSize , margin , useSpans = false } = this . props
639+ const {
640+ interaction ,
641+ svgSize ,
642+ margin ,
643+ useSpans = false ,
644+ canvasRendering
645+ } = this.props
514646 const { overlayRegions } = this.state
515647 let { enabled } = this.props
516648
@@ -527,6 +659,11 @@ class InteractionLayer extends React.Component<Props, State> {
527659 return null
528660 }
529661
662+ const interactionCanvas =
663+ canvasRendering &&
664+ this . state . overlayRegions &&
665+ this . state . interactionCanvas
666+
530667 return (
531668 < SpanOrDiv
532669 span = { useSpans }
@@ -537,20 +674,22 @@ class InteractionLayer extends React.Component<Props, State> {
537674 pointerEvents : "none"
538675 } }
539676 >
540- < svg
541- height = { svgSize [ 1 ] }
542- width = { svgSize [ 0 ] }
543- style = { { background : "none" , pointerEvents : "none" } }
544- >
545- < g
546- className = "interaction-overlay"
547- transform = { `translate(${ margin . left } ,${ margin . top } )` }
548- style = { { pointerEvents : enabled ? "all" : "none" } }
677+ { interactionCanvas || (
678+ < svg
679+ height = { svgSize [ 1 ] }
680+ width = { svgSize [ 0 ] }
681+ style = { { background : "none" , pointerEvents : "none" } }
549682 >
550- < g className = "interaction-regions" > { overlayRegions } </ g >
551- { semioticBrush }
552- </ g >
553- </ svg >
683+ < g
684+ className = "interaction-overlay"
685+ transform = { `translate(${ margin . left } ,${ margin . top } )` }
686+ style = { { pointerEvents : enabled ? "all" : "none" } }
687+ >
688+ < g className = "interaction-regions" > { overlayRegions } </ g >
689+ { semioticBrush }
690+ </ g >
691+ </ svg >
692+ ) }
554693 </ SpanOrDiv >
555694 )
556695 }
0 commit comments