当前位置:   article > 正文

关于jointjs的详细介绍

jointjs

1. 介绍

1.1 JointJS简介

        JointJS是一个专注于图形可视化的js库,用于创建交互式的图形和图表。它基于HTML、SVG(可缩放矢量图形)和CSS(层叠样式表)技术,主要用于在Web应用程序中实现可视化图形编辑器或图表展示(流程图、关系图和定制化图形)。

1.2 JointJS的特点
  • 可定制性: JointJS允许开发人员根据项目需求自定义图形元素和交互行为。
  • 跨浏览器支持: JointJS能够在主流的现代浏览器中运行,确保跨平台和跨设备的兼容性。
  • 丰富的功能: 支持图形元素的拖放、缩放、连接等交互功能,以及事件监听和处理。

2. 安装与配置

2.1 下载与安装

由于jointJS是基于backbone( 实现了web前端MVC模式的js库 )的,因此有view(视图)和model(模型)的概念,使用jointJS需要引入jQuery、backbone、lodash以及jointJS的包,可以通过script标签引入,也可以通过npm安装。

官网地址:Tutorials - JointJS Docs

中文文档:JointJS官方API的个人整理_graph.resetcells-CSDN博客

  • 下载本地文件:http://pan.baidu.com/s/1miKFmY0 密码:rlhh

  1. <head>
  2. <meta name="viewport" content="width=device-width, initial-scale=1">
  3. <title>JointJS Sample</title>
  4. <meta charset="UTF-8">
  5. <link rel="stylesheet" type="text/css" href="css/joint.min.css" />
  6. <!-- 下面的顺序不能变 -->
  7. <script src="js/jquery.js"></script>
  8. <script src="js/lodash.js"></script>
  9. <script src="js/backbone.js"></script>
  10. <script src="js/joint.js"></script>
  11. <!-- 这是自己的JS文件 -->
  12. <script type="text/javascript" src="js/main.js"></script>
  13. </head>
  14. <body>
  15. <div id="canvas"></div>
  16. </body>
  • 使用CDN :
  1. <head>
  2. <meta name="viewport" content="width=device-width, initial-scale=1">
  3. <title>JointJS Sample</title>
  4. <meta charset="UTF-8">
  5. <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jointjs/2.2.1/joint.min.css">
  6. <!--注意加载顺序-->
  7. <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
  8. <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
  9. <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone.js"></script>
  10. <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jointjs/2.2.1/joint.min.js"></script>
  11. </head>
  •  npm安装:
npm install jointjs

 以下是JointJS的一个简单示例代码:

  1. <template>
  2. <div class="canvas" ref="canvas"></div>
  3. </template>
  4. <script>
  5. import * as joint from 'jointjs'
  6. export default {
  7. data () {
  8. return {
  9. paper: null
  10. }
  11. },
  12. mounted() {
  13. this.init()
  14. },
  15. methods: {
  16. init() {
  17. // 创建了两个矩形元素和一个连接它们的图形
  18. let graph = new joint.dia.Graph // 创建画板,所有图上的元素都在画板里
  19. this.paper = new joint.dia.Paper({ // 创建画板上的画布,画布是用来渲染画板
  20. el: this.$refs.canvas, // HTML上div ID document.getElementById('canvas'),
  21. model: graph, // 指定画板
  22. width: 600,
  23. height: 100,
  24. gridSize: 1 // 画布上元素拖动时步进的像素,默认1,设的高方便对齐
  25. })
  26. // 创建一个矩形
  27. let rect = new joint.shapes.standard.Rectangle()
  28. rect.position(100, 30) // 矩形左上角的位置,x:100,y:30,单位像素
  29. rect.resize(100, 40) // 矩形大小,宽100,高40,单位像素
  30. rect.attr({
  31. body: {
  32. fill: 'blue' // 填充色
  33. },
  34. label: {
  35. text: 'Hello', // 矩形上显示的文字
  36. fill: 'white', // 文字颜色
  37. },
  38. })
  39. rect.addTo(graph) // 将上面定义的矩形加入到画板中
  40. let rect2 = rect.clone() // 复制一个相同的矩形
  41. rect2.translate(300, 0) // 将矩形在水平方向上向右移动300像素
  42. rect2.attr('label/text', 'World!') // 设置矩形2上的文字
  43. rect2.addTo(graph) // 将矩形2加入到画板中
  44. let link = new joint.shapes.standard.Link() // 创建一条连线
  45. link.source(rect) // 连线头为矩形1
  46. link.target(rect2) // 连线尾为矩形2
  47. link.addTo(graph) // 将上面定义的连线加入到画板中
  48. }
  49. }
  50. }
  51. </script>
  52. <style></style>

