1.完成节点、群组、连线、拖拽、删除、节点拉伸

This commit is contained in:
wangzijun 2022-07-29 09:25:36 +08:00
commit 9fc0b40cd6
14 changed files with 13187 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules/
dist/

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# rule-chain

12479
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

51
package.json Normal file
View File

@ -0,0 +1,51 @@
{
"name": "basic",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@antv/x6": "^1.32.3-beta.1",
"@antv/x6-vue-shape": "^1.4.0",
"@vue/composition-api": "^1.6.3",
"core-js": "^3.6.5",
"element-ui": "^2.15.9",
"vue": "^2.6.11",
"vue-json-viewer": "^2.2.22",
"vue-baidu-map": "^0.21.22"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.13",
"@vue/cli-plugin-eslint": "~4.5.13",
"@vue/cli-service": "~4.5.13",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"node-sass": "^4.14.1",
"sass": "^1.54.0",
"sass-loader": "^7.3.1",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
public/icon/ic-filter-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
public/imgs/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

17
public/index.html Normal file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="">
<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">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

27
src/App.vue Normal file
View File

@ -0,0 +1,27 @@
<template>
<div id="app">
<index-stencil></index-stencil>
</div>
</template>
<script>
import indexStencil from "./demo/index-stencil.vue";
export default {
name: 'App',
components: {
indexStencil
}
}
</script>
<style>
html,body,#app {
height:100%;
margin:0px;
padding:0px
}
.v-modal{
opacity: 0.5!important;
background: rgba(0,0,0,0.5)!important;
}
</style>

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

514
src/demo/index-stencil.vue Normal file
View File

