关键的数据-必须要服务端的回调来操控
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>
网友评论