运行结果: 

3. JointJS的一些基础知识:

  1. 元素(Element)和连接(Link):JointJS允许你创建元素和连接它们以形成图形,有预设和自定义两种。元素可以是各种形状,如矩形、圆形等,而连接通常是两个元素之间的线。
  2. 图形(Graph):JointJS中的图形是一个包含元素和连接的容器。你可以在图形中添加、删除和编辑元素,以及定义它们之间的连接关系。
  3. 模型(Model):JointJS使用模型来表示图形中的元素和连接。每个元素和连接都是一个模型,可以设置各种属性,如位置、大小、样式等。
  4. 图形编辑器(Graph Editor):JointJS通常用于构建图形编辑器,用户可以通过该编辑器添加、删除和调整图形元素,创建连接等。
  5. 视图(View):视图是JointJS中用于渲染图形的组件。它负责显示模型中定义的元素和连接,并处理用户输入。
  6. 事件(Event):JointJS支持丰富的事件系统,可以监听元素的拖动、缩放、连接等操作。通过事件,你可以在用户与图形交互时执行相应的操作。
  7. 样式和主题(Style and Theme):JointJS允许你定义元素和连接的样式,包括颜色、边框、字体等。你还可以使用主题来统一整个图形的外观。
  8. 导入和导出(Import and Export):JointJS提供了导入和导出图形数据的功能,这使得你可以保存用户创建的图形,也可以加载已保存的图形。

4. JointJS创建一个基础图形的步骤:

  4.1 首先要引入相应的js和css文件,还有一些依赖;
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1.0,user-scalable=no" />
  6. <title>Title</title>
  7. <link rel="stylesheet" type="text/css" href="css/joint.css">
  8. <!--注意加载顺序-->
  9. <script src="js/jquery-3.2.1.min.js" type="text/javascript" charset="utf-8"></script>
  10. <script src="js/lodash.js"></script>
  11. <script src="js/backbone-min.js"></script>
  12. <script src="js/joint.min.js"></script>
  13. <style>
  14. #wrapper {
  15. margin: 10px auto;
  16. background: #fafafa;
  17. }
  18. </style>
  19. </head>
  20. <body>
  21. <!--准备一个容器存放画板-->
  22. <div id="wrapper"></div>
  23. </body>
  24. </html>
  4.2 定义画板和画布
  1. var graph = new joint.dia.Graph; //生成画板
  2. var paper = new joint.dia.Paper({ //生成画布
  3. el: $('#wrapper'),
  4. width: 800,
  5. height: 500,
  6. model: graph,
  7. gridSize: 1
  8. });
  4.3 画一个简单的矩形
  1. var cell = new joint.shapes.basic.Rect({
  2. position: {
  3. x: 100,
  4. y: 100
  5. },
  6. size: {
  7. width: 100,
  8. height: 100
  9. },
  10. attrs: {
  11. //边框,填充,边框宽度,样式
  12. rect: {
  13. fill: 'pink',
  14. 'stroke': 'black',
  15. 'stroke-width': 2,
  16. 'stroke-dasharray': 0
  17. },
  18. text: {
  19. //字体内容,颜色,粗细,大小
  20. text: '矩形',
  21. fill: 'black',
  22. 'font-weight': 'normal',
  23. 'font-size': 20
  24. }
  25. }
  26. });
  27. //把矩形放到画板中
  28. graph.addCells([cell]);
  4.4 改变这个矩形的一些属性
  • 改变位置
  1. cell.position(20, 20);
  2. console.log(cell.get('position')); //{x: 20, y: 20}
  •  改变大小
  1. cell.size(50, 50);
  2. console.log(cell.get('size')); //{width: 50, height: 50}
  • 改变文本
  1. cell.attr('text/text', '测试文本');
  2. cell.attr('text/fill', 'white');
  3. cell.attr('text/font-weight', 'bold');
  4. cell.attr('text/font-size', 14);
  • 改变图形
