快点更新下一个,虽然只是小计.但是感觉会越拖越懒得写.
2022/7/4 更新,更新保存数据出现的bug,解决办法就是修改在clickNode里面在嵌套多一层customAttrs字段 this.clickNode.customAttrs
先创建画板
// 初始化画布
graph = new Graph({
container: document.getElementById('orgAndPersonnelContainer'),
grid: true,
width: this.onresizeWidth, // 这个是自己定义的宽度
height: this.onresizeHeight, // 这个是自己定义的高度
background: {
color: '#fff', // 设置画布背景颜色
},
mousewheel: {
enabled: true,
zoomAtMousePosition: true,
modifiers: 'ctrl',
minScale: 0.5,
maxScale: 3,
},
panning: {
enabled: true, // 单独开启拖动操作
modifiers: 'shift', // 按下shift才可以拖动
},
connecting: {
router: {
name: 'manhattan',
args: {
padding: 1,
},
},
connector: {
name: 'rounded',
args: {
radius: 8,
},
},
anchor: 'center',
connectionPoint: 'anchor',
allowBlank: false,
snap: {
radius: 20,
},
createEdge() {
return new Shape.Edge({
attrs: {
line: {
stroke: '#A2B1C3',
strokeWidth: 2,
targetMarker: {
name: 'block',
width: 12,
height: 8,
},
},
},
zIndex: 0,
})
},
validateConnection({ targetMagnet }) {
return !!targetMagnet
},
},
highlighting: {
magnetAdsorbed: {
name: 'stroke',
args: {
attrs: {
fill: '#5F95FF',
stroke: '#5F95FF',
},
},
},
},
resizing: true,
rotating: true,
selecting: {
enabled: true,
rubberband: true,
showNodeSelectionBox: true,
},
snapline: true,
keyboard: true,
clipboard: true,
})
接下来是拖动放大之类的一些事件,官方例子有写,我也是直接copy
这个真的是copy的没什么好说的QAQ 删除按钮的也在这里面
快捷键与事件
// copy cut paste
graph.bindKey(['meta+c', 'ctrl+c'], () => {
const cells = graph.getSelectedCells()
if (cells.length) {
graph.copy(cells)
}
return false
})
graph.bindKey(['meta+x', 'ctrl+x'], () => {
const cells = graph.getSelectedCells()
if (cells.length) {
graph.cut(cells)
}
return false
})
graph.bindKey(['meta+v', 'ctrl+v'], () => {
if (!graph.isClipboardEmpty()) {
const cells = graph.paste({ offset: 32 })
graph.cleanSelection()
graph.select(cells)
}
return false
})
//undo redo
graph.bindKey(['meta+z', 'ctrl+z'], () => {
if (graph.history.canUndo()) {
graph.history.undo()
}
return false
})
graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
if (graph.history.canRedo()) {
graph.history.redo()
}
return false
})
// select all
graph.bindKey(['meta+shift+a', 'ctrl+shift+a'], () => {
const nodes = graph.getNodes()
if (nodes) {
graph.select(nodes)
}
})
//delete
graph.bindKey('backspace', () => {
const cells = graph.getSelectedCells()
// console.log(cells.isEdge())
// if (cells.length) {
// graph.removeCells(cells)
// }
})
// zoom
graph.bindKey(['ctrl+1', 'meta+1'], () => {
const zoom = graph.zoom()
if (zoom < 1.5) {
graph.zoom(0.1)
}
})
graph.bindKey(['ctrl+2', 'meta+2'], () => {
const zoom = graph.zoom()
if (zoom > 0.5) {
graph.zoom(-0.1)
}
})
// 调整节点大小事件
graph.on('node:resized', ({ e, x, y, node, view }) => {
this.setClickNode(node) // 这里是将节点保存到变量的方法
})
// 移动节点事件
graph.on('node:moved', ({ e, x, y, node, view }) => {
})
// 点击背景板
graph.on('blank:click', ({ e, x, y }) => {
})
// 点击节点
graph.on('node:click', ({ e, x, y, node, view }) => {
})
// 添加边事件, 这里是添加线的删除事件
graph.on('edge:added', ({ edge, index, options }) => {
edge.addTools([
{
name: 'button-remove', // 添加删除按钮
args: {
distance: '85%',
attrs: {
y: -50,
width: 20,
height: 20
}
},
},
// {
// name: 'boundary',
// args: {
// distance: 10,
// },
// }
])
})
// 拖动新增的事件
graph.on('node:added', ({ node }) => {
node.addTools([
{
name: 'button-remove',
args: {
distance: '85%',
y: -10, // 删除按钮的位置
x: '100%',
},
},
{
name: 'boundary',
args: {
// distance: 20,
padding: 15,
},
},
])
好像没什么好写的了= =
写下修改样式的吧
this.clickNode 是上图样式属性相关值的对象
this.clickNodeTemp 的指向是点击的节点( 对象赋值的话是指向同一个堆哦)
this.timeEnd 一次性定时器
this.time 定时器
clickNode: {
// 这里对象在嵌套一层,不然保存数据的时候会出现奇怪的bug,往下看
customAttrs: {
clickNodeContent: '', // 内容
clickNodeContentSize: '', // 字体大小
clickNodeBoxSizeWidth: '', // 盒子宽度
clickNodeBoxSizeHeight: '', // 盒子高度
clickNodeBgColor: '', // 背景颜色
clickNodeTextColor: '', // 文字颜色
clickNodeBorderColor: '', // 边框颜色
positionx: 0, // x位置
positiony: 0 // y位置
},
}
html
<el-button
@click="addOrSubOrColorClickNodeData('add', 'clickNodeBoxSizeWidth')"
size="mini"
icon="el-icon-caret-top"
class="mini-icon"
@mousedown.native="holdDown('add', 'clickNodeBoxSizeWidth')"
@mouseup.native="holdUp()"
></el-button>
js
// 设置属性值
setClickNode(node) {
this.clickNodeTemp = node // 指向节点
this.clickNode.customAttrs.clickNodeContent = node.attrs.text.text
this.clickNode.customAttrs.clickNodeContentSize = node.attrs.text.fontSize
this.clickNode.customAttrs.clickNodeTextColor = node.attrs.text.fill
const propTemp = this.clickNodeTemp.getProp() // 获取样式信息
this.clickNode.customAttrs.clickNodeBoxSizeWidth = propTemp.size.width
this.clickNode.customAttrs.clickNodeBoxSizeHeight = propTemp.size.height
this.clickNode.customAttrs.clickNodeBorderColor = node.attrs.body.stroke
this.clickNode.customAttrs.clickNodeBgColor = node.attrs.body.fill
const relativePos = node.position({relative: true}) // 获取位置信息
this.clickNode.customAttrs.positionx = relativePos.x
this.clickNode.customAttrs.positiony = relativePos.y
},
// 鼠标按下时触发
holdDown(addOrSubOrColorTemp, data) {
var i = 0; //变量i
this.timeEnd = setTimeout(() => {
this.time = setInterval(() => { //setInterval可一直执行内部函数
this.addOrSubOrColorClickNodeData(addOrSubOrColorTemp, data);
i++; //若过一秒,执行一次i++
}, 200);
}, 800)
if (i == 0) { //i=0时证明无长按事件为单击事件
// this.addOrSubOrColorClickNodeData(addOrSubOrColorTemp, data);
}
},
holdUp() {
clearTimeout(this.timeEnd)
clearInterval(this.time); //如果按下时间不到1000毫秒便弹起,
},
// 加一减一或者颜色修改 addOrSubOrColorTemp 判断是点击加还是减 或者是选择颜色的
addOrSubOrColorClickNodeData(addOrSubOrColorTemp, data) {
if (addOrSubOrColorTemp == 'add') {
this.clickNode[data]++
} else if (addOrSubOrColorTemp == 'sub'){
this.clickNode[data]--
}
this.clickNode.customAttrs.positionx = this.clickNode.customAttrs.positionx*1,
this.clickNode.customAttrs.positiony = this.clickNode.customAttrs.positiony*1
this.clickNodeTemp.updateAttrs(this.clickNode)
if (this.clickNodeTemp.setAttrs) {
// 用这个方法设置颜色样式
this.clickNodeTemp.setAttrs(
{
body: { fill: this.clickNode.customAttrs.clickNodeBgColor, stroke: this.clickNode.customAttrs.clickNodeBorderColor },
label: {
fill: this.clickNode.customAttrs.clickNodeTextColor
},
text: {
text: this.clickNode.customAttrs.clickNodeContent,
fontSize: this.clickNode.customAttrs.clickNodeContentSize
},
}
)
if (addOrSubOrColorTemp && addOrSubOrColorTemp !== 'color') {
// 用这个方法修改长宽, 位置
this.clickNodeTemp.setProp({
size: {
width: this.clickNode.customAttrs.clickNodeBoxSizeWidth,
height: this.clickNode.customAttrs.clickNodeBoxSizeHeight,
},
position: {
x: this.clickNode.customAttrs.positionx*1,
y: this.clickNode.customAttrs.positiony*1
}
})
}
}
},
差点忘记一个最重要的东西,就是把数据转换的
// 将页面的图形转换成json
let preservationDataTemp = graph.toJSON()
// 将图形json绘制到页面,需要注意基本的宽高,
// 网格配置不能有改变(暂时还没研究太深入,简单说就是配置不变就行,不然有些样式缺失就绘制不出来)
graph.fromJSON(preservationDataTemp)
不知道为什么
this.clickNode
会出现划红线的情况
所以我就试试多加个对象解决问题
this.clickNode.customAttrs
好了 结束,比较枯燥.但是基本直接copy 能用.冲冲冲