@ -0,0 +1,514 @@
<template>
<div>
<div class="tools-bar">
<el-popover
placement="bottom"
width="200"
class="el-po"
trigger="click">
<div ref="stencilContainer" class="x6-stencil"></div>
<i class="el-icon-s-operation opt-btn" slot="reference" ></i>
</el-popover>
</div>
<div class="content" :style="{ height: contentHeight }">
<!-- <div ref="stencilContainer" class="x6-stencil"></div> -->
<div class="middle-box">
<div ref="container" class="x6-content" :style="{ height: contentHeight }"></div>
<!-- <div @click="click" style="width:600px;height:600px; position: absolute;z-index: 3;background:red;pointer-events;none;">这个是上层</div> -->
<!-- <div @click="click2" style="width:800px;height:600px; position: absolute;z-index: 2;background:yellow;pointer-events;none;">这个是中层</div> -->
<!-- 中间地图 -->
<baidu-map
class="mp-view"
:style="{ height: mapHeight }"
:center="center"
:zoom="zoom"
@ready="handler"></baidu-map>
</div>
</div>
</div>
</template>
<script>
import { Graph, Shape, Addon,Path } from '@antv/x6';
const { Stencil } = Addon
const { Rect, Circle } = Shape
export default {
data() {
return {
contentHeight:'0px', //x6
mapHeight: "200px", //
center: {lng: 0, lat: 0},//
zoom: 3,//
graph:undefined,//x6
stencil:undefined,//x6
projection:undefined,//projection
data : {
//
nodes: [
{
id: 'node1', // String
x: 0, // Number x
y: 0, // Number y
width: 80, // Number width
height: 40, // Number height
label: 'hello', // String
},
{
id: 'node2', // String
x: 160, // Number x
y: 180, // Number y
width: 80, // Number width
height: 40, // Number height
label: 'world', // String
},
],
//
edges: [
{
source: 'node1', // String id
target: 'node2', // String id
},
],
}
}
},
mounted () {
this.init()
this.initCell()
this.initGraph();
this.initStencil()
},
methods:{
init() {
this.contentHeight = document.documentElement.clientHeight -45 + "px";
this.mapHeight = document.documentElement.clientHeight -45 + "px";
},
//
handler ({BMap, map}) {
console.log(BMap, map)
this.center.lng = 116.404
this.center.lat = 39.915
this.zoom = 14
this.projection = map
},
//
initCell(){
//
const ports = {
groups: {
top: {
position: 'top',
attrs: {
circle: {
r: 4,
magnet: true,
stroke: '#5F95FF',
strokeWidth: 1,
fill: '#fff',
style: {
visibility: 'hidden',
},
},
},
},
right: {
position: 'right',
attrs: {
circle: {
r: 4,
magnet: true,
stroke: '#5F95FF',
strokeWidth: 1,
fill: '#fff',
style: {
visibility: 'hidden',
},
},
},
},
bottom: {
position: 'bottom',
attrs: {
circle: {
r: 4,
magnet: true,
stroke: '#5F95FF',
strokeWidth: 1,
fill: '#fff',
style: {
visibility: 'hidden',
},
},
},
},
left: {
position: 'left',
attrs: {
circle: {
r: 4,
magnet: true,
stroke: '#5F95FF',
strokeWidth: 1,
fill: '#fff',
style: {
visibility: 'hidden',
},
},
},
},
},
items: [
{
group: 'top',
},
{
group: 'right',
},
{
group: 'bottom',
},
{
group: 'left',
},
],
}
//
Graph.registerNode(
'custom-rect',
{
inherit: 'rect',
width: 66,
height: 36,
attrs: {
body: {
strokeWidth: 1,
stroke: '#5F95FF',
fill: '#EFF4FF',
},
text: {
fontSize: 12,
fill: '#262626',
},
},
ports: { ...ports },
},
true,
)
},
//
initGraph(){
let mapZoom = this.zoom
this.graph = new Graph({
container: this.$refs.container,
background: {//
color: 'transport', //
},
grid: {//
size: 10, // 10px
visible: true, //
},
// panning: {//
// enabled: true, //
// modifiers: 'shift', //
// },
mousewheel: {//
enabled: true,
modifiers: ['ctrl'],
guard(e){//
return true
}
},
snapline: true,//线
selecting: {///
enabled: true,///
rubberband: true,//
showNodeSelectionBox: true,//
},
resizing:true,//
highlighting: {//
//
magnetAdsorbed: {
name: 'stroke',
args: {
attrs: {
//fill: '#5F95FF',
stroke: '#5F95FF',
},
},
},
//
embedding: {
name: 'stroke',
args: {
padding: -1,
attrs: {
stroke: '#73d13d',
},
},
},
},
connecting:{//线
//20
snap: {
radius: 20,
},
allowBlank:false,//
allowNode:false,//
allowEdge:false,//
anchor: 'center',// anchor
connectionPoint: 'anchor',//
router: {// vertices
name: 'manhattan',
args: {
padding: 1,
},
},
connector: {//
name: 'rounded',
args: {
radius: 8,
},
},
createEdge() {//
return new Shape.Edge({
attrs: {
line: {
//stroke: '#A2B1C3',
stroke: 'green',
strokeWidth: 3,
targetMarker: {
name: 'block',
width: 12,
height: 8,
},
},
},
zIndex: 20,
})
},
validateConnection({ targetMagnet }) {//
return !!targetMagnet
},
},
//
embedding:{
enabled:true,//
findParent(node){// findParent
const bbox = node.node.getBBox()
return this.getNodes().filter((node) => {
// data.parent true
const data = node.getData()
if (data && data.canBeParent) {
const targetBBox = node.getBBox()
return bbox.isIntersectWithRect(targetBBox)
}
return false
})
}
},
//
translating: {
restrict(view) {
if(view){
const cell = view.cell
if (cell.isNode()) {
const parent = cell.getParent()
if (parent) {
return parent.getBBox()
}
}
}
return null
},
},
});
//this.graph.fromJSON(this.data)
//
//
this.graph.on('node:mouseenter', ( e ) => {
const container = this.$refs.container
const ports = container.querySelectorAll(
'.x6-port-body',
)
this.showPorts(ports, true)
this.showNodeTool(e.node,true)
})
//
this.graph.on('node:mouseleave', ( e) => {
const container = this.$refs.container
const ports = container.querySelectorAll(
'.x6-port-body',
)
this.showPorts(ports, false)
this.showNodeTool(e.node,false)
})
//线线
this.graph.on('edge:mouseenter',(e)=>{
this.showEdgeTool(e.edge,true)
})
//线线
this.graph.on('edge:mouseleave',(e)=>{
this.showEdgeTool(e.edge,false)
})
//
this.graph.on('node:change:parent', ({ node }) => {
node.attr({
body:{
stroke: 'none',
fill: '#47C769',
},
label: {
text: '节点-过程',
},
})
})
//
this.graph.on('node:added',(args)=>{
//
this.pixelToPoint(args.node,args.node.store.data.position)
})
//
this.graph.on('node:change:position',(args)=>{
//
this.pixelToPoint(args.node,args.current)
})
//
// this.graph.on('translate', ({ tx, ty }) => {
// console.log("tx",tx)
// //console.log("ty",ty)
// this.mapScrollBy(tx,ty)
// })
},
//Stencil
initStencil(){
this.stencil = new Stencil({
target: this.graph,//
stencilGraphWidth: 200,//
stencilGraphHeight: 80,//
groups: [
{
name: 'group1',//
title: '元素',//
collapsable: false,// true
},
],
})
//Stencil
this.$refs.stencilContainer.appendChild(this.stencil.container)
//
const process = this.graph.createNode({
shape: 'custom-rect',
label: '过程',
zIndex: 10,
attrs: {
body: {
stroke: 'none',
fill: '#3199FF',
},
},
})
const node = this.graph.createNode({
shape: 'custom-rect',
label: '节点',
zIndex: 1,
data: {
canBeParent: true,
},
})
//
this.stencil.load([process,node], 'group1')
},
///
showPorts(ports,show){
ports.forEach(port => {
port.style.visibility = show?'visible' : 'hidden'
});
},
///
showNodeTool(node,show){
if(show){
node.addTools({
name: 'button-remove',
args: {
x: '100%',
y: 0,
offset: { x: -3, y: 3 },
},
})
}else{
node.removeTools()
}
},
//线/
showEdgeTool(edge,show){
if(show){
edge.addTools({
name: 'button-remove',
args: { distance: -40 },
})
}else{
edge.removeTools()
}
},
//
pixelToPoint(node,position){
let ePoint = this.projection.pixelToPoint({x:position.x,y:position.y})
//node
node.store.data.mapPoint = ePoint
},
//
mapScrollBy(tx,ty){
this.projection.panBy(tx,ty)
},
}
}
</script>
<style lang="scss" scoped>
.tools-bar{
height: 45px;
line-height: 45px;
background: #fff;
display: flex;
.opt-btn{
margin-top: 4px;
font-size: 35px;
}
}
.content {
display: flex;
.x6-stencil{
width: 250px;
}
.middle-box{
width: 100%;
position: relative;
.x6-content {
width: 100%;
position: absolute;
z-index: 2;
}
.mp-view{
width: 100%;
position:absolute;
z-index: 1;
}
}
}
.el-popover{
height: 500px;
overflow: auto;
}
</style>
<style>
.el-popover{
height: 120px;
overflow: auto;
}
</style>