cell.attr('rect/stroke-dasharray', '2,5');  //虚线间隙
  • 偏移
cell.translate(10, 10)
  • 拉伸
cell.resize(120, 120)
  • 旋转
cell.rotate(45)
  • 改变z-index
  1. cell.toFront()
  2. cell.toBack()
  • 组合图形
  1. cell.embed(cell1) //当移动cell时,cell1也会跟着移动
  2. cell.unembed(cell1) // 取消跟着移动
  • 复制图形
cell.clone()
  • 删除图形
cell.remove()
  • 改变画布背景​​​​​​​
  1. paper.drawBackground({
  2. color: color
  3. });
  • 改变画布大小
paper.setDimensions(width, height);

5​​​​​​​. JointJS示例:

转载自:用JointJS做一个简单的功能控制图 | 思诚之道

做一个简单的自动化功能控制图:

5.1 首先要引入相应的js和css文件,还有一些依赖
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta name="viewport" content="width=device-width, initial-scale=1">
  5. <title>FBD Diagram</title>
  6. <meta name="description" content="功能控制图设计器" />
  7. <meta charset="UTF-8">
  8. <link rel="stylesheet" type="text/css" href="css/joint.min.css" />
  9. <script src="js/jquery.js"></script>
  10. <script src="js/lodash.js"></script>
  11. <script src="js/backbone.js"></script>
  12. <script src="js/joint.js"></script>
  13. <script src="js/main.js"></script>
  14. </head>
  15. <body>
  16. 将元素从左边拖入画布,双击删除
  17. <div id="myholder"></div>
  18. <button id="saveButton">保存</button>
  19. <button id="loadButton">加载</button> 图模型保存为JSon格式:
  20. <textarea id="mySavedModel" style="width:100%;height:300px">
  21. </textarea>
  22. </body>
  23. </html>

5.2 定义画板和画布

  1. var graph = new joint.dia.Graph; // 创建画板,所有图上的元素都在画板里
  2. var paper = new joint.dia.Paper({ // 创建画板上的画布,画布是用来渲染画板
  3. el: $('#myholder'), // 指向HTML里ID为"myGraph"的元素
  4. model: graph, // 指定画板
  5. width: 600, // 画布宽600像素
  6. height: 300, // 画布高300像素
  7. gridSize: 5, // 画布上元素拖动时步进的为5像素,默认1
  8. drawGrid: true, // 显示步进点,方便对齐
  9. background: { // 画布背景色
  10. color: 'rgba(0, 0, 0, 0.1)'
  11. },
  12. // 连接线风格
  13. defaultLink: new joint.shapes.logic.Wire({
  14. connector: { name: 'jumpover' }, // 当两根连线交叉时,其中一根跳过
  15. }),
  16. linkPinning: false, // 连线必须连到某个元素,即不允许连到空白处
  17. snapLinks: {
  18. radius: 25 // 距离元素连接点25像素时自动连接上
  19. },
  20. // 验证连线是否允许,
  21. validateConnection: function(viewSource, magnetSource, viewTarget, magnetTarget, end, viewLink) {
  22. if (end === 'target') {
  23. // 连线目标必须时一个"in"类型连接点
  24. if (!magnetTarget || !magnetTarget.getAttribute('port-group') || magnetTarget.getAttribute('port-group').indexOf('in') < 0) {
  25. return false;
  26. }
  27. // 检查连接点是否已经有连线接入,不允许多重接入
  28. var portUsed = this.model.getLinks().some(function(link) {
  29. return (link.id !== viewLink.model.id &&
  30. link.get('target').id === viewTarget.model.id &&
  31. link.get('target').port === magnetTarget.getAttribute('port'));
  32. });
  33. return !portUsed;
  34. } else { // end === 'source'
  35. // 连线起始点必须时一个"out"类型连接点
  36. return magnetSource && magnetSource.getAttribute('port-group') && magnetSource.getAttribute('port-group').indexOf('out') >= 0;
  37. }
  38. },
  39. });

        上面的属性有些多,但大部分都好理解,主要是验证函数validateConnection(),其返回truefalse,用来决定连线是否被允许。传入的参数viewSourceviewTarget分别是画线过程中鼠标按钮释放时,当前连线头和尾的元素;而参数magnetSourcemagnetTarget分别是当前连线头和尾的”连接点”(port)。”连接点”的概念下面会讲到。

