1
votes

I am using React Konva 1.1.6 and learning how to use it. In the following code, I am trying to show a label near the mouse pointer every time my mouse passes over the konva arrow. Yet, my label just disappears. Am I missing something in my code? I tried using e.nativeEvent but I get an error.

import { Stage, Layer, Rect, Circle, Text, Tag, Arrow, Shape, TextPath, Label, Arc, Ellipse } from 'react-konva';
import Konva from 'konva';

class ColoredRect extends React.Component {
 constructor(props) {
    super(props);
    this.state = {
        color: 'green',
        label: '',
        x: '',
        y: ''
    };


    this.handleClick = () => {
        this.setState({
                color: Konva.Util.getRandomColor()
            });
    };


 }

  render() {
    return (
      <Rect
        x={20}
        y={20}
        width={50}
        height={50}
        fill={this.state.color}
        shadowBlur={5}
        onClick={this.handleClick}
      />
    );
  }
}

class App extends React.Component {
 constructor(props) {
    super(props);
    this.state = {
        color: 'green',
        label: '',
        mouse_x: '',
        mouse_y: '',
        label_x: 100,
        label_y: 300
    };

   this._onMouseMove = (e) => {

     console.log('moved mouse = -------------------- ' + 3207);
     console.log(e);   
     console.log(e.nativeEvent);   
     e.preventDefault;
     this.setState({  mouse_x: e.screenX, mouse_y: e.screenY });
   }    

 }



  render() {
    return (
        <div >
                  <Stage onMouseMove={this._onMouseMove}  width={window.innerWidth} height={window.innerHeight}>
                    <Layer>
                      <Text text="Try click on rect" />
                      <ColoredRect />
                      <Circle
                          x={window.innerWidth / 4}
                          y={window.innerHeight / 4}
                          radius={70}
                          fill={'red'}
                          stroke={'black'}
                          strokeWidth={4}
                          onClick={() => {alert('Cliked me') }}
                       />
                       <Text 
                          text={'Test Text position'}
                          x={window.innerWidth / 4}
                          y={window.innerHeight / 4}
                          fontSize={30}
                          fontFamily={'Arial'}
                          fill={'green'}
                          onClick={() => {alert('text??') }}
                       />

                       <Arrow
                          x={window.innerWidth / 4}
                          y={window.innerHeight / 4}
                          points={[0,0, window.innerWidth / 2, window.innerHeight / 2]}
                          pointerLength={3}
                          pointerWidth={3}
                          fill={'black'}
                          stroke={'blue'}
                          strokeWidth={80}   
                          onMouseover={() => {this.setState({label: 'x=' + this.state.mouse_x + ', ' + 'y= ' + this.state.mouse_y,
                                                             label_x: this.state.mouse_x,
                                                             label_y: this.state.mouse_y
                                                           }, () => {console.log('label=' + this.state.label)}) }}
                       />

                       <Shape
                          x={5}
                          y={500}
                          fill={'green'}
                          sceneFunc= {(context, shape) => {
                                            context.beginPath();
                                            context.moveTo(200, 50);
                                            context.lineTo(420, 80);
                                            context.quadraticCurveTo(300, 100, 260, 170);
                                            context.closePath();
                                            // Konva specific method
                                            context.fillStrokeShape(shape);
                                    }           
                                  }   
                       />

                       <TextPath
                           x={0}
                           y={50}
                           fill={'#333'}
                           fontSize={16}
                           text={'All the world\'s a stage, and all the men and women merely players.'}
                           data={'M10,10 C0,0 10,150 100,100 S300,150 400,50'}
                       />

                    </Layer>

                    <Layer>


                       <Label
                        x={this.state.label_x}
                        y={this.state.label_y}>

                        <Tag
                            fill={'black'}

                            fontFamily={'Calibri'}
                            fontSize={18}
                            padding={5}
                            pointerDirection={'down'}
                            pointerWidth={10}
                            pointerHeight={10}
                            lineJoin={'round'}
                            shadowColor={'black'}
                            shadowBlur={10}
                            shadowOffset={10}
                            shadowOpacity={0.5}                                   
                          />    
                        <Text

                               text={this.state.label}
                                fontFamily={'Calibri'}
                                fontSize={18}
                                padding={5}
                                fill={'white'}
                        />                  
                       </Label> 


                        <Arc
                              x={150}
                              y={window.innerHeight-200}
                              innerRadius={40}
                              outerRadius={120}
                              angle={60}
                              fill={'red'}
                              stroke={'red'}
                              strokeWidth={4}
                              rotation={0}
                        />            

                        <Arc
                              x={150}
                              y={window.innerHeight-200}
                              innerRadius={40}
                              outerRadius={120}
                              angle={60}
                              fill={'green'}
                              stroke={'green'}
                              strokeWidth={4}
                              rotation={60}
                        />        
                        <Arc
                              x={150}
                              y={window.innerHeight-200}
                              innerRadius={40}
                              outerRadius={120}
                              angle={60}
                              fill={'yellow'}
                              stroke={'yellow'}
                              strokeWidth={4}
                              rotation={120}
                        />   

                        <Arc
                              x={150}
                              y={window.innerHeight-200}
                              innerRadius={40}
                              outerRadius={120}
                              angle={60}
                              fill={'blue'}
                              stroke={'blue'}
                              strokeWidth={4}
                              rotation={180}
                        />               

                        <Arc
                              x={150}
                              y={window.innerHeight-200}
                              innerRadius={40}
                              outerRadius={120}
                              angle={120}
                              fill={'orange'}
                              stroke={'orange'}
                              strokeWidth={4}
                              rotation={60 + 180}
                        />                        


                        <Ellipse
                            x={400}
                            y={window.innerHeight - 200}
                            radius={ {x: 100, y: 50}}
                            fill={'yellow'}
                            stroke={'black'}
                            strokeWidth={4}          

                        />


                    </Layer>



                  </Stage>
            </div>
    );
  }
}

 ReactDOM.render(<App />, document.getElementById('konvaid1'));
1
Did you call layer,draw() after the final positioning of the text on each move ?Vanquished Wombat
is layer.draw used with React? React redraws Stage every time a state is modified.Jose Cabrera Zuniga
You could be right - I just looked at the React-konva demo and there is no mention of draw(). I wonder if screen.x/y is what is needed. Konva has stage.getPointerPosition() which might be better. How about this - hard code your x & y pos in the mouseover to like (10,20) and see if the text is over near topleft of the stage - if yes then it is the co-ords, if no it is something deeper.Vanquished Wombat
I believe it is the coords but the Label was declared outside the Arrow so I believe I need to know the coords of the Arrow relative to Stage and the coords of the mouse relative to the arrow and add these coordinates to place the Label. But, how can I do to get this info? In react Stage replaces stage. I might have to use a reference to Stage to use the getPointerPosition() functionJose Cabrera Zuniga
Hopefully @lavrton will be along in a moment to show the way....Vanquished Wombat

1 Answers

1
votes

I modified the Stage to have a reference to it:

  <Stage ref={ref => {
                this.stageRef = ref;
         }}
      ....
  />

and also

   this._onMouseMove = (e) => {

     console.log('moved mouse = -------------------- ' + 3207);
     console.log(e);   
     console.log(e.nativeEvent);   
     e.preventDefault;
     # var stage = e.currentTarget;
     var stage = this.stageRef.getStage();   
     const cursor = stage.getPointerPosition();


     this.setState({  mouse_x: cursor.x, mouse_y: cursor.y });
   }   

Directly using an answer from:

getPointerPosition() of stage in React-Konva