웹 프론트엔드 JS 튜토리얼 JS 프런트 엔드 그래픽 플러그인 도구 Gojs 구성 요소

JS 프런트 엔드 그래픽 플러그인 도구 Gojs 구성 요소

May 12, 2018 am 09:32 AM
gojs javascript 날카로운 무기

JsPlumb을 사용하여 프로세스 드로잉의 프런트 엔드 구성 요소에 대해 이전에 두 개의 기사를 공유한 적이 있습니다. 이 컴포넌트 자체는 나쁘지 않은데, 사용하기 쉽고, 시작하기 쉽고, 가볍습니다. 그러나 일정 기간 사용해 본 결과, 처음 들어왔을 때 컴포넌트가 안정적이지 않다는 등의 단점을 발견했습니다. 페이지 연결 스타일이 엉망이 되는 경우가 있는데, 페이지를 새로 고쳐야 정상으로 돌아갈 수 있고, 배선 스타일도 상대적으로 단순해 최근에는 시각적인 피로도가 심해졌습니다. 소위 "Industry 4.0"을 추진하면서 자동화 제어에 대한 요구 사항도 증가했고, 따라서 단순한 jsPlumb 구성 요소의 효과로는 더 이상 성장하는 회사의 비즈니스를 만족시킬 수 없습니다. 위 내용을 바탕으로 강력한 효과와 풍부한 API를 갖춘 Gojs 컴포넌트를 드디어 찾았습니다. 유일한 단점은 이 컴포넌트가 유료 컴포넌트라는 것입니다.

1. 구성요소 효과 미리보기

두 가지 멋진 효과부터 시작해 보겠습니다.

아래 두 가지 효과는 jsPlumb로는 얻을 수 없지만 이 효과는 MES 시스템, 특히 일부 프로세스 기반 비즈니스에서는 매우 매력적입니다. 이 효과를 사용하면 한눈에 키가 커집니다. 그리고 언뜻 보면 이것이 웹페이지의 효과라고 믿지 않을 것입니다.

기타 효과 예시

접이식 나무

이게 사진인가요?

차트도 생성할 수 있습니다!

visio의 일자리를 구하고 싶으신가요?

공식 홈페이지에서 더 많은 예시를 보실 수 있습니다

2. 첫 번째 문의

1 Gojs 소개

GoJS는 풍부한 기능을 갖춘 JS입니다. 도서관. 웹 브라우저 맞춤형 상호 작용 다이어그램과 복잡한 시각화 효과를 플랫폼에서 구현할 수 있습니다. 맞춤형 템플릿과 레이아웃 구성 요소를 사용하여 노드, 링크, 그룹 등 복잡한 JS 다이어그램을 단순화하고 드래그와 같은 사용자 상호 작용을 위한 다양한 고급 기능을 제공합니다. 앤 드롭, 복사, 붙여넣기, 텍스트 편집, 도구 설명, 상황에 맞는 메뉴, 자동 레이아웃, 템플릿, 데이터 바인딩 및 모델, 트랜잭션 상태 및 실행 취소 관리, 팔레트, 개요, 이벤트 핸들러, 명령 및 사용자 정의 작업을 위한 광범위한 도구 시스템입니다. GoJS는 사용자 상호 작용을 지원하고 브라우저에서 완전히 실행되어 서버나 플러그인을 전환할 필요 없이 서버 측 요청 없이 HTML5 Canvas 요소 또는 SVG를 렌더링합니다. GoJS는 JS 라이브러리나 프레임워크(예: bootstrap, jquery 등)에 의존하지 않으며 HTML이나 JS 프레임워크와 함께 작동할 수 있으며 심지어 프레임워크 없이도 작동할 수 있습니다.

2. 시작하기

(1) 파일 참조

코드 복사 코드는 다음과 같습니다.

<script src="gojs/go-debug_ok.js"></script>
로그인 후 복사

최신 버전을 CDN에서 사용하시거나, 로컬에서 다운로드 받은 것을 참고하시면 됩니다. 파일. 개발이라면 디버그 버전의 js를 인용하면 되고, 공식적으로 실행할 때는 공식 js를 인용하면 됩니다. 이에 대해서는 더 이상 말할 필요가 없습니다.

(2) 캔버스 만들기

html 요소를 캔버스로 정의하기만 하면 됩니다

코드를 복사하세요코드는 다음과 같습니다.

<p id="myDiagramp" style="margin:auto;width:300px; height:300px; background-color:#ddd;"></p>
로그인 후 복사

그런 다음 gojs API를 사용하여 캔버스를 초기화합니다

//创建画布
  var objGo = go.GraphObject.make;
  var myDiagram = objGo(go.Diagram, "myDiagramp",
   {
    //模型图的中心位置所在坐标
    initialContentAlignment: go.Spot.Center,
    
    //允许用户操作图表的时候使用Ctrl-Z撤销和Ctrl-Y重做快捷键
    "undoManager.isEnabled": true,
    
    //不运行用户改变图表的规模
    allowZoom: false,

    //画布上面是否出现网格
    "grid.visible": true,

    //允许在画布上面双击的时候创建节点
    "clickCreatingTool.archetypeNodeData": { text: "Node" },

    //允许使用ctrl+c、ctrl+v复制粘贴
    "commandHandler.copiesTree": true, 

    //允许使用delete键删除节点
    "commandHandler.deletesTree": true, 

    // dragging for both move and copy
    "draggingTool.dragsTree": true, 
   });