5.3 定义基本图例元素

        这里,我们创建了与、或、非,三个基本元素,因为是图例元素,所以不允许连入连出。我们使用标准库提供的”joint.shapes.devs.Model”元素,因为它很方便设置”连接点”(port)。

  1. // 创建基础元件模板
  2. var gateTemplate = new joint.shapes.devs.Model({
  3. position: { // 默认位置
  4. x: 0,
  5. y: 0
  6. },
  7. size: { // 默认大小
  8. width: 50,
  9. height: 60
  10. },
  11. // "连接点"(port)的风格
  12. portMarkup: '<rect class="joint-port-body" width="10" height="3" style="fill:black" />',
  13. // "连接点"(port)标签文字的显示风格
  14. portLabelMarkup: '<text class="port-label joint-port-label" font-size="10" y="0" fill="#000" /> ',
  15. ports: { // 定义连接点
  16. groups: {
  17. 'in': { // "入"连接点的属性和风格
  18. attrs: {
  19. '.port-body': { // 这是JointJS类库预定义的连接点属性类
  20. magnet: 'passive', // 该连接点只入不出
  21. },
  22. '.joint-port-body': { // 这是JointJS类库预定义的连接点风格类
  23. x:-10 // "入"连接点左移10个像素,这样可以显示在元素外部
  24. }
  25. },
  26. label: {
  27. position: {
  28. args: {x:18}, // 标签右移,这样可以显示在元素内部
  29. },
  30. },
  31. },
  32. 'out': {
  33. label: { // "出"连接点的属性和风格
  34. position: {
  35. args: {x:-23}, // 标签左移,这样可以显示在元素内部
  36. },
  37. },
  38. }
  39. }
  40. },
  41. attrs: {
  42. '.label': {
  43. 'type': 'primary', // 自定义一个图例属性,后面事件操作时判断用
  44. fontSize: 12, // 标签字体
  45. 'ref-x': .5, // 标签相对于元素的水平位置
  46. 'ref-y': .05 // 标签相对于元素的垂直位置
  47. },
  48. }
  49. });
  50. // 生成"与"元素,两个"入"连接点,一个"出"连接点,显示"And"字样标签
  51. function genAndPr() {
  52. return gateTemplate.clone().set('inPorts', ['IN1', 'IN2']).set('outPorts', ['OUT']).attr('.label/text', 'And');
  53. }
  54. // 生成"或"元素,两个"入"连接点,一个"出"连接点,显示"Or"字样标签
  55. function genOrPr() {
  56. return gateTemplate.clone().set('inPorts', ['IN1', 'IN2']).set('outPorts', ['OUT']).attr('.label/text', 'Or');
  57. }
  58. // 生成"非"元素,一个"入"连接点,一个"出"连接点,显示"Not"字样标签
  59. function genNotPr() {
  60. return gateTemplate.clone().set('inPorts', ['IN ']).set('outPorts', ['OUT']).attr('.label/text', 'Not');;
  61. }
  62. // 图例加入到画板左侧
  63. graph.addCell(genAndPr().translate(20, 20));
  64. graph.addCell(genOrPr().translate(20, 120));
  65. graph.addCell(genNotPr().translate(20, 220));
  66. // 添加一个分割栏将图例和绘图区域分开
  67. var separator = new joint.shapes.standard.Polyline();
  68. separator.resize(5, 400);
  69. separator.position(95, 0);
  70. separator.addTo(graph);

         上面关键的概念就是”连接点”(port),JointJS库中joint.shapes.devs.Model元素默认支持”入”(in)和”出”(out)两种连接点,分别显示在元素图形的左边和右边,多个连接点会自动排列。通过前一段代码中paperlinkPinning属性设置,可以要求”连线”只允许接在”连接点”上。上面我们定义了”连接点”风格为一个长10px3px的水平线。上例中,因为我重写了”连接点”的标记portMarkup,去掉了允许连线的属性,所以这些连接点目前都无法被连线。

