协同编辑

2022-06-09  本文已影响0人  skoll

关键的数据-必须要服务端的回调来操控

1 .节点增加,节点删除,边增加,边删除.已经实现
2 .节点数据修改.
3 .要把每个保存在本地的数据饭到房间里面,服务端.allNode,allEdge的操作

不关键的数据-本地先操控,然后把操作发给服务端,同步给其他的数据

1 .节点样式相关信息,比如节点移动,节点缩放之类的

服务端

//聊天服务器
const roomList={
  1:{
    name:"星星小屋",
    value:"...一些关于房间的描述",
    numbers:[],
    // 房间的人数
  },
  2:{
    name:"月亮小屋",
    value:"...一些关于房间的描述",
    numbers:[],
  }
}

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");

const io = new Server(server,{
  cors:{
    origin:'*'
  }
});

// 可以获取的一些变量
// io.engine.clientsCount:当前连接的客户端数量


//可以加的一些事件钩子


app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
})


io.on('connection', (socket) => {
  console.log('有人连接!')
  socket.emit('connection',{
    msg:"连接成功"
  })

  socket.on('disconnect',(socket)=>{
      console.log('有人断开',socket)
  })

  socket.on('login',({username})=>{
    console.log('有人登陆'+username)
    socket.data.username=username
  })
  // 创建房间:实际里面的操作是创建并加入
  socket.on('create',({room},callback)=>{
    socket.join(room)
    console.log('创建了房间'+room)
    //把玩家塞进去
    socket.data.name='群主'
    roomList[room].numbers.push({
      name:socket.data.name
    })
    callback({'msg':"创建成功",data:roomList[room]})
  })

  // 加入房间
  socket.on('join',({room},callback)=>{
    io.in(room).fetchSockets().then((e)=>{
      // 返回房间里面的所有客户,不过这个可以是一个数据库的属性,查就可以了,这种用方法是不是有点炸.
      console.log('当前全部客户',e.length)
      if(e.length>=12){
        // io.to(room).emit('房间满了,无法加入')
        callback({msg:"房间满了,无法加入"})
      }else{
        socket.join(room)
        io.to(room).emit('room',`欢迎加入${room}房间`)
        roomList[room].numbers.push({name:`玩家${roomList[room].numbers.length+1}`})
        callback({msg:"成功加入房间"+room,number:roomList[room].numbers})
      }
    })
      
  })

  socket.on('leave',({room},callback)=>{
    socket.leave(room)
    callback({'msg':"成功离开房间"})
  })

  socket.on('chat',(msg)=>{
    console.log('加入房间之后发送的话',msg)
    io.to(msg.room).emit('chat',msg.data)
  })

  socket.on('goto',({from,to},callback)=>{
    io.in(from).socketsJoin([to,])
    // 将当前方加你的人加入到2,3房间
    callback({'msg':"已经加入房间2"})
  })

  socket.on('loginOut',({room},callback)=>{
    io.in(room).disconnectSockets(true)
  })
  //让一个房间的全部玩家全部断开

  //和节点相关的操作
  socket.on('remove',(data,callback)=>{
    io.in(data.room).emit('remove',data)
  })

  socket.on('add',(data,callback)=>{
    io.in(data.room).emit('add',data)
  })

  socket.on('nodePosition',(data)=>{
    io.in(data.room).emit('nodePosition',data)
  })

  socket.on('addEdge',(data)=>{
    console.log('edgeAdd')
    io.in(data.room).emit('addEdge',data.data)
  })

  socket.on('removeEdge',(data)=>{
    console.log('edgeRemove',data)

    io.in(data.room).emit('removeEdge',data.id)
  })

});

io.engine.on('connection_error',(err)=>{
  console.log('连接错误',err)
})


io.of('/').adapter.on('create-room',(room)=>{
  console.log(`room ${room} was created`)
})

io.of("/").adapter.on("join-room", (room, id) => {
  //这里应该是用来记录日志的,因为拿不到socekt实例,所以无法通信
  console.log(`编号${id} 加入房间 ${room}`);
  console.log('当前的房间名字',io.of("/").adapter.rooms)
  
});

io.of('/').adapter.on('leave-room',(room,id)=>{
  // console.log(`编号${id} 离开房间 ${room}`)
})

app.set('host','10.252.60.55')
server.listen(5000, () => {
  console.log('listening on *:5000');
});


客户端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.socket.io/4.5.0/socket.io.min.js" integrity="sha384-7EyYLQZgWBi67fBtVxw60/OWl1kjsfrPFcaU0pp0nAh+i8FD068QogUvg85Ewy1k" crossorigin="anonymous"></script>
    <script src="https://unpkg.com/@antv/x6/dist/x6.js"></script>
    <style>
        .my-selecting{
            color:red;
        }
    </style>
</head>
<body>
    <input type="text" id="input">
    <button id="login">登陆</button>
    <select name="" value="1" id="select">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
        <option value="5">5</option>
    </select>
    <button id="join">加入房间</button>
    <button id="joinTwo">前往房间2</button>
    <button id="joinTwo">加入房间2</button>
    <button id="leave">离开房间</button>
    <button id="create">创建房间</button>
    <button id="send">发送</button>}|<button id="add">添加节点</button><button id="remove">删除节点</button>
    <button id="addEdge">添加边</button>
    <button id="centerPoint">滚动到画布中心</button>