16
src/main.js Normal file
View File

@ -0,0 +1,16 @@
import Vue from 'vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue'
//全局引入注册
import BaiduMap from 'vue-baidu-map'
Vue.config.productionTip = false
Vue.use(ElementUI);
Vue.use(BaiduMap, {
ak:'mnFNphcQGzYVF90CZScxgmZQ3o8ABga8'
})
new Vue({
render: h => h(App),
}).$mount('#app')

5
vue.config.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
lintOnSave: false,
runtimeCompiler: true,
}

74
yarn-error.log Normal file
View File

@ -0,0 +1,74 @@
Arguments:
/usr/local/bin/node /usr/local/bin/yarn add @vue/composition-api --dev
PATH:
/Users/zijunwang/Desktop/Flutter/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/Users/zijunwang/Desktop/Flutter/bin:/Users/zijunwang/Library/Android/sdk/tools:/Users/zijunwang/Library/Android/sdk/platform-tools:/Users/zijunwang/Library/Android/sdk/tools:/Users/zijunwang/Library/Android/sdk/platform-tools
Yarn version:
1.22.18
Node version:
14.17.3
Platform:
darwin x64
Trace:
Error: EINVAL: invalid argument, unlink '/Users/zijunwang/Desktop/vue-project/rule-chain/node_modules/globule/node_modules/glob'
npm manifest:
{
"name": "basic",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@antv/x6": "^1.32.3-beta.1",
"@antv/x6-vue-shape": "^1.4.0",
"@vue/composition-api": "^1.6.3",
"core-js": "^3.6.5",
"element-ui": "^2.15.9",
"vue": "^2.6.11",
"vue-json-viewer": "^2.2.22"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.13",
"@vue/cli-plugin-eslint": "~4.5.13",
"@vue/cli-service": "~4.5.13",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"vue-template-compiler": "^2.6.11",
"node-sass": "^4.14.1",
"sass-loader": "^7.3.1"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
yarn manifest:
No manifest
Lockfile:
No lockfile