日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

html控制图的宽,用JointJS做一个简单的功能控制图

發布時間:2024/7/19 javascript 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 html控制图的宽,用JointJS做一个简单的功能控制图 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

繼上一篇介紹了GoJS之后,繼續研究JS的繪圖工具,畢竟GoJS有些小貴。這次選擇了JointJS,完全開源,它還有一個商業版本叫Raddit,功能更強大。不過就我的需求場景,開源的Joint就足夠了。接下來,我們看看它是怎么使用的。

JointJS是基于Backbone開發的,所以使用Joint之前,要先引入Backbone的相關依賴,所以我們的HTML文件是這樣的:

JointJS Sample

這里我都用CDN,也可以將相應的庫載到本地,但需要注意的是JS的加載順序不能改。接下來,我們寫一個官方的HelloWorld:

window.οnlοad=function() {

var graph = new joint.dia.Graph; // 創建畫板,所有圖上的元素都在畫板里

var paper = new joint.dia.Paper({ // 創建畫板上的畫布,畫布是用來渲染畫板

el: document.getElementById('myGraph'), // 指向HTML里ID為"myGraph"的元素

model: graph, // 指定畫板

width: 600, // 畫布寬600像素

height: 100, // 畫布高100像素

gridSize: 1, // 畫布上元素拖動時步進的像素,默認1,設的高方便對齊

background: { // 畫布背景色

color: 'rgba(0, 0, 0, 0.1)'

},

});

// 創建一個矩形

var rect = new joint.shapes.standard.Rectangle();

rect.position(100, 30); // 矩形左上角的位置,x:100,y:30,單位像素

rect.resize(100, 40); // 矩形大小,寬100,高40,單位像素

rect.attr({

body: {

fill: 'blue' // 填充色

},

label: {

text: 'Hello', // 矩形上顯示的文字

fill: 'white' // 文字顏色

}

});

rect.addTo(graph); // 將上面定義的矩形加入到畫板中

var rect2 = rect.clone(); // 復制一個相同的矩形

rect2.translate(300, 0); // 將矩形在水平方向上向右移動300像素

rect2.attr('label/text', 'World!'); // 設置矩形2上的文字

rect2.addTo(graph); // 將矩形2加入到畫板中

// 創建一條連線

var link = new joint.shapes.standard.Link();

link.source(rect); // 連線頭為矩形1

link.target(rect2); // 連線尾為矩形2

link.addTo(graph); // 將上面定義的連線加入到畫板中

}

從上例里,我們可以看出,使用JointJS開發主要的步驟就是創建畫板、創建畫布、創建圖形,然后將圖形置于畫板中。上面的例子執行后會得到下面的圖像。

HelloWorld!

JointJS中的圖形主要有兩類,一是”元素”(Element),由構造函數創建。上例中的矩形就是JointJS庫提供的標準元素,其構造函數為joint.shapes.standard.Rectangle。元素創建后,可以設置各種參數,比如位置,大小,風格等。JointJS提供了豐富的內置元素如矩形,圓形,橢圓等,可以參考API文檔。同時,我們可以通過擴展joint.dia.Element類來自定義元素。

另一類圖形是”連接”(Link),用來將兩個”元素”連起來,一般顯示為一條連線。上例中的連線是通過JointJS庫提供的標準構造函數joint.shapes.standard.Link來創建的,創建后設置其”頭”(Source)和”尾”(Target),即可將兩個”元素”連起來。我們也可以設置”連接”的各種參數,如顏色,箭頭,標簽文字等。

HelloWorld之后我們來做一個簡單的自動化功能控制圖吧,HTML部分不變,我們來寫JS部分。

第一步定義畫板和畫布

var graph = new joint.dia.Graph; // 創建畫板,所有圖上的元素都在畫板里