5.4 定义绘图元素

  1. function genAnd() {
  2. return genAndPr().set('portMarkup', '<rect class="port-body joint-port-body" width="10" height="2" style="fill:black" />').attr('.label/type', 'instance');
  3. }
  4. function genOr() {
  5. return genOrPr().set('portMarkup', '<rect class="port-body joint-port-body" width="10" height="2" style="fill:black" />').attr('.label/type', 'instance');
  6. }
  7. function genNot() {
  8. return genNotPr().set('portMarkup', '<rect class="port-body joint-port-body" width="10" height="2" style="fill:black" />').attr('.label/type', 'instance');
  9. }

        将图例元素中的portMarkup改了,其实就是增加了css类port-body,这是JointJS库中预定义的。该类中设置了”元素”的magnet属性,设为true时可入可出;passive时只入不出;false时不能连线。这样,我们的绘图元素就可以接上连线了。另外,这里将自定义属性.label/type改为instance主要是后面的事件判断用。

5.5 定义鼠标事件,来支持将图例元素拖入绘图区域

  1. paper.on({ // JointJS事件都定义在画布上
  2. // 当鼠标左键按下时
  3. 'element:pointerdown': function(elementView, evt) {
  4. // 当图例元素被拖走时,在原来的位置创建一个新的图例元素
  5. if (elementView.model.attr('.label/type') == 'primary') {
  6. var type = elementView.model.attr('.label/text');
  7. if (type == 'And') {
  8. graph.addCell(genAndPr().translate(20, 20));
  9. } else if (type == 'Or') {
  10. graph.addCell(genOrPr().translate(20, 120));
  11. } else if (type == 'Not') {
  12. graph.addCell(genNotPr().translate(20, 220));
  13. }
  14. // 被拖动的元素挪到图层的最上层,这样可以遮盖现有元素
  15. elementView.model.toFront();
  16. } else if (elementView.model.attr('.label/type') == 'instance') {
  17. // 对于绘图元素,记住其被拖动时的起始点,当拖动位置超出绘图区域时,可以回到原点
  18. evt.data = elementView.model.position();
  19. }
  20. },
  21. // 当鼠标左键抬起时
  22. 'element:pointerup': function(elementView, evt, x, y) {
  23. if (elementView.model.attr('.label/type') == 'primary') {
  24. // 对于图例元素,当其被拖入绘图区域时,则在该位置创建一个新的绘图元素,并删除被拖动的图例元素
  25. if (elementView.model.position().x > 105) {
  26. var type = elementView.model.attr('.label/text');
  27. if (type == 'And') {
  28. graph.addCell(genAnd().translate(elementView.model.position().x, elementView.model.position().y));
  29. } else if (type == 'Or') {
  30. graph.addCell(genOr().translate(elementView.model.position().x, elementView.model.position().y));
  31. } else if (type == 'Not') {
  32. graph.addCell(genNot().translate(elementView.model.position().x, elementView.model.position().y));
  33. }
  34. }
  35. // 删除当前被拖动的元素
  36. graph.removeCells(elementView.model);
  37. } else {
  38. // 对于绘图元素,当其被拖出绘图区域时,则将其移回原点
  39. if (elementView.model.position().x < 110) {
  40. elementView.model.position(evt.data.x, evt.data.y);
  41. }
  42. }
  43. },
  44. // 当鼠标左键双击时
  45. 'element:pointerdblclick': function(elementView, evt) {
  46. // 双击绘图元素则删除该元素,相应的连线也会被自动删除
  47. if (elementView.model.attr('.label/type') == 'instance') {
  48. elementView.model.remove();
  49. }
  50. },
  51. })

​​​​​​​

JointJS的事件都定义在画布paper上,可以参考​​​​​​​这里的说明事件的种类很多,可以在”元素”、”连线”或”空白处”上监听,可以是各种鼠标事件,这里不赘述了。大部分事件都接受4个参数:

  • “cellView”(或叫”elementView”) – 事件监听的主体,可以通过elementView.model来获得元素对象,并对其做各种设置
  • “evt” – 保存信息用于在事件间传数据
  • “x”和”y” – 记录事件发生时鼠标的位置

上例中的事件函数,定义了将图例元素拖入绘图区域,并创建一个新的绘图元素的过程。

保存上面的代码并在浏览器里打开,大家应该可以看到如下内容。

        JointJS源码托管在Github中。更详细的开发API文档可以在官方API文档中找到。 本文中的示例代码,可以在这里下载

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/526287
推荐阅读
  

闽ICP备14008679号