關鍵字:設計器源代碼,Web設計器,工做流設計器,jQuery插件,組態設計器,SCADA系統設計器,流程圖設計,表單設計建模,報表設計,可視化,設計時,運行時,輕量級開放平臺。html
上節講到如何經過OOP思路設計設計器視圖和元素,本節將重點講述設計視圖上的元素管理(建立組件,清除組件,打開文件,持久化設計),衆所周知,設計器視圖上的元素主要由組件和連線組成(連線也是組件),只是在建立時因爲要先實例化組件,再在組件間連線,因此從管理上來講將它分開定義,這樣咱們在visualDesigner類中定義兩個成員:nodes和lines,以下:前端
var VisualDesigner = function (element, options) { this.init(element, options) this.nodes = {};//設計器上全部節點集合 this.lines = {};//設計器上全部線條 }
也許眼尖的讀者已經看出來了,爲啥不該該是數組集合的類型:this.nodes=[];呢?主要是爲了後續經過組件id屬性查找時方便,不用遍歷全部節點,代碼片段以下:node
/*增長元素*/ VisualDesigner.prototype.addElement = function (e) { this.nodes[e.properties.id] = e; } VisualDesigner.prototype.createId = function() { var idx = 1; var name = ""; while (true) { name = "e" + idx; var element = this.nodes[name]; //同名組件是否存在? if (element) idx++; else break; } return name; }
1.建立組件數據庫
頁面上組件在兩個地方會被建立,第一個是拖動工具面板中的組件到設計視圖上(已經講過:鼠標DRAG/DROP事件),第二個是打開保存的組件文件時,還原建立。筆者是有一些清潔代碼強迫症的,只要是相同的代碼,必須抽象,所以建立元素的代碼能夠抽象出來:數組
VisualDesigner.prototype.createElement = function (typeName, options) { options.id = this.createId(); //爲元素增長id屬性 switch (typeName) { case "圓": var circle = new Circle().init().render(options); this.addElement(circle); break; case "矩形": var rect = new Retangle().init().render(options); this.addElement(rect); break; case "橢圓": var path = new Ellipse().init().render(options); this.addElement(path); break; } }
而調用代碼則簡化爲(傳遞要建立的元素類型和位置信息x/y):工具
this.$element.on("drop", function (event) { event.preventDefault(); var data = null; if (event.dataTransfer == undefined && event.originalEvent != undefined) data = event.originalEvent.dataTransfer.getData("text"); else if (event.dataTransfer != undefined) data = event.dataTransfer.getData("text"); var drag = false; me.createElement(data, { x: event.originalEvent.offsetX, y: event.originalEvent.offsetY }); });
一樣的對於不一樣的組件在render時也增長了一些默認屬性(以前示例是在建立時指定,這是不合理的,所以移到子類組件中),好比typeName、大小、背景色等,以下示例:post
Retangle.prototype = $.extend(Retangle.prototype, { render: function (options) { this.properties.typeName = "矩形"; this.properties.width = 200; this.properties.height = 100; this.properties.opacity = 0.5; this.properties = $.extend(this.properties, options); var rect = new paper.Path.Rectangle({ point: [this.properties.x, this.properties.y], size: [this.properties.width, this.properties.height], radius: 5, strokeWidth: 1, strokeColor: this.properties.borderColor, fillColor: this.properties.backgroundColor, opacity: this.properties.opacity }); this.group.addChild(rect); return this; } });
2.清除組件:this
在打開一個現有設計視圖時,必須將設計視圖上的全部元素刪除,這是如何作到的呢?url
由於咱們在設計視圖中有一個nodes和lines對象保存了當前的全部元素,因此能夠經過循環刪除每個圖形化元素,實際就是經過最終的this.group.remove()方法。所以在Component基類中增長destroy方法:spa
Component.prototype.destroy = function () { this.group.remove(); }
清除結點遍歷的代碼以下:
VisualDesigner.prototype.clear = function () { var me = this; $.each(this.nodes, function (idx, item) { item.destroy(); delete me.nodes[item.properties.id] }) }
3.保存:
保存時,設計器的主要工做就是將當前設計視圖上的全部元素和連線序列化成字符串,並返回,由用戶決定這個返回的內容是存入數據庫仍是本地文件(本示例存到localStorage):
VisualDesigner.prototype.getContent = function () { return JSON.stringify({ "nodes": this.nodes, "lines": this.lines }); }
因此代碼很是精簡。
咱們再看看前端index.htm中保存代碼的邏輯(增長一個btnSave的button元素)
$("#btnSave").on("click", function () { debugger; var content = view.getContent(); localStorage.setItem("visualdesigner", content); })
4.打開現有的設計視圖文件:
接上面,設計視圖已經保存到localStorage的visualdesigner中,所以按打開(btnOpen)按鈕時,先獲取已存的內容,再調用設計器的open方法:
$("#btnOpen").on("click", function () { var content = localStorage.getItem("visualdesigner"); if (content) view.open(content); })
VisualDesigner.prototype.open = function (content) { //此處打開操做:清除原來內容,並渲染新內容的代碼 this.clear();//先清除原來內容 var contentObj = JSON.parse(content); for (var en in contentObj.nodes) { var el = contentObj.nodes[en]; this.createElement(el.properties.typeName, el.properties) } }
完整的示例效果以下:
源代碼:sample.1.4.rar
(本文爲原創,在引用代碼和文字時請註明出處)