antvX6 - Vue自定义节点,并实现多种画布操作,拖拽、缩放、连线、双击、检索等等

一、 首先 antv x6 分为两个版本  低版本和高版本

  我这里是使用的2.0版本 并且搭配了相关插件 例如:画布的图形变换、地图等

  个人推荐 2.0版本,高版本配置多,可使用相关插件多,但是文档描述小,仍在更新, 低版本文档描述清晰,但是相关插件少

二、antv x6 支持自定义节点! 

          这里要特别注意  虽然支持自定义节点,但是连线,连线桩也自然只能节点之间互连,所以你看我的例子中,想要列表里的子节点也可以实现 互相连接,但是这是自定义节点无法做到的。
          因为此时这一整个盒子就是 一个节点!

三、事件集合

    // 事件集合loadEvents(containerRef) {// 节点双击this.graph.on('node:dblclick', ({ node }) => {const data = node.store.data;console.log(data);this.$router.push({path: '/modeling/homeModeling',query: {id: data.modelingId,name: data.name,layerTypeId: data.layerTypeId,tableType: data.modelingType,},});});// 连线双击this.graph.on('edge:dblclick', ({ edge }) => {// const data = edge.store.data;// const { type, id } = data;// alert('连线双击');// console.log('edge:dbclick', edge);// if (type === 'taskNode') {//   this.nodeId = id;//   this.showRight = true;// } else {//   this.nodeId = '';//   this.showRight = false;// }});// 节点鼠标移入this.graph.on('node:mouseenter',FunctionExt.debounce(({ node }) => {// 添加删除// const x = node.store.data.size.width - 10;// node.addTools({//   name: 'button-remove',//   args: {//     x: 0,//     y: 0,//     offset: { x, y: 15 },//   },// });}),500,);this.graph.on('node:port-contextmenu', ({ e }) => {// console.log(//   'ports',//   e,//   e.currentTarget.parentElement.getAttribute('port'),// );});// 连接线鼠标移入this.graph.on('edge:mouseenter', ({ edge }) => {// edge.addTools([//   'source-arrowhead',//   'target-arrowhead',//   {//     name: 'button-remove',//     args: {//       distance: '50%',//     },//   },// ]);});// 节点鼠标移出this.graph.on('node:mouseleave', ({ node }) => {// // 移除删除// node.removeTools();});this.graph.on('edge:mouseleave', ({ edge }) => {// edge.removeTools();});this.graph.on('edge:connected', ({ isNew, edge }) => {// console.log('connected', edge.source, edge.target);// if (isNew) {//   // 对新创建的边进行插入数据库等持久化操作// }});},