로그인 후 복사

공식 예제에서는 다음을 사용합니다. $ 기호를 변수로 사용하는 경우, 블로거는 $ 기호가 너무 민감하다고 생각하므로 이름을 변경하겠습니다~ 위 매개변수는 블로거가 캔버스를 초기화하기 위해 선택한 매개변수에 대한 자세한 내용은 아래 공식 API 그림을 참조하세요.

(3)创建模型数据(Model)

接着上面的代码,我们增加如下几行

var myModel = objGo(go.Model);//创建Model对象
  // model中的数据每一个js对象都代表着一个相应的模型图中的元素
  myModel.nodeDataArray = [
   { key: "工厂" },
   { key: "车间" },
   { key: "工人" },
   { key: "岗位" },
  ];
  myDiagram.model = myModel; //将模型数据绑定到画布图上
로그인 후 복사

效果预览

(4)创建节点(Node)

上面有了画布和节点数据,只是有了一个雏形,但是还没有任何的图形化效果。我们加入一些效果试试

在gojs里面给我们提供了几种模型节点的可选项:

Shape:形状——Rectangle(矩形)、RoundedRectangle(圆角矩形),Ellipse(椭圆形),Triangle(三角形),Diamond(菱形),Circle(圆形)等
TextBlock:文本域(可编辑)
Picture:图片
Panel:容器来保存其他Node的集合
默认的节点模型代码只是由一个TextBlock组件构建成

我们增加如下一段代码

