How to open a popup window/Dialog to client from server using socket io?

Viewed 24

I am developing a whiteboard application using react, node.js and socket.io. My requirement is when I open the whiteboard it will also visible to other people/user. How can I achieve that? In current situation user have to click on a button to open the whiteboard from ther end. I am new to react and socket.io. It will be very helpful if anybody share any knowledge about the idea.

I have shared some code done so far.

server.js

const express = require('express');
const app = express();
const path = require('path');
const http = require('http').createServer(app);
const io = require('socket.io')(http);

io.on('connection', onConnection);

function onConnection(socket){
  socket.on('drawing', (data) => {
    socket.broadcast.emit('drawing',data);
    console.log(data);
  });

  socket.on('clear', () => {
    socket.broadcast.emit('clear');
    console.log('data cleard........');
  });
}

app.get('*', (_, res) => res.sendFile(path.join(__dirname, 'build/index.html')));

const server_port =  8081;
http.listen(server_port, () => {
    console.log(`Started on : ${server_port}`);
})

canvas.jsx

const Canvas = () => {
  const canvasRef = useRef(null);
  const colorsRef = useRef(null);
  const socketRef = useRef();
  const classes = useStyles();
  const [color, setColor] = useState('#3B3B3B');
  const [size, setSize] = useState('3');
  const [cursor, setCursor] = useState('default');
  const [isDrawing, setIsDrawing] = useState(false);
  const timeout = useRef(null);
  const ctx = useRef(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    ctx.current = canvas.getContext('2d');

    //Resizing
    canvas.height = window.innerHeight;
    canvas.width = window.innerWidth;

    //Load from locastorage
    const canvasimg = localStorage.getItem('canvasimg');
    if (canvasimg) {
      var image = new Image();
      ctx.current = canvas.getContext('2d');
      image.onload = function() {
        ctx.current.drawImage(image, 0, 0);
        setIsDrawing(false);
      };
      image.src = canvasimg;
    }
  }, [ctx]);

  useEffect(() => {
    //     // --------------- getContext() method returns a drawing context on the canvas-----

    const canvas = canvasRef.current;
    // const context = canvas.getContext('2d');
    let drawing = false;
    // ctx.current = context;

    // ------------------------------- create the drawing ----------------------------

    const drawLine = (x0, y0, x1, y1, emit) => {
      ctx.current.beginPath();
      ctx.current.moveTo(x0, y0);
      ctx.current.lineTo(x1, y1);
      ctx.current.strokeStyle = color;
      ctx.current.lineWidth = size;
      ctx.current.stroke();
      ctx.current.closePath();

      if (!emit) {
        return;
      }
      const w = canvas.width;
      const h = canvas.height;

      socketRef.current.emit('drawing', {
        x0: x0 / w,
        y0: y0 / h,
        x1: x1 / w,
        y1: y1 / h,
      });
    };

    //     // ---------------- mouse movement --------------------------------------

    const onMouseDown = e => {
      drawing = true;
      ctx.current.x = e.clientX || e.touches[0].clientX;
      ctx.current.y = e.clientY || e.touches[0].clientY;
    };

    const onMouseMove = e => {
      if (!drawing) {
        return;
      }
      drawLine(
        ctx.current.x,
        ctx.current.y,
        e.clientX || e.touches[0].clientX,
        e.clientY || e.touches[0].clientY,
        true
      );
      ctx.current.x = e.clientX || e.touches[0].clientX;
      ctx.current.y = e.clientY || e.touches[0].clientY;
    };

    const onMouseUp = e => {
      if (!drawing) {
        return;
      }
      drawing = false;
      drawLine(
        ctx.current.x,
        ctx.current.y,
        e.clientX || e.touches[0].clientX,
        e.clientY || e.touches[0].clientY,
        true
      );
    };

    // ----------- limit the number of events per second -----------------------

    const throttle = (callback, delay) => {
      let previousCall = new Date().getTime();
      return function() {
        const time = new Date().getTime();

        if (time - previousCall >= delay) {
          previousCall = time;
          callback.apply(null, arguments);
        }
      };
    };

    // -----------------add event listeners to our canvas ----------------------

    canvas.addEventListener('mousedown', onMouseDown, false);
    canvas.addEventListener('mouseup', onMouseUp, false);
    canvas.addEventListener('mouseout', onMouseUp, false);
    canvas.addEventListener('mousemove', throttle(onMouseMove, 10), false);

    // Touch support for mobile devices
    canvas.addEventListener('touchstart', onMouseDown, false);
    canvas.addEventListener('touchend', onMouseUp, false);
    canvas.addEventListener('touchcancel', onMouseUp, false);
    canvas.addEventListener('touchmove', throttle(onMouseMove, 10), false);

    // -------------- make the canvas fill its parent component -----------------

    const onResize = () => {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    };

    window.addEventListener('resize', onResize, false);
    onResize();

    // ----------------------- socket.io connection ----------------------------
    socketRef.current = io.connect('/');

    const onDrawingEvent = data => {
      const w = canvas.width;
      const h = canvas.height;
      drawLine(data.x0 * w, data.y0 * h, data.x1 * w, data.y1 * h);
    };

    socketRef.current.on('drawing', onDrawingEvent);
    socketRef.current.on('clear', clearCanvas);
  }, []);


  const emitAndCanvas = () => {
    socketRef.current.emit('clear');
    clearCanvas();
  };

  const clearCanvas = () => {
    // localStorage.removeItem('canvasimg');
    const canvas = canvasRef.current;
    const context = canvas.getContext('2d');
    // ctx.current.fillStyle = 'white';
    context.clearRect(0, 0, canvas.width, canvas.height);
    // socketRef.current.emit('clear');

    //Passing clear screen
  };

  const getPen = () => {
    setCursor('default');
    setSize('3');
    setColor('#3B3B3B');
  };

  const eraseCanvas = () => {
    setCursor('grab');
    setSize('20');
    setColor('#FFFFFF');
    $('#circularcursor').show();
    $(document).ready(function() {
      $(document).on('mousemove', function(e) {
        $('#circularcursor').css({
          left: e.pageX,
          top: e.pageY,
        });
      });
    });
  };

  return (
    <>
      <p id="message">Initializing Sync...</p>
      <div className="canvas-btn">
        <button onClick={getPen} className="btn-width">
          <Tooltip title="Pencil">
            <CreateRoundedIcon />
          </Tooltip>
        </button>
        <div className="btn-width">
          <input type="color" value={color} onChange={e => setColor(e.target.value)} />
        </div>
        <div>
          <Select value={size} onChange={e => setSize(e.target.value)}>
            <MenuItem value={1}>1</MenuItem>
            <MenuItem value={3}>3</MenuItem>
            <MenuItem value={5}>5</MenuItem>
            <MenuItem value={10}>10</MenuItem>
            <MenuItem value={15}>15</MenuItem>
            <MenuItem value={20}>20</MenuItem>
            <MenuItem value={25}>25</MenuItem>
          </Select>
        </div>
        <div>
          <button onClick={emitAndCanvas} className="btn-width">
            <Tooltip title="Clear All">
              <ClearAllIcon />
            </Tooltip>
          </button>
        </div>
        <div>
          <button onClick={eraseCanvas} className="btn-width">
            <Tooltip title="Reset">
              <DeleteForeverRoundedIcon />
            </Tooltip>
          </button>
        </div>
      </div>
      <canvas
        style={{ cursor: cursor }}
        // onMouseDown={onMouseMove}
        // onMouseUp={onMouseUp}
        // onMouseMove={drawLine}
        ref={canvasRef}
        className={classes.canvascover}
      />
    </>
  );
};

export default Canvas;
0 Answers
Related