四、画布初始化

    graphInit() {// 容器生成图表const containerRef = this.$refs.containerRef;const graph = new Graph({container: containerRef,background: {color: '#F1F6F9',},grid: {size: 10, // 网格大小 10pxvisible: true, // 绘制网格,默认绘制 dot 类型网格type: 'fixedDot',args: {color: '#AFB0B1', // 网点颜色thickness: 1, // 网点大小},},panning: true, // 画布拖拽history: true, // 启动历史记录selecting: {// 选择与框选enabled: true,rubberband: true,movable: true,strict: true,showNodeSelectionBox: true, // 显示节点的选择框(才能进行移动)modifiers: ['alt'],},// Scroller 使画布具备滚动、平移、居中、缩放等能力scroller: {enabled: true,pageVisible: true,pageBreak: true,pannable: true,},// 鼠标滚轮的默认行为是滚动页面 使用ctrl+滚轮 实现缩放mousewheel: {enabled: true,modifiers: ['ctrl', 'meta'], // +按键为缩放minScale: 0.5,maxScale: 2,},snapline: true, // 对齐线// 节点连接connecting: {router: {name: 'er',args: {offset: 25,direction: 'H',},},snap: true, // 自动吸附allowBlank: false, // 是否允许连接到画布空白位置的点allowLoop: false, // 是否允许创建循环连线,即边的起始节点和终止节点为同一节点allowNode: false, // 是否允许边链接到节点(非节点上的链接桩)createEdge() {return new Shape.Edge({attrs: {line: {stroke: '#1684FC',strokeWidth: 2,},},});},},// 连接桩样式 -- 高亮highlighting: {magnetAvailable: {name: 'stroke',args: {padding: 4,attrs: {strokeWidth: 4,stroke: '#1684FC',},},},},});// 小地图const minimapContainer = this.$refs.minimapContainer;graph.use(new MiniMap({container: minimapContainer,width: '250',height: '150',scalable: true, // 是否可缩放minScale: 0.01,maxScale: 16,}),);// 图形graph.use(new Transform({enabled: true,resizing: map,}),);// 缩放画布内容,使画布内容充满视口graph.zoomToFit({ padding: 10, maxScale: 1 });// 赋值生成this.graph = graph;// 事件集合this.loadEvents(containerRef);},

五、创建Vue自定义节点

<template><divref="node_dom"class="node_warp":style="{width: node.size.width + 'px',height: node.size.height + 'px',borderTopColor: color,}"><div class="head_top" :style="{ backgroundColor }"><svg-icon :icon-class="icon" :style="{ color }"></svg-icon><div class="code_warp"><span class="code ellipsis_text">{{ node.code }}</span><span class="name ellipsis_text">{{ node.name }}</span></div><el-popoverref="popoverDom"placement="bottom-end"width="60":value="popShow"trigger="click"popper-class="filter_column_popover"@hide="popShow = false"@show="popShow = true"><svg-iconslot="reference"class="icon"type="primary"size="mini"style="opacity: 0.5;"icon-class="table_column_settings"></svg-icon><p class="header_wrap_filter_column"><el-checkboxv-model="checkAll":indeterminate="isIndeterminate"@change="handleCheckAllChange">全选</el-checkbox><!-- --><!-- <el-button size="mini" type="text" @click="resetColumn">重置</el-button> --></p><el-checkbox-groupv-model="checkList"@change="handleCheckedCitiesChange"><el-checkbox v-for="item in checkData" :key="item" :label="item">{{ item }}</el-checkbox></el-checkbox-group><div v-if="!checkData.length" class="empy">暂无数据</div></el-popover></div><div class="main"><divv-for="(item, index) in node.columnVersions":key="index"class="text "><svg-icon v-if="item.isPrimaryKey" icon-class="key"></svg-icon><span v-show="checkList.includes('英文名称')" class="ellipsis_text">{{ item.code }}</span><div v-show="checkList.includes('字段类型')" class="type ellipsis_text">{{ item.dataType }}</div><span v-show="checkList.includes('中文名称')" class="ellipsis_text">{{ item.name }}</span></div><divv-if="!node.columnVersions || !node.columnVersions.length"class="empy flex">暂无数据</div></div><div class="footer">{{ `共${node.columnSize || 0}个字段` }}</div></div>
</template><script>
import { manage } from './config';
const cityOptions = ['英文名称', '字段类型', '中文名称'];
export default {name: 'Node',inject: ['getNode'],data() {return {num: 0,icon: '',color: '',node: {},popShow: false,checkAll: false,checkList: ['英文名称', '字段类型'],checkData: cityOptions,isIndeterminate: true,backgroundColor: null,typeMap: manage.typeMap,};},watch: {checkList(val) {console.log(val);},},created() {const node = this.getNode();const typeMap = this.typeMap;this.node = node.store.data;const type = this.node.modelingType;this.icon = typeMap[type].icon;this.color = typeMap[type].color;this.backgroundColor = typeMap[type].backgroundColor;},methods: {handleCheckAllChange(val) {this.checkList = val ? cityOptions : [];this.isIndeterminate = false;},handleCheckedCitiesChange(value) {const checkedCount = value.length;this.checkAll = checkedCount === this.checkData.length;this.isIndeterminate =checkedCount > 0 && checkedCount < this.checkData.length;},resetColumn() {this.checkList = ['英文名称', '字段类型'];},},
};
</script><style lang="scss" scoped>
.node_warp {display: flex;border-radius: 4px;flex-direction: column;border: 1px solid #d9dae2;border-top: 5px solid #d9dae2;position: relative;user-select: none;transition: all 0.4s ease-in 0.2s;transition: width 0.25s;-webkit-transition: width 0.25s;-moz-transition: width 0.25s;-webkit-transition: width 0.25s;-o-transition: width 0.25s;.head_top {width: 100%;height: 48px;display: flex;padding-left: 10px;align-items: center;position: relative;border-bottom: 1px solid #d9dae2;.code_warp {width: 85%;font-size: 12px;margin-left: 8px;display: flex;flex-direction: column;.code {color: black;font-weight: 700;}.name {color: #b3b2bf;font-weight: 600;}}.icon {position: absolute;right: 5px;bottom: 5px;}}.main {flex: 1;width: 100%;overflow: auto;padding-right: 2px;background: #fff;.text {height: 32px;display: flex;gap: 1px;font-size: 13px;position: relative;padding-left: 20px;align-items: center;svg {position: absolute;left: 4px;top: 10px;}.type {flex: 1;height: 24px;font-size: 12px;line-height: 24px;text-align: center;border-radius: 4px;margin-right: 5px;display: inline-block;background-color: #f7f7f9;}span {flex: 1;text-align: center;}&:hover {background: #f8f8fa;}}}.footer {height: 20px;font-size: 12px;line-height: 20px;padding-left: 10px;color: rgb(156, 160, 184);border-top: 1px solid #d9dae2;background: rgb(247, 247, 249);}.ellipsis_text {white-space: nowrap;overflow: hidden;text-overflow: ellipsis;word-break: break-all;line-height: 18px;}.empy {color: #ccc;font-size: 14px;margin: 10px auto;width: fit-content;}.flex {display: flex;height: calc(100% - 30px);align-items: center;}
}
</style>

六、注册引入Vue自定义节点

1、安装依赖

      "@antv/x6-vue-shape": "2.0.6",

      yarn add antv/x6-vue-shape@2.0.6

2、引入 Vue 自定义组件

      import CustomNode from '../node';

3、引入插件的方法

      import { register } from '@antv/x6-vue-shape'; // vue节点

4、注册节点

        

register({

  shape: 'custom-vue-node',

  component: CustomNode,

});


import CustomNode from '../node';
import { register } from '@antv/x6-vue-shape'; // vue节点// 注册 Vue component
register({shape: 'custom-vue-node',component: CustomNode,
});

七、创建节点、创建连线、渲染节点

// 连接线  
const lineNewData = newData.map((item, index) => {return {id: String(new Date().getTime() + index),shape: 'edge',// 连接源source: {cell: item.sourceTableId,},// 连接目标target: {cell: item.targetTableId,},attrs: {line: {stroke: '#1684FC',strokeWidth: 2,},},// 名字labels: [{attrs: {label: {text: item.name || '',},},},],zIndex: 0,};});// 节点const nodeData = result.map(item => {return {...item,id: item.modelingVersionId,width: Number(item.width || 300),height: Number(item.heigh || 270),// 节点类型shape: item.shape || 'custom-vue-node',position: {x: Number(item.posX || this.getRandomInt()),y: Number(item.posY || this.getRandomInt()),},};});this.erData = [...nodeData, ...lineNewData];

  通过数据 渲染节点

  watch: {data(val) {const cells = [];this.data.forEach(item => {console.log(item, item.shape);if (item.shape === 'edge') {cells.push(this.graph.createEdge(item)); // 创建连线} else {cells.push(this.graph.createNode(item)); // 创建节点}});// 清空画布并添加用指定的节点/边this.graph.resetCells(cells);},},

八、canvas主页面 全部代码

<template><div id="container" class="antv-x6"><div ref="minimapContainer" class="app-mini"></div><div ref="containerRef" class="app-content"></div><div class="operating"><el-selectv-model="value"clearablefilterableplaceholder="请选择"size="mini":popper-append-to-body="false":class="isShow ? 'showSelect' : 'hideSelect'"@change="valChange"><el-optionv-for="item in data.filter(i => i.modelingType)":key="item.id":label="item.code":value="item.id"><div class="head_top"><svg-icon:icon-class="typeMap[item.modelingType].icon":style="{ color: typeMap[item.modelingType].color }"/><div class="code_warp"><span class="code ellipsis_text">{{ item.code }}</span><span class="name ellipsis_text">{{ item.name }}</span></div></div></el-option></el-select><div class="icon_oper"><el-tooltipclass="item"effect="dark"content="搜索"placement="bottom"><svg-icon icon-class="search_canvas" @click="search" /></el-tooltip><el-tooltipclass="item"effect="dark"content="放大"placement="bottom"><svg-icon icon-class="amplify_canvas" @click="zoomInFn" /></el-tooltip><el-tooltipclass="item"effect="dark"content="缩小"placement="bottom"><svg-icon icon-class="reduce_canvas" @click="zoomOutFn" /></el-tooltip><el-tooltipclass="item"effect="dark"content="还原"placement="bottom"><svg-icon icon-class="1_1_canvas" @click="resetFn" /></el-tooltip><el-tooltipclass="item"effect="dark"content="保存"placement="bottom"><svg-icon icon-class="saveModel" @click="submit" /></el-tooltip><el-tooltipclass="item"effect="dark":content="isFullScreen ? '退出全屏' : '全屏'"placement="bottom"><svg-icon icon-class="screen" @click="fullScreen" /></el-tooltip><el-tooltipclass="item"effect="dark"content="刷新"placement="bottom"><svg-icon icon-class="refresh" @click="redoFn" /></el-tooltip></div></div></div>
</template><script>
import { manage } from '../config';
import CustomNode from '../node';
import { Graph, Shape, FunctionExt } from '@antv/x6';
import { register } from '@antv/x6-vue-shape'; // vue节点
import { MiniMap } from '@antv/x6-plugin-minimap'; // 地图
import { Transform } from '@antv/x6-plugin-transform'; // 图形变换
// import { Scroller } from '@antv/x6-plugin-scroller'; // 滚动画布const map = {enabled: true,minWidth: 200,maxWidth: 700,minHeight: 100,maxHeight: 500,orthogonal: false,restrict: false,preserveAspectRatio: false,
};// 注册 Vue component
register({shape: 'custom-vue-node',component: CustomNode,
});export default {name: 'Er',props: {data: {type: Array,default: () => [],},},data() {return {value: '',graph: null,isShow: false,showRight: false,isFullScreen: false,typeMap: manage.typeMap,};},watch: {data(val) {const cells = [];this.data.forEach(item => {console.log(item, item.shape);if (item.shape === 'edge') {cells.push(this.graph.createEdge(item)); // 创建连线} else {cells.push(this.graph.createNode(item)); // 创建节点}});// 清空画布并添加用指定的节点/边this.graph.resetCells(cells);},},mounted() {this.graphInit();},methods: {graphInit() {// 容器生成图表const containerRef = this.$refs.containerRef;const graph = new Graph({container: containerRef,background: {color: '#F1F6F9',},grid: {size: 10, // 网格大小 10pxvisible: true, // 绘制网格,默认绘制 dot 类型网格type: 'fixedDot',args: {color: '#AFB0B1', // 网点颜色thickness: 1, // 网点大小},},panning: true, // 画布拖拽history: true, // 启动历史记录selecting: {// 选择与框选enabled: true,rubberband: true,movable: true,strict: true,showNodeSelectionBox: true, // 显示节点的选择框(才能进行移动)modifiers: ['alt'],},// Scroller 使画布具备滚动、平移、居中、缩放等能力scroller: {enabled: true,pageVisible: true,pageBreak: true,pannable: true,},// 鼠标滚轮的默认行为是滚动页面 使用ctrl+滚轮 实现缩放mousewheel: {enabled: true,modifiers: ['ctrl', 'meta'], // +按键为缩放minScale: 0.5,maxScale: 2,},snapline: true, // 对齐线// 节点连接connecting: {router: {name: 'er',args: {offset: 25,direction: 'H',},},snap: true, // 自动吸附allowBlank: false, // 是否允许连接到画布空白位置的点allowLoop: false, // 是否允许创建循环连线,即边的起始节点和终止节点为同一节点allowNode: false, // 是否允许边链接到节点(非节点上的链接桩)createEdge() {return new Shape.Edge({attrs: {line: {stroke: '#1684FC',strokeWidth: 2,},},});},},// 连接桩样式 -- 高亮highlighting: {magnetAvailable: {name: 'stroke',args: {padding: 4,attrs: {strokeWidth: 4,stroke: '#1684FC',},},},},});// 小地图const minimapContainer = this.$refs.minimapContainer;graph.use(new MiniMap({container: minimapContainer,width: '250',height: '150',scalable: true, // 是否可缩放minScale: 0.01,maxScale: 16,}),);// 图形graph.use(new Transform({enabled: true,resizing: map,}),);// 缩放画布内容,使画布内容充满视口graph.zoomToFit({ padding: 10, maxScale: 1 });// 赋值生成this.graph = graph;// 事件集合this.loadEvents(containerRef);},// 事件集合loadEvents(containerRef) {// 节点双击this.graph.on('node:dblclick', ({ node }) => {const data = node.store.data;console.log(data);this.$router.push({path: '/modeling/homeModeling',query: {id: data.modelingId,name: data.name,layerTypeId: data.layerTypeId,tableType: data.modelingType,},});});// 连线双击this.graph.on('edge:dblclick', ({ edge }) => {// const data = edge.store.data;// const { type, id } = data;// alert('连线双击');// console.log('edge:dbclick', edge);// if (type === 'taskNode') {//   this.nodeId = id;//   this.showRight = true;// } else {//   this.nodeId = '';//   this.showRight = false;// }});// 节点鼠标移入this.graph.on('node:mouseenter',FunctionExt.debounce(({ node }) => {// 添加删除// const x = node.store.data.size.width - 10;// node.addTools({//   name: 'button-remove',//   args: {//     x: 0,//     y: 0,//     offset: { x, y: 15 },//   },// });}),500,);this.graph.on('node:port-contextmenu', ({ e }) => {// console.log(//   'ports',//   e,//   e.currentTarget.parentElement.getAttribute('port'),// );});// 连接线鼠标移入this.graph.on('edge:mouseenter', ({ edge }) => {// edge.addTools([//   'source-arrowhead',//   'target-arrowhead',//   {//     name: 'button-remove',//     args: {//       distance: '50%',//     },//   },// ]);});// 节点鼠标移出this.graph.on('node:mouseleave', ({ node }) => {// // 移除删除// node.removeTools();});this.graph.on('edge:mouseleave', ({ edge }) => {// edge.removeTools();});this.graph.on('edge:connected', ({ isNew, edge }) => {// console.log('connected', edge.source, edge.target);// if (isNew) {//   // 对新创建的边进行插入数据库等持久化操作// }});},// 放大zoomInFn() {this.graph.zoom(0.1);},// 缩小zoomOutFn() {const Num = Number(this.graph.zoom().toFixed(1));if (Num > 0.1) {this.graph.zoom(-0.1);}},// 重置1:1resetFn() {this.graph.centerContent();this.graph.zoomTo(1); // 缩放画布到指定的比例},// 刷新redoFn() {this.$emit('detailsEr');},// 全屏fullScreen() {// const element = document.documentElement;const element = document.getElementById('container');// 判断是否已经是全屏if (this.isFullScreen) {// 退出全屏if (document.exitFullscreen) {document.exitFullscreen();} else if (document.webkitCancelFullScreen) {document.webkitCancelFullScreen();} else if (document.mozCancelFullScreen) {document.mozCancelFullScreen();} else if (document.msExitFullscreen) {document.msExitFullscreen();}} else {// 全屏if (element.requestFullscreen) {element.requestFullscreen();} else if (element.webkitRequestFullScreen) {element.webkitRequestFullScreen();} else if (element.mozRequestFullScreen) {element.mozRequestFullScreen();} else if (element.msRequestFullscreen) {// IE11element.msRequestFullscreen();}}this.isFullScreen = !this.isFullScreen;},// 搜索search() {this.isShow = !this.isShow;},// 保存submit() {const data = this.graph.getNodes();this.$emit('submitEr', data);},// 检索valChange(val) {if (val) {// false - 清空const nodes = this.graph.getNodes() || [];const node = nodes.filter(item => item.id === val)[0] || {};this.graph.centerCell(node); // 将节点/边的中心与视口中心对齐} else {this.resetFn();}},},
};
</script><style lang="scss" scoped>
.antv-x6 {width: 100%;height: 100%;padding: 0;display: flex;position: relative;box-sizing: border-box;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;::v-deep body {min-width: auto;}.node-c {width: 200px;border-right: 1px solid #eee;padding: 20px;dl {margin-bottom: 20px;line-height: 30px;display: flex;cursor: move;dt {&.circle {width: 30px;height: 30px;border-radius: 50%;&.start {border: 1px solid green;background: greenyellow;}&.end {border: 1px solid salmon;background: red;}}&.rect {width: 30px;height: 30px;border: 1px solid #ccc;}}dd {font-size: bold;font-size: 14px;padding: 0 0 0 10px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}}}.template-c {padding: 10px 0;li {line-height: 40px;font-size: 14px;border-bottom: 1px solid #dcdfe6;cursor: pointer;display: flex;justify-content: space-between;span {flex: 1;padding-right: 10px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}i {font-size: 14px;color: #2d8cf0;width: 20px;line-height: 40px;}}}.container {flex: 1;}.operating {position: absolute;z-index: 999;right: 20px;top: 10px;padding: 5px 10px;border-radius: 6px;background-color: #ffffff;border: 1px solid rgb(187, 187, 187);box-shadow: 1px 1px 4px 0 #0a0a0a2e;display: flex;height: 34px;align-items: center;.el-select {transition: width 0.6s ease-in-out;::v-deep .el-input__inner {height: 26px;line-height: 26px;}::v-deep .el-input--mini .el-input__icon {line-height: 26px;}::v-deep .el-select-dropdown__item {height: 48px;max-width: 410px;line-height: 48px;}&.hideSelect {width: 0px;::v-deep .el-input__inner {display: none;}::v-deep .el-input__suffix {display: none;}}&.showSelect {width: 180px;::v-deep .el-input__inner {display: block;}::v-deep .el-input__suffix {display: block;}}}.icon_oper {svg {font-size: 18px;cursor: pointer;margin: 0 5px;&:hover {color: #2d8cf0;}&.opacity {opacity: 0.5;}}}}
}
.app-mini {position: fixed;z-index: 999;bottom: 10px;right: 20px;border-radius: 6px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
.app-content {flex: 1;height: 100% !important;
}
::v-deep .x6-graph-scroller {border: 1px solid #f0f0f0;margin-left: -1px;width: 100% !important;height: 100% !important;
}.head_top {width: 100%;height: 48px;display: flex;align-items: center;.code_warp {width: 90%;height: 100%;font-size: 12px;margin-left: 8px;display: flex;gap: 4px;flex-direction: column;justify-content: center;.code {color: black;font-weight: 700;line-height: normal;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;word-break: break-all;}.name {color: #b3b2bf;font-weight: 600;line-height: normal;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;word-break: break-all;}}
}
::v-deep .text {height: 32px;display: flex;gap: 1px;font-size: 13px;position: relative;padding-left: 20px;align-items: center;svg {position: absolute;left: 4px;top: 10px;}.type {width: 25%;height: 24px;font-size: 12px;line-height: 24px;text-align: center;border-radius: 4px;margin-right: 5px;display: inline-block;background-color: #f7f7f9;}span {flex: 1;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;word-break: break-all;line-height: 18px;}&:hover {background: #f8f8fa;}
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/503778.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaWeb之 Web概述

目录 前言1.1 Web和 JavaWeb的概念1.2 JavaWeb技术栈1.2.1 B/S架构1.2.2 静态资源1.2.3 动态资源1.2.4 数据库1.2.5 HTTP协议1.2.6 Web服务器 1.3 JavaWeb 学习内容 前言 博主将用 CSDN 记录 Java 后端开发学习之路上的经验&#xff0c;并将自己整理的编程经验和知识分享出来&a…

yolo目标检测实战

该博客主要介绍了&#xff1a; 1. 如何制作yolo目标检测数据集 2.如何在自己的数据集上训练yolo 3.训练好后的模型如何进行推理 1.数据标注 关于数据如何标注&#xff0c;请查看这篇博文 2.数据集目录结构 重点关注红框内部的结构 images: 图片目录 images/train: 训练集…

Zookeeper学习1:概述、安装、应用场景、集群配置

文章目录 概述安装LinuxWindows 配置参数集群参考配置文件配置步骤流程启动 概述 Zookeeper&#xff1a; 为分布式框架组件提供协调服务的中间件 【类似&#xff1a;文件系统通知机制】 负责存储上下层应用关系的数据以及接收观察者注册监听&#xff0c;一旦观察查关心的数据发…

npm与包

包 包的概念 Node.js中的第三方模块又叫做包。包的来源 由第三方个人或团队开发出来的&#xff0c;免费提供给所有人使用。为什么需要包 由于Node.js内置模块仅提供了一些底层的API&#xff0c;导致在基于内置模块进行项目开发时&#xff0c;效率很低。包是基于内置模块封装出…

在idea中用模板骨架初始创建maven管理的web项目时没有src有关的目录的解决方案

一.问题如下 二.解决方法 首先关闭当前项目&#xff0c;接着修改全局设置&#xff0c;重新创建项目 在VM Options中添加"-DarchetypeCataloginternal"&#xff0c;点击ok保存 点击创建&#xff0c;如果创建成功没报错且有src&#xff0c;就ok了。 当然如果出现以下…

Avalonia学习(二十八)-OpenGL

Avalonia已经继承了opengl&#xff0c;详细的大家可以自己查阅。Avalonia里面启用opengl继承OpenGlControlBase类就可以了。有三个方法。分别是初始化、绘制、释放。 这里把官方源码的例子扒出来给大家看一下。源码在我以前发布的单组件里面。地址在前面的界面总结博文里面。 …

vue cesium加载点与定位到指定位置

vue cesium定位到指定位置 window.viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(point.longDeg, point.latDeg, 6500000), orientation: {heading: 6.2079384332084935, roll: 0.00031509431759868534, pitch: -1.535}, duration: 3})vue cesium加载点 …

[技巧]Arcgis之图斑四至范围批量计算

ArcGIS图层&#xff08;点、线、面三类图形&#xff09;四至范围计算 例外一篇介绍&#xff1a;[技巧]Arcgis之图斑四至点批量计算 说明&#xff1a;如下图画出来的框&#xff08;范围标记不是很准&#xff09; &#xff0c;图斑的x最大和x最小&#xff0c;y最大&#xff0c;…

css实现居中

基础代码&#xff1a; <div class"box"><div class"content"></div> </div> css实现居中的几种方式&#xff1a; 1、flex布局&#xff08;水平垂直&#xff09; .box {width: 200px;height: 200px;background-color: pink;disp…

如何利用Flutter来写后端 服务端应用

前言 Flutter是谷歌推出的一款跨平台开发框架&#xff0c;现在属于此领域star最多的框架&#xff0c;其被广泛应用于构建前台界面&#xff0c;但或许很少人知道&#xff0c;他也可以写后端应用。 本文主角 flutter非常著名的getx库推出的get server jonataslaw/get_server:…

管家婆云上管家新帐套建立步骤

第一步&#xff0c;客户服务管理&#xff1b; 第二步&#xff0c;添加帐套&#xff1b; 第三步&#xff0c;点击“管理”进入&#xff1b;第四步&#xff0c;添加帐套信息&#xff1b; 第五步&#xff0c;找到客户&#xff0c;查看帐套信息&#xff1b; 第六步&#xff0c;确认…

ShardingJdbc分库分表-浅谈分表原理

文章目录 为什么要分库分表一、分库分表二、不停机分库分表数据迁移 为什么要分库分表 一般的机器&#xff08;4核16G&#xff09;&#xff0c;单库的MySQL并发&#xff08;QPSTPS&#xff09;超过了2k&#xff0c;系统基本就完蛋了。最好是并发量控制在1k左右。这里就引出一个…