var paper = new joint.dia.Paper({ // 創建畫板上的畫布,畫布是用來渲染畫板

el: $('#myGraph'), // 指向HTML里ID為"myGraph"的元素

model: graph, // 指定畫板

width: 600, // 畫布寬600像素

height: 300, // 畫布高300像素

gridSize: 5, // 畫布上元素拖動時步進的為5像素,默認1

drawGrid: true, // 顯示步進點,方便對齊

background: { // 畫布背景色

color: 'rgba(0, 0, 0, 0.1)'

},

// 連接線風格

defaultLink: new joint.shapes.logic.Wire({

connector: { name: 'jumpover' }, // 當兩根連線交叉時,其中一根跳過

}),

linkPinning: false, // 連線必須連到某個元素,即不允許連到空白處

snapLinks: {

radius: 25 // 距離元素連接點25像素時自動連接上

},

// 驗證連線是否允許,

validateConnection: function(viewSource, magnetSource, viewTarget, magnetTarget, end, viewLink) {

if (end === 'target') {

// 連線目標必須時一個"in"類型連接點

if (!magnetTarget || !magnetTarget.getAttribute('port-group') || magnetTarget.getAttribute('port-group').indexOf('in') < 0) {

return false;

}

// 檢查連接點是否已經有連線接入,不允許多重接入

var portUsed = this.model.getLinks().some(function(link) {

return (link.id !== viewLink.model.id &&

link.get('target').id === viewTarget.model.id &&

link.get('target').port === magnetTarget.getAttribute('port'));

});

return !portUsed;

} else { // end === 'source'

// 連線起始點必須時一個"out"類型連接點

return magnetSource && magnetSource.getAttribute('port-group') && magnetSource.getAttribute('port-group').indexOf('out') >= 0;

}

},

});

上面的屬性有些多,但大部分都好理解,主要是驗證函數validateConnection(),其返回true或false,用來決定連線是否被允許。傳入的參數viewSource和viewTarget分別是畫線過程中鼠標按鈕釋放時,當前連線頭和尾的元素;而參數magnetSource和magnetTarget分別是當前連線頭和尾的”連接點”(port)?!边B接點”的概念下面會講到。

第二步定義基本圖例元素

這里,我們創建了與、或、非,三個基本元素,因為是圖例元素,所以不允許連入連出。我們使用標準庫提供的”joint.shapes.devs.Model”元素,因為它很方便設置”連接點”(port)。

// 創建基礎元件模板

var gateTemplate = new joint.shapes.devs.Model({

position: { // 默認位置

x: 0,

y: 0

},

size: { // 默認大小

width: 50,

height: 60

},

// "連接點"(port)的風格

portMarkup: '',

// "連接點"(port)標簽文字的顯示風格

portLabelMarkup: ' ',

ports: { // 定義連接點

groups: {

'in': { // "入"連接點的屬性和風格

attrs: {

'.port-body': { // 這是JointJS類庫預定義的連接點屬性類

magnet: 'passive', // 該連接點只入不出

},

'.joint-port-body': { // 這是JointJS類庫預定義的連接點風格類

x:-10 // "入"連接點左移10個像素,這樣可以顯示在元素外部

}

},

label: {

position: {

args: {x:18}, // 標簽右移,這樣可以顯示在元素內部

},

},

},

'out': {

label: { // "出"連接點的屬性和風格

position: {

args: {x:-23}, // 標簽左移,這樣可以顯示在元素內部

},

},

}

}

},

attrs: {

'.label': {

'type': 'primary', // 自定義一個圖例屬性,后面事件操作時判斷用

fontSize: 12, // 標簽字體

'ref-x': .5, // 標簽相對于元素的水平位置

'ref-y': .05 // 標簽相對于元素的垂直位置

},

}

});

// 生成"與"元素,兩個"入"連接點,一個"出"連接點,顯示"And"字樣標簽

function genAndPr() {

return gateTemplate.clone().set('inPorts', ['IN1', 'IN2']).set('outPorts', ['OUT']).attr('.label/text', 'And');

}

// 生成"或"元素,兩個"入"連接點,一個"出"連接點,顯示"Or"字樣標簽

function genOrPr() {

return gateTemplate.clone().set('inPorts', ['IN1', 'IN2']).set('outPorts', ['OUT']).attr('.label/text', 'Or');

}

// 生成"非"元素,一個"入"連接點,一個"出"連接點,顯示"Not"字樣標簽

function genNotPr() {

return gateTemplate.clone().set('inPorts', ['IN ']).set('outPorts', ['OUT']).attr('.label/text', 'Not');;

}

// 圖例加入到畫板左側

graph.addCell(genAndPr().translate(20, 20));

graph.addCell(genOrPr().translate(20, 120));

graph.addCell(genNotPr().translate(20, 220));

// 添加一個分割欄將圖例和繪圖區域分開

var separator = new joint.shapes.standard.Polyline();

separator.resize(5, 400);

separator.position(95, 0);

separator.addTo(graph);

