vue使用jtopo实现拓扑图

介绍


技术实现:vue3+vite+jtopo

完整代码:vue-jtopo

功能描述:

  • 拖拽节点
  • 生成几何图形,文本,图片等
  • 编辑节点属性
  • 保存生成json字符串

实现效果:
在这里插入图片描述

引入


  1. 官网安装导入教程
    http://www.jtopo.com/doc/tutorial_install.html

  2. 查看项目模板
    https://gitee.com/nengduan/jtopo_vue_vite

  3. 拷贝资源
    jtopo_npm目录拷贝至项目根目录
    在这里插入图片描述

  4. 修改
    jtopo_npm/editor/package.json:
    在这里插入图片描述
    改成./jtopo_npm/core

  5. 安装依赖
    yarn add ./jtopo_npm/core ./jtopo_npm/editor

使用

  1. 初始化
<div id="topo" class="content"></div>
import { Stage, Layer } from '@jtopo/core'
const stage = new Stage('topo')
const layer = new Layer('default')
stage.addChild(layer)
  1. 添加连线(带端点)
/**
 * 直线
 * @param { String } pos 坐标:{ x: x, y: y }
 * @param { String } w 宽度
 * @param { String } h 高度
 */
static addLink (pos: any, w: number, h: number) {
  const begin = new Point(pos.x, pos.y)
  const end = new Point(pos.x + w, pos.y)
  const link = new Link('', begin, end)
  this.layer.addChild(link)
  link.css({
  	// 线条样式
    strokeStyle: css.strokeStyle,
    lineWidth: h
  })
}

在这里插入图片描述

  1. 添加矩形
/**
 * 矩形
 * @param text 文本
 * @param pos 坐标:{ x: x, y: y }
 * @param w 宽度
 * @param h 高度
 */
static addRectangle (text: string, pos: any, w: number, h: number) {
  const node = new Node(text, pos.x, pos.y, w, h)
  node.css(css)
  this.layer.addChild(node)
}

在这里插入图片描述

  1. 添加圆形
/**
 * 圆形
 * @param text 文本
 * @param pos 坐标:{ x: x, y: y }
 * @param radius 半径
 */
static addCircle(text: string, pos: any, radius: number) {
  const node = new CircleNode(text, pos.x, pos.y)
  // 设置半径
  node.setRadius(radius)
  node.css(css)
  this.layer.addChild(node)
}

在这里插入图片描述

  1. 添加三角形
/**
 * 三角形
 * @param pos 坐标:{ x: x, y: y }
 * @param w 边长
 */
static addTriangle(pos: any, w: number) {
  const node = new Node('', pos.x, pos.y, w, w)
  const shape = Shape.polygon(3)
  node.setShape(shape)

  // 将节点内的图形逆时针旋转-90度
  node.shape.rotate(Math.PI / 2)
  // 上下镜像
  node.shape.scale(1, -1)
  node.css(css)

  // 设置连线点
  node.getAnchorPoints = () => {
    return ['ct', 'lb', 'rb']
  }

  this.layer.addChild(node)
}

在这里插入图片描述

  1. 添加文本
/**
 * 文本
 * @param text 文本内容
 * @param pos 坐标:{ x: x, y: y }
 * @param w 宽度
 * @param h 高度
 * @param textPosition 文本位置
 */
static addText (text: string, pos: any, w: number, h: number, textPosition: string) {
  const node = new TextNode(text, pos.x, pos.y, w, h)
  const cssObj = {
    color: config.textNodeColor,
    textPosition: textPosition,
    textBaseline: 'middle',
    textAlign: textPosition,
    font: 'bold 14px arial'
  }

  node.setStyles(cssObj)
  node.autoSize = false
  this.layer.addChild(node)
}

在这里插入图片描述

  1. 添加比率节点
/**
 * 比率节点
 * @param text 文本
 * @param pos 坐标:{ x: x, y: y }
 * @param w 宽度
 * @param h 高度
 */
static addRatioNode(text: string, pos: any, w: number, h: number) {
  const node = new RatioNode(text, pos.x, pos.y, w, h)
  node.direction = 'up'
  node.ratio = 0.8
  node.css({
    border: 'solid 2px #0fd63f',
    backgroundColor: '#000',
    fillStyle: '#21993e',
    shadowColor: "#009A93"
  })
  this.layer.addChild(node)
  const ratioNodeTip = new Node()
  ratioNodeTip.width = 16
  ratioNodeTip.height = 8
  ratioNodeTip.css({
    border: 'solid 2px #0fd63f'
  })
  ratioNodeTip.translate(0, -node.height / 2 - 2)
  node.addChild(ratioNodeTip)
}

在这里插入图片描述

  1. 添加图片
/**
 * 图片
 * @param pos 坐标:{ x: x, y: y }
 * @param w 宽度
 * @param h 高度
 * @param image 图片url
 */
static addImage(pos: any, w: number, h: number, image: string) {
  const node = new Node('', pos.x, pos.y, w, h)
  this.layer.addChild(node)
  node.setImage(image, '')
  node.resizeTo(w, h)
}

在这里插入图片描述

常用方法汇总


  1. 设置样式
    node.setStyles(styleOpt: any)
  2. 设置文本
    node.setText(v: string)
  3. 设置图片
    node.setImage(img: any, fitSize: any)
  4. 添加子对象
    layer.addChild(child: DisplayObject)
    node.addChild(child: DisplayObject)
  5. 图层更新
    layer.update()
  6. 清空当前画布并加载json内容
    layer.openJson(json: string)
  7. 生成json字符串
    editor.toJson()
  8. 自动居中画面到Stage的中心
    stage.translateToCenter()
  9. 设置场景模式
    stage.setMode(mode: StageModeType)
  10. 隐藏工具条
    stage.hideToolbar()

注意点


  1. 节点拖拽结束鼠标停留处生成对象
<div id="topo" class="content"></div>
const el = document.getElementById('topo')
el && el.addEventListener('drop', dropEvent)
const dropEvent = function (this: any, o: any) {
  const pos = { x: o.pageX - this.offsetLeft - this.offsetWidth / 2, y: o.pageY - this.offsetTop - this.offsetHeight / 2 }
}

ps:

画布坐标原点位于正中心,需减去画布长宽的一半

在这里插入图片描述

  1. 针对特殊节点对象添加子节点
    在这里插入图片描述
/**
 * 文字子节点
 * @param text 文本
 * @param pos 坐标:{ x: x, y: y }
 * @param parentNode 父节点
 */
static addChildText (text: string, pos: any, parentNode: any) {
  const node = new TextNode(text, pos.x, pos.y)
  node.alignOriginToNode('lt', 'lt')
  const cssObj = {
    color: config.textNodeColor,
    textPosition: 'lt',
    textBaseline: 'top',
    textAlign: 'left',
    font: '14px arial'
  }
  node.setStyles(cssObj)
  parentNode.addChild(node)
}
  1. 卡顿问题
    输入文字或设置样式等操作时会出现卡顿,导致更新延迟,可调用图层的更新方法layer.update()

总结


刚开始接到这个需求有点不知所措,官方文档不够详细,使用这个插件的大神少之又少。一路磕磕绊绊,看着源码反复试错,总算有个雏形了。当然还有很多需要完成完善的地方,不过问题不大。
下班!!冲冲冲!!

在这里插入图片描述

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值