<hr>
<div id="container"></div>
    <script>
        let userId=Math.random()
        let transitionLock=true

        const graph = new X6.Graph({
            container: document.getElementById('container'),
            width: 800,
            height: 600,
            grid:{
                visible:true,
                size:20,
                type:"mesh"
            },
            selecting:true,
            connecting:{
                allowBlank:false,
                allowMulti:'withPort',
                allowLoop:false,
                allowNode:false,
                allowEdge:false,
                allowPort:true,
                highlight:true,
                snap:{
                    radius:10,
                },
                validateEdge({edge}){
                    socket.emit('addEdge',{
                        room:'1',
                        userId,
                        data:edge.store.data,
                    })
                    return false
                },
            },
            highlighting:{
                //
                magnetAvailable:{
                    name:"stroke",
                    args:{
                        padding:4,
                        attrs:{
                            'strok-width':2,
                            stroke:'#31d0c6'
                        }
                    }
                },

            },
            onPortRendered(args){
                const selectors=args.contentSelectors
                const container=selectors&&selectors.foContent
                console.log(selectors,container)
                if(container){
                    container.innerText="x"
                    container.className='my-port'
                }
            }
        });
        
        const source = graph.addNode({
            id:'node1',
            x: 40,
            y: 40,
            width: 180,
            height: 100,
            label: 'Source',
            attrs:{
                body:{
                    fill:"red",
                    stroke:"yellow"
                },
                label:{
                    text:'hello',
                    fill:"#333",
                    fontSize:20
                }
            },
            tools: [
              {
                name: 'button',
                args: {
                    markup: [
                            {
                                tagName: 'circle',
                                selector: 'button',
                                attrs: {
                                r: 5,
                                stroke: '#fe854f',
                                'stroke-width': 3,
                                fill: 'white',
                                cursor: 'pointer',
                                },
                                className:'node1'
                            },
                            {
                                tagName: 'text',
                                textContent: 'X',
                                selector: 'icon',
                                attrs: {
                                fill: '#fe854f',
                                'font-size': 8,
                                'text-anchor': 'middle',
                                'pointer-events': 'none',
                                y: '0.3em',
                                },
                            },
                    ],
                    x: '100%',
                    y: '100%',
                    offset: { x: -18, y: -18 },
                    onClick({ view }) {
                      const node = view.cell
                      //console.log(view)
                      socket.emit('remove',{id:view.cell.id,room:"1",userId})
                    },
                },
              },
            ],
            ports:{
                groups:{
                    group1:{
                        attrs:{
                            circle: {
                                r: 6,
                                magnet: true,
                                stroke: '#31d0c6',
                                strokeWidth: 2,
                                fill: '#fff',
                              },
                        },
                    }
                },
                //桩模板
                items:[
                    {
                        id:'source-port1',
                        group:'group1'
                    },{
                        id:'source-port2',
                        group:'group1'
                    }
                ]
            }
          })
      
        const target = graph.addNode({
            x: 220,
            y: 260,
            width: 180,
            height: 50,
            label: 'Target',
            id:'node2',
            ports:{
                groups:{
                    group1:{
                        attrs:{
                            fo:{
                                width:10,
                                height:10,
                                x:-5,
                                y:-5,
                                magnet:"true",
                                "border-radius":5
                            }
                        },
                        
                    }
                },
                //桩模板
                items:[
                    {
                        id:'target-port1',
                        group:'group1'
                    },{
                        id:'target-port2',
                        group:'group1'
                    }
                ]
            },
            portMarkup: [X6.Markup.getForeignObjectMarkup()],
          })

        

          graph.on('node:removed',(data)=>{
            console.log('节点删除',data)
          })

          graph.on('node:change:position',(data)=>{
              if(transitionLock){
                socket.emit('nodePosition',{
                    room:"1",
                    userId,
                    data:{
                        nodeId:data.node.id,
                        position:data.current
                    }
                })
              }
          })

        
        //房间连接
        const socket=io('ws://localhost:5000')
        socket.addEventListener('connection',()=>{
            console.log('连接成功')
            //自动加入房间吧
            socket.emit("join",{room:'1'},(res)=>{
                console.log('成功加入房间1')
            })

            const engine=socket.io.engine;
            console.log(engine.transport.name)

            engine.once('upgrade',()=>{
                //协议传输升级的时候调用
                //console.log(engine.transport.name)
            })

            engine.on('packet',({type,data})=>{
                //收到消息的时候触发
                //console.log(type,data)
            })

            engine.on('packetCreate',({type,data})=>{
                //发送消息的时候触发
                //console.log(type,data)
            })

            engine.on('drain',()=>{
                //写缓冲区被耗尽的时候
            })

            engine.on('close',(reason)=>{
                //连接被关闭的时候
            })
        })

        socket.addEventListener('disconnection',()=>{
            console.log('断开连接')
        })

        //客户端socket发出的3个事件
        socket.on('connect',()=>{
            console.log('正在重新连接')
            //重连的时候的时候触发
        })

        socket.on('connect_error',()=>{
            //连接错误
        })

        socket.on('disconnect',(rason)=>{
            //连接断开
        })

        socket.on('chat',(data)=>{
            //登陆成功之后的发送消息
            console.log('收到消息',data)
            //怎么知道是哪个房间的呢?
        })

        socket.on('remove',(data)=>{
            console.log('remove',data)
            graph.removeNode(data.id)
        })

        socket.on('add',(data)=>{
            const value=data.data
            graph.addNode({
                id:value.data.id,
                x: 220,
                y: 160,
                width: 80,
                height: 30,
                label: value.data.label,
                shape:value.type
              })
        })

        socket.on('nodePosition',(data)=>{
            if(data.userId==userId){
                return false
            }else{
                transitionLock=false
                let node=graph.getCellById(data.data.nodeId)
                const oldPos=node.position()
                const newPos=data.data.position
                console.log(newPos.x,newPos.y)
                node.position(newPos.x,newPos.y,{
                    //silent:true,
                })
            }
            
        })

        socket.on('addEdge',(data)=>{
            const config={
                shape:'edge',
                tools:[
                    {
                        name:"button",
                        args:{
                            markup:[
                                {
                                    tagName:"circle",
                                    selector:'button',
                                    attrs:{
                                        r:5,
                                        stroke:'#fe85f',
                                        'stroke-width':3,
                                        fill:'red',
                                        cursor:'pointer',
                                    },
                                    
                                },{
                                    tagName:'text',
                                    textCOntent:"x",
                                    selector:"icon",
                                    attrs:{
                                        fill:"white",
                                        "font-size":8,
                                        'text-anchor':'middle',
                                        'pointer-events':'none',

                                    }

                                }
                            ],
                            onClick({view}){
                                socket.emit('removeEdge',{
                                    id:view.cell.id,
                                    room:"1",
                                    userId
                                })
                            }
                        },
                    }
                ],
                attrs:{
                    line:{
                        stroke:"orange",
                        sourceMarker: {
                            tagName: 'path',
                            d: 'M 20 -10 0 0 20 10 Z',
                          },
                        targetMarker: {
                            tagName: 'path',
                            fill: 'yellow',  // 使用自定义填充色
                            stroke: 'green', // 使用自定义边框色
                            strokeWidth: 2,
                            d: 'M 20 -10 0 0 20 10 Z',
                        },
                        
                    },
                }
            }
            graph.addEdge(Object.assign({},data,config))
        })

        socket.on('removeEdge',(data)=>{
            console.log('删除',data)
            graph.removeEdge(data)

        })

        
         //获取变量
         const loginBtn=document.querySelector('#login')
         loginBtn.addEventListener('click',()=>{
             let username=document.querySelector('#input').value
             socket.emit('login',{
                 username
             },(res)=>{
                 console.log('login-res',res)
             })
             
         })


         const joinBtn=document.querySelector('#join')
         joinBtn.addEventListener('click',()=>{
             let joinName=document.querySelector('#select').value
             socket.emit('join',{
                 'room':joinName
             },(res)=>{
                 console.log('加入成功',res)
             })
         })

         const createBtn=document.querySelector('#create')
         createBtn.addEventListener('click',()=>{
            let joinName=document.querySelector('#select').value
            socket.emit('create',{
                'room':joinName
            },(res)=>{
                console.log('创建成功',res)
            })
        })

         const sendBtn=document.querySelector('#send')
         sendBtn.addEventListener('click',()=>{
             console.log('send')
             let message=document.querySelector('#input').value
             socket.emit('chat',{
                 room:"2",
                 data:message,
                 id:1,
             })
         })

         const leaveBtn=document.querySelector('#leave')
         leaveBtn.addEventListener('click',()=>{
             console.log('leave')
             socket.emit('leave',{room:1},(res)=>{
                 console.log('leave callback')
             })
         })

         const joinTwoBtn=document.querySelector('#joinTwo')
         joinTwoBtn.addEventListener('click',()=>{
             socket.emit('goto',{from:'1',to:'2'},(res)=>{
                 console.log(res)
             })
             //当前房间1加入房间2
         })

         const addBtn=document.querySelector('#add')
         addBtn.addEventListener('click',()=>{
             socket.emit('add',{room:'1',userId,data:{type:'rect',data:{id:'node3',label:"按钮3"}}})
             //想要创建一个这个元素
         })

         const removeBtn=document.querySelector('#remove')
         removeBtn.addEventListener('click',()=>{
             socket.emit('remove',{id:'node1',room:"1",userId})
         })

         const addEdgeBtn=document.querySelector('#addEdge')
         addEdgeBtn.addEventListener('click',()=>{
             socket.emit('addEdge',{
                room:"1",
                userId,
                data:{
                    id:"edge1",
                    source:{
                        cell:'node1',
                        port:'source-port1'
                    },
                    target:{
                        cell:'node2',
                        port:'target-port2'
                    }
   
                }
             })
         })
    </script>
   
</body>
</html>
上一篇 下一篇

猜你喜欢

热点阅读