上面代碼寫得挺粗燥的,高手見笑。其實可以更好的抽象,只是懶得弄了。上面關鍵的概念就是”連接點”(port),JointJS庫中joint.shapes.devs.Model元素默認支持”入”(in)和”出”(out)兩種連接點,分別顯示在元素圖形的左邊和右邊,多個連接點會自動排列。通過前一段代碼中paper的linkPinning屬性設置,可以要求”連線”只允許接在”連接點”上。上面我們定義了”連接點”風格為一個長10px寬3px的水平線。上例中,因為我重寫了”連接點”的標記portMarkup,去掉了允許連線的屬性,所以這些連接點目前都無法被連線。

第三步定義繪圖元素

function genAnd() {

return genAndPr().set('portMarkup', '').attr('.label/type', 'instance');

}

function genOr() {

return genOrPr().set('portMarkup', '').attr('.label/type', 'instance');

}

function genNot() {

return genNotPr().set('portMarkup', '').attr('.label/type', 'instance');

}

上面的代碼還是很好理解的,我將圖例元素中的portMarkup改了,其實就是增加了css類port-body,這是JointJS庫中預定義的。該類中設置了”元素”的magnet屬性,設為true時可入可出;passive時只入不出;false時不能連線。這樣,我們的繪圖元素就可以接上連線了。另外,這里將自定義屬性.label/type改為instance主要是后面的事件判斷用。

最后,我們定義鼠標事件,來支持將圖例元素拖入繪圖區域

paper.on({ // JointJS事件都定義在畫布上

// 當鼠標左鍵按下時

'element:pointerdown': function(elementView, evt) {

// 當圖例元素被拖走時,在原來的位置創建一個新的圖例元素

if (elementView.model.attr('.label/type') == 'primary') {

var type = elementView.model.attr('.label/text');

if (type == 'And') {

graph.addCell(genAndPr().translate(20, 20));

} else if (type == 'Or') {

graph.addCell(genOrPr().translate(20, 120));

} else if (type == 'Not') {

graph.addCell(genNotPr().translate(20, 220));

}

// 被拖動的元素挪到圖層的最上層,這樣可以遮蓋現有元素

elementView.model.toFront();

} else if (elementView.model.attr('.label/type') == 'instance') {

// 對于繪圖元素,記住其被拖動時的起始點,當拖動位置超出繪圖區域時,可以回到原點

evt.data = elementView.model.position();

}

},

// 當鼠標左鍵抬起時

'element:pointerup': function(elementView, evt, x, y) {

if (elementView.model.attr('.label/type') == 'primary') {

// 對于圖例元素,當其被拖入繪圖區域時,則在該位置創建一個新的繪圖元素,并刪除被拖動的圖例元素

if (elementView.model.position().x > 105) {

var type = elementView.model.attr('.label/text');

if (type == 'And') {

graph.addCell(genAnd().translate(elementView.model.position().x, elementView.model.position().y));

} else if (type == 'Or') {

graph.addCell(genOr().translate(elementView.model.position().x, elementView.model.position().y));

} else if (type == 'Not') {

graph.addCell(genNot().translate(elementView.model.position().x, elementView.model.position().y));

}

}

// 刪除當前被拖動的元素

graph.removeCells(elementView.model);

} else {

// 對于繪圖元素,當其被拖出繪圖區域時,則將其移回原點

if (elementView.model.position().x < 110) {

elementView.model.position(evt.data.x, evt.data.y);

}

}

},

// 當鼠標左鍵雙擊時

'element:pointerdblclick': function(elementView, evt) {

// 雙擊繪圖元素則刪除該元素,相應的連線也會被自動刪除

if (elementView.model.attr('.label/type') == 'instance') {

elementView.model.remove();

}

},

})

JointJS的事件都定義在畫布paper上,可以參考這里的說明。事件的種類很多,可以在”元素”、”連線”或”空白處”上監聽,可以是各種鼠標事件,這里不贅述了。大部分事件都接受4個參數:

“cellView”(或叫”elementView”) – 事件監聽的主體,可以通過elementView.model來獲得元素對象,并對其做各種設置

“evt” – 保存信息用于在事件間傳數據

“x”和”y” – 記錄事件發生時鼠標的位置

上例中的事件函數,定義了將圖例元素拖入繪圖區域,并創建一個新的繪圖元素的過程。

保存上面的代碼并在瀏覽器里打開,大家應該可以看到如下內容。

JointJS源碼托管在Github中。更詳細的開發API文檔可以在官方API文檔中找到。 本文中的示例代碼,可以在這里下載

總結

以上是生活随笔為你收集整理的html控制图的宽,用JointJS做一个简单的功能控制图的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。