// 定义一个简单的节点模板
  myDiagram.nodeTemplate =
   objGo(go.Node, "Horizontal",//横向布局的面板
    // 节点淡蓝色背景
    { background: "#44CCFF" },
    objGo(go.Shape,
     "RoundedRectangle", //定义形状,这是圆角矩形
     { /* Shape的参数。宽高颜色等等*/figure: "Club", width: 40, height: 60, margin: 4, fill: &#39;red&#39; },
     // 绑定 Shape.figure属性为Node.data.fig的值,Model对象可以通过Node.data.fig 获取和设置Shape.figure(修改形状)
     new go.Binding("figure", "fig"), new go.Binding(&#39;fill&#39;, &#39;fill2&#39;)),
    objGo(go.TextBlock,
     "Default Text", // 默认文本
     // 设置字体大小颜色以及边距
     { margin: 12, stroke: "white", font: "bold 16px sans-serif" },
     //绑定TextBlock.text 属性为Node.data.name的值,Model对象可以通过Node.data.name获取和设置TextBlock.text
     new go.Binding("text", "name"))
   );

  var myModel = objGo(go.Model);//创建Model对象
  // model中的数据每一个js对象都代表着一个相应的模型图中的元素
  myModel.nodeDataArray = [
   { name: "工厂", fig: &#39;YinYang&#39;, fill2: &#39;blue&#39; },
   { name: "车间", fig: &#39;Peace&#39;, fill2: &#39;red&#39; },
   { name: "工人", fig: &#39;NotAllowed&#39;, fill2: &#39;green&#39; },
   { name: "岗位", fig: &#39;Fragile&#39;, fill2: &#39;yellow&#39; },
  ];
  myDiagram.model = myModel; //将模型数据绑定到画布图上
로그인 후 복사

代码释疑:以上我们给画布对象定义了两种节点模板,一种是文本节点,另一种是形状节点(Node)。在形状节点中,我们定义了数据模型的通用节点样式,就是这一段代码{ /* Shape的参数。宽高颜色等等*/figure: "Club", width: 40, height: 60, margin: 4, fill: 'red' },然后通过new go.Binding("figure", "fig")方法将模板里面的属性映射到数据实例中,比如这里模板里面的figure属性定义的是Club,如果在我们的数据里面定义fig属性,那么它就会覆盖模板里面的figure的默认值。同样,fill和fill2也是通过同样的原理去区别模板中的样式和实例中的实际样式的!

注:更多figure属性的取值详见这里

效果如下

由此可见我们数据里面的属性会覆盖模板的原始属性,如果是新增的节点,由于没有自定义数据属性,所以呈现到界面上面的时候就是模板里面的原生样式!

(5)节点连线

有了上面的基础,我们可以在画布上面画出我们想要的图形效果了,可是还没有连线。我们知道连线是建立在节点模型的上面的,于是乎我们的Model又分为了以下三种类型:

Model:最基本的(不带连线,如上面的例子)

GraphLinksModel :高级点的动态连线图

TreeModel:树形图的模型(从例子看好像用的不多)

GraphLinksModel中为model.nodeDataArray提供model.linkDataArray为node节点连线保存数据模型信息,其实也是的一个JSON数组对象,每个线条都有两个属性 “to” 和 “from” 即Node节点的“key”值,两个属性代表两个key表示两个节点间的连线。

我们上面已经写过最基本的Model的例子了,我们再来个带连线的Model的示例

var myModel = objGo(go.GraphLinksModel);
  myModel.nodeDataArray =
   [
    { key: "aaa" ,name: "工厂" },
    { key: "bbb" ,name: "车间"},
    { key: "ccc" ,name: "车间" }
   ];
  myModel.linkDataArray =
   [
    { from: "aaa", to: "bbb" },
    { from: "bbb", to: "ccc" }
   ];
  myDiagram.model = myModel;
로그인 후 복사

效果如下

学习了Model、GraphLinksModel,还剩下一种TreeModel树节点的模型,这个博主不打算做详细介绍,有兴趣可以直接查看官网。

三、综合效果

关于综合效果,博主不打算将gojs的api逐个翻个遍了,这样太耗时间,伤不起,只是将官方示例中的部分源码截取出来供大家参考。有需要的再细究!

1、自定义流程的使用

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Draggable Link</title>
<meta name="description" content="Drag a link to reconnect it. Nodes have custom Adornments for selection, resizing, and reshaping." />
<!-- Copyright 1998-2017 by Northwoods Software Corporation. -->
<meta charset="UTF-8">
<script src="../../gojs/go-debug.js"></script>
<script id="code">
 function init() {
 if (window.goSamples) goSamples(); // init for these samples -- you don&#39;t need to call this
 var objGo = go.GraphObject.make; // for conciseness in defining templates

 myDiagram =
  objGo(go.Diagram, "myDiagramp", // must name or refer to the p HTML element
  {
   grid: objGo(go.Panel, "Grid",
     objGo(go.Shape, "LineH", { stroke: "lightgray", strokeWidth: 0.5 }),
     objGo(go.Shape, "LineH", { stroke: "gray", strokeWidth: 0.5, interval: 10 }),
     objGo(go.Shape, "LineV", { stroke: "lightgray", strokeWidth: 0.5 }),
     objGo(go.Shape, "LineV", { stroke: "gray", strokeWidth: 0.5, interval: 10 })
    ),
   allowDrop: true, // must be true to accept drops from the Palette
   "draggingTool.dragsLink": true,
   "draggingTool.isGridSnapEnabled": true,
   "linkingTool.isUnconnectedLinkValid": true,
   "linkingTool.portGravity": 20,
   "relinkingTool.isUnconnectedLinkValid": true,
   "relinkingTool.portGravity": 20,
   "relinkingTool.fromHandleArchetype":
   objGo(go.Shape, "Diamond", { segmentIndex: 0, cursor: "pointer", desiredSize: new go.Size(8, 8), fill: "tomato", stroke: "darkred" }),
   "relinkingTool.toHandleArchetype":
   objGo(go.Shape, "Diamond", { segmentIndex: -1, cursor: "pointer", desiredSize: new go.Size(8, 8), fill: "darkred", stroke: "tomato" }),
   "linkReshapingTool.handleArchetype":
   objGo(go.Shape, "Diamond", { desiredSize: new go.Size(7, 7), fill: "lightblue", stroke: "deepskyblue" }),
   rotatingTool: objGo(TopRotatingTool), // defined below
   "rotatingTool.snapAngleMultiple": 15,
   "rotatingTool.snapAngleEpsilon": 15,
   "undoManager.isEnabled": true
  });

 // when the document is modified, add a "*" to the title and enable the "Save" button
 myDiagram.addDiagramListener("Modified", function(e) {
  var button = document.getElementById("SaveButton");
  if (button) button.disabled = !myDiagram.isModified;
  var idx = document.title.indexOf("*");
  if (myDiagram.isModified) {
  if (idx < 0) document.title += "*";
  } else {
  if (idx >= 0) document.title = document.title.substr(0, idx);
  }
 });

 // Define a function for creating a "port" that is normally transparent.
 // The "name" is used as the GraphObject.portId, the "spot" is used to control how links connect
 // and where the port is positioned on the node, and the boolean "output" and "input" arguments
 // control whether the user can draw links from or to the port.
 function makePort(name, spot, output, input) {
  // the port is basically just a small transparent square
  return objGo(go.Shape, "Circle",
    {
     fill: null, // not seen, by default; set to a translucent gray by showSmallPorts, defined below
     stroke: null,
     desiredSize: new go.Size(7, 7),
     alignment: spot, // align the port on the main Shape
     alignmentFocus: spot, // just inside the Shape
     portId: name, // declare this object to be a "port"
     fromSpot: spot, toSpot: spot, // declare where links may connect at this port
     fromLinkable: output, toLinkable: input, // declare whether the user may draw links to/from here
     cursor: "pointer" // show a different cursor to indicate potential link point
    });
 }

 var nodeSelectionAdornmentTemplate =
  objGo(go.Adornment, "Auto",
  objGo(go.Shape, { fill: null, stroke: "deepskyblue", strokeWidth: 1.5, strokeDashArray: [4, 2] }),
  objGo(go.Placeholder)
  );

 var nodeResizeAdornmentTemplate =
  objGo(go.Adornment, "Spot",
  { locationSpot: go.Spot.Right },
  objGo(go.Placeholder),
  objGo(go.Shape, { alignment: go.Spot.TopLeft, cursor: "nw-resize", desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "deepskyblue" }),
  objGo(go.Shape, { alignment: go.Spot.Top, cursor: "n-resize", desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "deepskyblue" }),
  objGo(go.Shape, { alignment: go.Spot.TopRight, cursor: "ne-resize", desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "deepskyblue" }),

  objGo(go.Shape, { alignment: go.Spot.Left, cursor: "w-resize", desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "deepskyblue" }),
  objGo(go.Shape, { alignment: go.Spot.Right, cursor: "e-resize", desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "deepskyblue" }),

  objGo(go.Shape, { alignment: go.Spot.BottomLeft, cursor: "se-resize", desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "deepskyblue" }),
  objGo(go.Shape, { alignment: go.Spot.Bottom, cursor: "s-resize", desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "deepskyblue" }),
  objGo(go.Shape, { alignment: go.Spot.BottomRight, cursor: "sw-resize", desiredSize: new go.Size(6, 6), fill: "lightblue", stroke: "deepskyblue" })
  );

 var nodeRotateAdornmentTemplate =
  objGo(go.Adornment,
  { locationSpot: go.Spot.Center, locationObjectName: "CIRCLE" },
  objGo(go.Shape, "Circle", { name: "CIRCLE", cursor: "pointer", desiredSize: new go.Size(7, 7), fill: "lightblue", stroke: "deepskyblue" }),
  objGo(go.Shape, { geometryString: "M3.5 7 L3.5 30", isGeometryPositioned: true, stroke: "deepskyblue", strokeWidth: 1.5, strokeDashArray: [4, 2] })
  );

 myDiagram.nodeTemplate =
  objGo(go.Node, "Spot",
  { locationSpot: go.Spot.Center },
  new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
  { selectable: true, selectionAdornmentTemplate: nodeSelectionAdornmentTemplate },
  { resizable: true, resizeObjectName: "PANEL", resizeAdornmentTemplate: nodeResizeAdornmentTemplate },
  { rotatable: true, rotateAdornmentTemplate: nodeRotateAdornmentTemplate },
  new go.Binding("angle").makeTwoWay(),
  // the main object is a Panel that surrounds a TextBlock with a Shape
  objGo(go.Panel, "Auto",
   { name: "PANEL" },
   new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
   objGo(go.Shape, "Rectangle", // default figure
   {
    portId: "", // the default port: if no spot on link data, use closest side
    fromLinkable: true, toLinkable: true, cursor: "pointer",
    fill: "white", // default color
    strokeWidth: 2
   },
   new go.Binding("figure"),
   new go.Binding("fill")),
   objGo(go.TextBlock,
   {
    font: "bold 11pt Helvetica, Arial, sans-serif",
    margin: 8,
    maxSize: new go.Size(160, NaN),
    wrap: go.TextBlock.WrapFit,
    editable: true
   },
   new go.Binding("text").makeTwoWay())
  ),
  // four small named ports, one on each side:
  makePort("T", go.Spot.Top, false, true),
  makePort("L", go.Spot.Left, true, true),
  makePort("R", go.Spot.Right, true, true),
  makePort("B", go.Spot.Bottom, true, false),
  { // handle mouse enter/leave events to show/hide the ports
   mouseEnter: function(e, node) { showSmallPorts(node, true); },
   mouseLeave: function(e, node) { showSmallPorts(node, false); }
  }
  );

 function showSmallPorts(node, show) {
  node.ports.each(function(port) {
  if (port.portId !== "") { // don&#39;t change the default port, which is the big shape
   port.fill = show ? "rgba(0,0,0,.3)" : null;
  }
  });
 }

 var linkSelectionAdornmentTemplate =
  objGo(go.Adornment, "Link",
  objGo(go.Shape,
   // isPanelMain declares that this Shape shares the Link.geometry
   { isPanelMain: true, fill: null, stroke: "deepskyblue", strokeWidth: 0 }) // use selection object&#39;s strokeWidth
  );

 myDiagram.linkTemplate =
  objGo(go.Link, // the whole link panel
  { selectable: true, selectionAdornmentTemplate: linkSelectionAdornmentTemplate },
  { relinkableFrom: true, relinkableTo: true, reshapable: true },
  {
   routing: go.Link.AvoidsNodes,
   curve: go.Link.JumpOver,
   corner: 5,
   toShortLength: 4
  },
  new go.Binding("points").makeTwoWay(),
  objGo(go.Shape, // the link path shape
   { isPanelMain: true, strokeWidth: 2 }),
  objGo(go.Shape, // the arrowhead
   { toArrow: "Standard", stroke: null }),
  objGo(go.Panel, "Auto",
   new go.Binding("visible", "isSelected").ofObject(),
   objGo(go.Shape, "RoundedRectangle", // the link shape
   { fill: "#F8F8F8", stroke: null }),
   objGo(go.TextBlock,
   {
    textAlign: "center",
    font: "10pt helvetica, arial, sans-serif",
    stroke: "#919191",
    margin: 2,
    minSize: new go.Size(10, NaN),
    editable: true
   },
   new go.Binding("text").makeTwoWay())
  )
  );

 load(); // load an initial diagram from some JSON text

 // initialize the Palette that is on the left side of the page
 myPalette =
  objGo(go.Palette, "myPalettep", // must name or refer to the p HTML element
  {
   maxSelectionCount: 1,
   nodeTemplateMap: myDiagram.nodeTemplateMap, // share the templates used by myDiagram
   linkTemplate: // simplify the link template, just in this Palette
   objGo(go.Link,
    { // because the GridLayout.alignment is Location and the nodes have locationSpot == Spot.Center,
    // to line up the Link in the same manner we have to pretend the Link has the same location spot
    locationSpot: go.Spot.Center,
    selectionAdornmentTemplate:
     objGo(go.Adornment, "Link",
     { locationSpot: go.Spot.Center },
     objGo(go.Shape,
      { isPanelMain: true, fill: null, stroke: "deepskyblue", strokeWidth: 0 }),
     objGo(go.Shape, // the arrowhead
      { toArrow: "Standard", stroke: null })
     )
    },
    {
    routing: go.Link.AvoidsNodes,
    curve: go.Link.JumpOver,
    corner: 5,
    toShortLength: 4
    },
    new go.Binding("points"),
    objGo(go.Shape, // the link path shape
    { isPanelMain: true, strokeWidth: 2 }),
    objGo(go.Shape, // the arrowhead
    { toArrow: "Standard", stroke: null })
   ),
   model: new go.GraphLinksModel([ // specify the contents of the Palette
   { text: "Start", figure: "Circle", fill: "#00AD5F" },
   { text: "Step" },
   { text: "DB", figure: "Database", fill: "lightgray" },
   { text: "???", figure: "Diamond", fill: "lightskyblue" },
   { text: "End", figure: "Circle", fill: "#CE0620" },
   { text: "Comment", figure: "RoundedRectangle", fill: "lightyellow" }
   ], [
   // the Palette also has a disconnected Link, which the user can drag-and-drop
   { points: new go.List(go.Point).addAll([new go.Point(0, 0), new go.Point(30, 0), new go.Point(30, 40), new go.Point(60, 40)]) }
   ])
  });
 }


 function TopRotatingTool() {
 go.RotatingTool.call(this);
 }
 go.Diagram.inherit(TopRotatingTool, go.RotatingTool);

 /** @override */
 TopRotatingTool.prototype.updateAdornments = function(part) {
 go.RotatingTool.prototype.updateAdornments.call(this, part);
 var adornment = part.findAdornment("Rotating");
 if (adornment !== null) {
  adornment.location = part.rotateObject.getDocumentPoint(new go.Spot(0.5, 0, 0, -30)); // above middle top
 }
 };

 /** @override */
 TopRotatingTool.prototype.rotate = function(newangle) {
 go.RotatingTool.prototype.rotate.call(this, newangle + 90);
 };
 // end of TopRotatingTool class


 // Show the diagram&#39;s model in JSON format that the user may edit
 function save() {
 saveDiagramProperties(); // do this first, before writing to JSON
 document.getElementById("mySavedModel").value = myDiagram.model.toJson();
 myDiagram.isModified = false;
 }
 function load() {
 myDiagram.model = go.Model.fromJson(document.getElementById("mySavedModel").value);
 loadDiagramProperties(); // do this after the Model.modelData has been brought into memory
 }

 function saveDiagramProperties() {
 myDiagram.model.modelData.position = go.Point.stringify(myDiagram.position);
 }
 function loadDiagramProperties(e) {
 // set Diagram.initialPosition, not Diagram.position, to handle initialization side-effects
 var pos = myDiagram.model.modelData.position;
 if (pos) myDiagram.initialPosition = go.Point.parse(pos);
 }
</script>
</head>
<body onload="init()">
<p id="sample">
 <p style="width:100%; white-space:nowrap;">
 <span style="display: inline-block; vertical-align: top; width:105px">
  <p id="myPalettep" style="border: solid 1px black; height: 620px"></p>
 </span>

 <span style="display: inline-block; vertical-align: top; width:80%">
  <p id="myDiagramp" style="border: solid 1px black; height: 620px"></p>
 </span>
 </p>
 <p>
 This sample demonstrates the ability for the user to drag around a Link as if it were a Node.
 When either end of the link passes over a valid port, the port is highlighted.
 </p>
 <p>
 The link-dragging functionality is enabled by setting some or all of the following properties:
 <a>DraggingTool.dragsLink</a>, <a>LinkingTool.isUnconnectedLinkValid</a>, and
 <a>RelinkingTool.isUnconnectedLinkValid</a>.
 </p>
 <p>
 Note that a Link is present in the <a>Palette</a> so that it too can be dragged out and onto
 the main Diagram. Because links are not automatically routed when either end is not connected
 with a Node, the route is provided explicitly when that Palette item is defined.
 </p>
 <p>
 This also demonstrates several custom Adornments:
 <a>Part.selectionAdornmentTemplate</a>, <a>Part.resizeAdornmentTemplate</a>, and
 <a>Part.rotateAdornmentTemplate</a>.
 </p>
 <p>
 Finally this sample demonstrates saving and restoring the <a>Diagram.position</a> as a property
 on the <a>Model.modelData</a> object that is automatically saved and restored when calling <a>Model.toJson</a>
 and <a>Model.fromJson</a>.
 </p>
 <p>
 <p>
  <button id="SaveButton" onclick="save()">Save</button>
  <button onclick="load()">Load</button>
  Diagram Model saved in JSON format:
 </p>
 <textarea id="mySavedModel" style="width:100%;height:300px">
{ "class": "go.GraphLinksModel",
 "linkFromPortIdProperty": "fromPort",
 "linkToPortIdProperty": "toPort",
 "nodeDataArray": [
 ],
 "linkDataArray": [
 ]}
 </textarea>
 </p>
</p>
</body>
</html>
로그인 후 복사

效果如下:

建议各位copy代码,在本地看到效果,然后再根据实际需求去研究它的api,这样才不会太盲目而花费太多时间。

2、工业流程图

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Process Flow</title>
<meta name="description" content="A simple process flow or SCADA diagram editor, simulating equipment monitoring and control." />
<!-- Copyright 1998-2017 by Northwoods Software Corporation. -->
<meta charset="UTF-8">
<script src="../../gojs/go-debug.js"></script>
<script id="code">
 function init() {
 if (window.goSamples) goSamples(); // init for these samples -- you don&#39;t need to call this
 var $ = go.GraphObject.make; // for more concise visual tree definitions

 myDiagram =
  $(go.Diagram, "myDiagramp",
  {
   "grid.visible": true,
   "grid.gridCellSize": new go.Size(30, 20),
   "draggingTool.isGridSnapEnabled": true,
   "resizingTool.isGridSnapEnabled": true,
   "rotatingTool.snapAngleMultiple": 90,
   "rotatingTool.snapAngleEpsilon": 45,
   "undoManager.isEnabled": true
  });

 // when the document is modified, add a "*" to the title and enable the "Save" button
 myDiagram.addDiagramListener("Modified", function(e) {
  var button = document.getElementById("SaveButton");
  if (button) button.disabled = !myDiagram.isModified;
  var idx = document.title.indexOf("*");
  if (myDiagram.isModified) {
  if (idx < 0) document.title += "*";
  } else {
  if (idx >= 0) document.title = document.title.substr(0, idx);
  }
 });

 myDiagram.nodeTemplateMap.add("Process",
  $(go.Node, "Auto",
  { locationSpot: new go.Spot(0.5, 0.5), locationObjectName: "SHAPE",
   resizable: true, resizeObjectName: "SHAPE" },
  new go.Binding("location", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
  $(go.Shape, "Cylinder1",
   { name: "SHAPE",
   strokeWidth: 2,
   fill: $(go.Brush, "Linear",
     { start: go.Spot.Left, end: go.Spot.Right,
      0: "gray", 0.5: "white", 1: "gray" }),
   minSize: new go.Size(50, 50),
   portId: "", fromSpot: go.Spot.AllSides, toSpot: go.Spot.AllSides
   },
   new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify)),
  $(go.TextBlock,
   { alignment: go.Spot.Center, textAlign: "center", margin: 5,
   editable: true },
   new go.Binding("text").makeTwoWay())
  ));

 myDiagram.nodeTemplateMap.add("Valve",
  $(go.Node, "Vertical",
  { locationSpot: new go.Spot(0.5, 1, 0, -21), locationObjectName: "SHAPE",
   selectionObjectName: "SHAPE", rotatable: true },
  new go.Binding("angle").makeTwoWay(),
  new go.Binding("location", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
  $(go.TextBlock,
   { alignment: go.Spot.Center, textAlign: "center", margin: 5, editable: true },
   new go.Binding("text").makeTwoWay(),
   // keep the text upright, even when the whole node has been rotated upside down
   new go.Binding("angle", "angle", function(a) { return a === 180 ? 180 : 0; }).ofObject()),
  $(go.Shape,
   { name: "SHAPE",
   geometryString: "F1 M0 0 L40 20 40 0 0 20z M20 10 L20 30 M12 30 L28 30",
   strokeWidth: 2,
   fill: $(go.Brush, "Linear", { 0: "gray", 0.35: "white", 0.7: "gray" }),
   portId: "", fromSpot: new go.Spot(1, 0.35), toSpot: new go.Spot(0, 0.35) })
  ));

 myDiagram.linkTemplate =
  $(go.Link,
  { routing: go.Link.AvoidsNodes, curve: go.Link.JumpGap, corner: 10, reshapable: true, toShortLength: 7 },
  new go.Binding("points").makeTwoWay(),
  // mark each Shape to get the link geometry with isPanelMain: true
  $(go.Shape, { isPanelMain: true, stroke: "black", strokeWidth: 5 }),
  $(go.Shape, { isPanelMain: true, stroke: "gray", strokeWidth: 3 }),
  $(go.Shape, { isPanelMain: true, stroke: "white", strokeWidth: 1, name: "PIPE", strokeDashArray: [10, 10] }),
  $(go.Shape, { toArrow: "Triangle", fill: "black", stroke: null })
  );

 load();

 loop(); // animate some flow through the pipes
 }

 function loop() {
 var diagram = myDiagram;
 setTimeout(function() {
  var oldskips = diagram.skipsUndoManager;
  diagram.skipsUndoManager = true;
  diagram.links.each(function(link) {
   var shape = link.findObject("PIPE");
   var off = shape.strokeDashOffset - 2;
   shape.strokeDashOffset = (off <= 0) ? 20 : off;
  });
  diagram.skipsUndoManager = oldskips;
  loop();
 }, 100);
 }

 function save() {
 document.getElementById("mySavedModel").value = myDiagram.model.toJson();
 myDiagram.isModified = false;
 }
 function load() {
 myDiagram.model = go.Model.fromJson(document.getElementById("mySavedModel").value);
 }
</script>

</head>
<body onload="init()">
<p id="sample">
 <p id="myDiagramp" style="border: solid 1px black; width:100%; height:500px"></p>
 <p>
 A <em>process flow diagram</em> is commonly used in chemical and process engineering to indicate the general flow of plant processes and equipment.
 A simple SCADA diagram, with animation of the flow along the pipes, is implemented here.
 </p>
 <p>
 The diagram displays the background grid layer by setting <b>grid.visible</b> to true,
 and also allows snapping to the grid using <a>DraggingTool.isGridSnapEnabled</a>,
 <a>ResizingTool.isGridSnapEnabled</a>, and <a>RotatingTool.snapAngleMultiple</a> alongside <a>RotatingTool.snapAngleEpsilon</a>.
 </p>
 <p>
 The diagram also uses the <b>loop</b> function to animate the links by adjusting the <a>Shape.strokeDashOffset</a> every 100 ms.
 </p>
 <p>
 <p>
  <button id="SaveButton" onclick="save()">Save</button>
  <button onclick="load()">Load</button>
  Diagram Model saved in JSON format:
 </p>
 <textarea id="mySavedModel" style="width:100%;height:300px">
{ "class": "go.GraphLinksModel",
 "nodeDataArray": [
{"key":"P1", "category":"Process", "pos":"150 120", "text":"Process"},
{"key":"P2", "category":"Process", "pos":"330 320", "text":"Tank"},
{"key":"V1", "category":"Valve", "pos":"270 120", "text":"V1"},
{"key":"P3", "category":"Process", "pos":"150 420", "text":"Pump"},
{"key":"V2", "category":"Valve", "pos":"150 280", "text":"VM", "angle":270},
{"key":"V3", "category":"Valve", "pos":"270 420", "text":"V2", "angle":180},
{"key":"P4", "category":"Process", "pos":"450 140", "text":"Reserve Tank"},
{"key":"V4", "category":"Valve", "pos":"390 60", "text":"VA"},
{"key":"V5", "category":"Valve", "pos":"450 260", "text":"VB", "angle":90}
 ],
 "linkDataArray": [
{"from":"P1", "to":"V1"},
{"from":"P3", "to":"V2"},
{"from":"V2", "to":"P1"},
{"from":"P2", "to":"V3"},
{"from":"V3", "to":"P3"},
{"from":"V1", "to":"V4"},
{"from":"V4", "to":"P4"},
{"from":"V1", "to":"P2"},
{"from":"P4", "to":"V5"},
{"from":"V5", "to":"P2"}
 ]}
 </textarea>
 </p>
</p>
</body>
</html>
로그인 후 복사

工业流程图

四、总结

本文根据js的一些基础用法做了简单介绍,今天就先到这里,以后有问题了再来跟大家分享。如果你的项目里面也有这种业务需求,可以用起来试试!需要说明一点,如果您的公司不缺钱,建议使用正版授权的组件,毕竟尊重作者的劳动成果很重要!

相关推荐:

Javascript-EXTJS 컴포넌트 개발 완료 코드

JS 컴포넌트 부트스트랩 테이블 페이징 구현 중 발생한 문제 해결

JS 컴포넌트 기반 드래그 슬라이더 검증 기능 구현

위 내용은 JS 프런트 엔드 그래픽 플러그인 도구 Gojs 구성 요소의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

WebSocket과 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법 WebSocket과 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법 Dec 17, 2023 pm 02:54 PM

WebSocket 및 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법 소개: 지속적인 기술 개발로 음성 인식 기술은 인공 지능 분야의 중요한 부분이 되었습니다. WebSocket과 JavaScript를 기반으로 한 온라인 음성 인식 시스템은 낮은 대기 시간, 실시간, 크로스 플랫폼이라는 특징을 갖고 있으며 널리 사용되는 솔루션이 되었습니다. 이 기사에서는 WebSocket과 JavaScript를 사용하여 온라인 음성 인식 시스템을 구현하는 방법을 소개합니다.

WebSocket 및 JavaScript: 실시간 모니터링 시스템 구현을 위한 핵심 기술 WebSocket 및 JavaScript: 실시간 모니터링 시스템 구현을 위한 핵심 기술 Dec 17, 2023 pm 05:30 PM

WebSocket과 JavaScript: 실시간 모니터링 시스템 구현을 위한 핵심 기술 서론: 인터넷 기술의 급속한 발전과 함께 실시간 모니터링 시스템이 다양한 분야에서 널리 활용되고 있다. 실시간 모니터링을 구현하는 핵심 기술 중 하나는 WebSocket과 JavaScript의 조합입니다. 이 기사에서는 실시간 모니터링 시스템에서 WebSocket 및 JavaScript의 적용을 소개하고 코드 예제를 제공하며 구현 원칙을 자세히 설명합니다. 1. 웹소켓 기술

JavaScript 및 WebSocket을 사용하여 실시간 온라인 주문 시스템을 구현하는 방법 JavaScript 및 WebSocket을 사용하여 실시간 온라인 주문 시스템을 구현하는 방법 Dec 17, 2023 pm 12:09 PM

JavaScript 및 WebSocket을 사용하여 실시간 온라인 주문 시스템을 구현하는 방법 소개: 인터넷의 대중화와 기술의 발전으로 점점 더 많은 레스토랑에서 온라인 주문 서비스를 제공하기 시작했습니다. 실시간 온라인 주문 시스템을 구현하기 위해 JavaScript 및 WebSocket 기술을 사용할 수 있습니다. WebSocket은 TCP 프로토콜을 기반으로 하는 전이중 통신 프로토콜로 클라이언트와 서버 간의 실시간 양방향 통신을 실현할 수 있습니다. 실시간 온라인 주문 시스템에서는 사용자가 요리를 선택하고 주문을 하면

WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법 WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법 Dec 17, 2023 am 09:39 AM

WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법 오늘날의 디지털 시대에는 점점 더 많은 기업과 서비스에서 온라인 예약 기능을 제공해야 합니다. 효율적인 실시간 온라인 예약 시스템을 구현하는 것이 중요합니다. 이 기사에서는 WebSocket과 JavaScript를 사용하여 온라인 예약 시스템을 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 1. WebSocket이란 무엇입니까? WebSocket은 단일 TCP 연결의 전이중 방식입니다.

JavaScript와 WebSocket: 효율적인 실시간 일기예보 시스템 구축 JavaScript와 WebSocket: 효율적인 실시간 일기예보 시스템 구축 Dec 17, 2023 pm 05:13 PM

JavaScript 및 WebSocket: 효율적인 실시간 일기 예보 시스템 구축 소개: 오늘날 일기 예보의 정확성은 일상 생활과 의사 결정에 매우 중요합니다. 기술이 발전함에 따라 우리는 날씨 데이터를 실시간으로 획득함으로써 보다 정확하고 신뢰할 수 있는 일기예보를 제공할 수 있습니다. 이 기사에서는 JavaScript 및 WebSocket 기술을 사용하여 효율적인 실시간 일기 예보 시스템을 구축하는 방법을 알아봅니다. 이 문서에서는 특정 코드 예제를 통해 구현 프로세스를 보여줍니다. 우리

자바스크립트에서 insertBefore를 사용하는 방법 자바스크립트에서 insertBefore를 사용하는 방법 Nov 24, 2023 am 11:56 AM

사용법: JavaScript에서 insertBefore() 메서드는 DOM 트리에 새 노드를 삽입하는 데 사용됩니다. 이 방법에는 삽입할 새 노드와 참조 노드(즉, 새 노드가 삽입될 노드)라는 두 가지 매개 변수가 필요합니다.

간단한 JavaScript 튜토리얼: HTTP 상태 코드를 얻는 방법 간단한 JavaScript 튜토리얼: HTTP 상태 코드를 얻는 방법 Jan 05, 2024 pm 06:08 PM

JavaScript 튜토리얼: HTTP 상태 코드를 얻는 방법, 특정 코드 예제가 필요합니다. 서문: 웹 개발에서는 서버와의 데이터 상호 작용이 종종 포함됩니다. 서버와 통신할 때 반환된 HTTP 상태 코드를 가져와서 작업의 성공 여부를 확인하고 다양한 상태 코드에 따라 해당 처리를 수행해야 하는 경우가 많습니다. 이 기사에서는 JavaScript를 사용하여 HTTP 상태 코드를 얻는 방법과 몇 가지 실용적인 코드 예제를 제공합니다. XMLHttpRequest 사용

JavaScript에서 HTTP 상태 코드를 쉽게 얻는 방법 JavaScript에서 HTTP 상태 코드를 쉽게 얻는 방법 Jan 05, 2024 pm 01:37 PM

JavaScript에서 HTTP 상태 코드를 얻는 방법 소개: 프런트 엔드 개발에서 우리는 종종 백엔드 인터페이스와의 상호 작용을 처리해야 하며 HTTP 상태 코드는 매우 중요한 부분입니다. HTTP 상태 코드를 이해하고 얻는 것은 인터페이스에서 반환된 데이터를 더 잘 처리하는 데 도움이 됩니다. 이 기사에서는 JavaScript를 사용하여 HTTP 상태 코드를 얻는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 1. HTTP 상태 코드란 무엇입니까? HTTP 상태 코드는 브라우저가 서버에 요청을 시작할 때 서비스가

See all articles