各位網友大家好,今天給大家推薦一個前端畫圖的javascript庫,可用于構建數據流圖、任務流圖、知識圖譜展示等,他就是——MetricFlow.js。
MetricFlow是一個前端畫圖的javascript庫,可用于構建可拖拽、可靈活定義的數據流圖、任務流圖、知識圖譜展示等
創建畫布只需要定義div標簽即可,并聲明畫布的width和height
<div id="graph" height="700px" width="1100px" ></div>
/*在畫布上創建圖*/
let metricFlow=MetricFlow("graph")
/*定義節點數據*/
let nodeData={
"id":"primaryKey",//id在全局中不能重復,否則會被覆蓋
"title":{'name':"運行時間統計"},
"data":[
{'name':'方法:IndexController#method1'},
{'name':'平均耗時:0.333ms'},
]
};
/*在(20,200)坐標上創建一個節點*/
let node1=metricFlow.createNode(nodeData,10,200);
/*或者直接在nodeData中定義位置x和y屬性,然后*/
/*metricFlow.createNode(nodeData);*/
let metricFlow=MetricFlow("graph")
let node1Data={
"x":10,
"y":200,
"id":"node1",
"title":{'name':"運行時間統計"},
"data":[
{'name':'方法:IndexController#method1'},
{'name':'平均耗時:0.333ms'},
]
};
let node1=metricFlow.createNode(node1Data);
let node2Data={
"x":300,
"y":200,
"id":"node2",
"title":{'name':"運行時間統計"},
"data":[
{'name':'方法:IndexController#method1'},
{'name':'平均耗時:0.333ms'},
]
};
let node2=metricFlow.createNode(node2Data);
/*連接兩個節點*/
metricFlow.createLink(node1,node2);
或者直接在末尾節點中指定from屬性,無需metricFlow.createLink(node1,node2);
let metricFlow=MetricFlow("graph")
let node1Data={
"x":10,
"y":200,
"id":"node1",
"title":{'name':"運行時間統計"},
"data":[]
};
let node1=metricFlow.createNode(node1Data);
let node2Data={
"x":300,
"y":200,
"id":"node2",
"from":"node1",//from的值可以是string 也可以是數組
"title":{'name':"運行時間統計"},
"data":[]
};
let node2=metricFlow.createNode(node2Data);
批量創建節點有兩種方式,第一種使用list創建,并在每個節點數據中指定from屬性即可創建關系:
let metricFlow=MetricFlow("graph")
/*定義節點數據*/
let node1Data={
"x":20,
"y":200,
"id":"node1",
"title":{'name':"節點1"}
};
let node2Data={
"x":300,
"y":50,
"id":"node2",
"from":"node1",
"title":{'name':"節點2"}
};
let node3Data={
"x":300,
"y":300,
"id":"node3",
"from":"node1",
"title":{'name':"節點3"}
};
let nodes=[node1Data,node2Data,node3Data];
metricFlow.createNodes(nodes);
第二種使用children屬性創建,根節點的x和y需指定,其余子節點會自動向右排列
let nodes={
"x":20,
"y":200,
...
"children":[
{
"id":"node3",
...
"children":[
{...}
]
},
]
};
metricFlow.createNodes(nodes);
自動創建的時候如果節點間距不合適,可調整
let options={
'node-distance-offsetx':5,//左右間距+5
'node-distance-offsety':-5//上下間距-5
};
let metricFlow=MetricFlow("graph",options)
自動創建的時候如果數據格式不匹配,又不想遍歷處理,可傳入函數調整
function format(data){
data['value']=data['value']+"ms";
return data;
}
metricFlow.createNodes(nodes,format);
節點由三部分組成,分別是 標題、元素集和剩余的背景,每一個部分都支持兩種樣式定義方式:
第一種是沿用了css的樣式,在數據上添加style即可,如,更改整個節點的邊框顏色和粗細:
let node2Data={
"id":"node2",
"style":"border-color:red;border-width:2px;",
"title":{'name':"運行時間統計"},
"data":[
{'name':'方法:IndexController#method1'},
{'name':'平均耗時:0.333ms'},
]
};
第二種是提取了background-color和border-color兩個樣式,可以單獨配置
let node2Data={
"id":"node2",
"background-color":"red",
"border-color":"red",
"title":{'name':"運行時間統計"},
"data":[
{'name':'方法:IndexController#method1'},
{'name':'平均耗時:0.333ms'},
]
};
樣式定義demo-demo4.html
let node2Data={
"id":"node2",
"title":{'name':"運行時間統計","style":"background-color:red;border-color:red;font-size:15px;"},
"data":[
{'name':'方法:IndexController#method1'},
{'name':'平均耗時:0.333ms'},
]
};
let node2Data={
"id":"node2",
"title":{'name':"運行時間統計"},
"data":[
{'name':'方法:IndexController#method1',"style":"font-size:10px;"},
{'name':'平均耗時:0.333ms',"style":"font-size:10px;"},
]
};
連線位置目前僅支持偏移量定義,可在創建MetricFlow時定義
連線分為起始點和終點,可設置全局的起始點的偏移位置,主要考慮前端框架使用較為復雜時css沖突所導致位置偏移的校正
let options={
'link-start-offsetx':1,//起始點向右偏移一個單位
'link-start-offsety':-1,//起始點向上偏移一個單位
'link-end-offsetx':-1,
'link-end-offsety':-1,
'link-width-offset':-1,//線段粗細減小1個單位
'link-color':"blue", //更改線段顏色
};
let metricFlow=MetricFlow("graph",options)
連線位置demo-demo5.html
支持基本的鼠標事件,如click、dblclick、mousedown、mouseup等,與原生js一致,事件在對應節點身上配置即可:
let node1Data={
"id":"primaryKey",
"title":{'name':"雙擊"},
'click':"sinclick", //單擊 sinclick為函數名
'dblclick':"doubleClick",//雙擊
"data":[
{'name':'方法:IndexController#method1'},
{'name':'平均耗時:0.333ms'},
]
};
V1.0:創建節點;連線;樣式定義;鼠標事件
1.本項目版權屬作者所有,并使用 Apache-2.0進行開源;
2.您可以使用本項目進行學習、商用或者開源,但任何使用了本項目的代碼的軟件和項目請尊重作者的原創權利;
3.如果您使用并修改了本項目的源代碼,請注明修改內容以及出處;
4.其他內容請參考Apache-2.0
Python數據分析與可視化領域,Matplotlib作為一款功能強大的圖形庫,不僅能夠創建靜態圖表,更支持創建生動的動畫效果,使數據的演變過程得以直觀展現。本文將深入探討Matplotlib的動畫功能,通過實例代碼解析,幫助您掌握如何利用Matplotlib繪制出令人眼前一亮的動態圖表,為您的數據分析工作注入活力。
Matplotlib動畫基于matplotlib.animation模塊,通過迭代更新圖表元素(如線條、文本、圖像等),實現數據隨時間變化的動態可視化。主要涉及以下核心類和方法:
以下是一個使用FuncAnimation繪制動態正弦波的例子:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax=plt.subplots()
x_data, y_data=[], []
line,=ax.plot([], [], lw=2)
def update(frame):
t=frame / 10.0
x=np.linspace(0, 2 * np.pi, 1000)
y=np.sin(x + t)
x_data.append(x)
y_data.append(y)
line.set_data(x_data[-1], y_data[-1])
return line,
ani=FuncAnimation(fig, update, frames=np.arange(100), interval=20, blit=True)
plt.show()
在這個例子中:
def update(frame):
...
ax.set_title(f"Time: {frame / 10.0:.1f} s")
ax.set_xlabel("X-axis label")
ax.set_ylabel("Y-axis label")
...
ani.save('sine_wave_animation.mp4', writer='ffmpeg')
import random
fig, ax=plt.subplots()
scat=ax.scatter([], [])
def update(frame):
N=?
data=[(random.uniform(-1, 1), random.uniform(-1, 1)) for _ in range(N)]
scat.set_offsets(data)
return scat,
ani=FuncAnimation(fig, update, frames=np.arange(100), interval=20, blit=True)
plt.show()
import time
data=[random.randint(0, 100) for _ in range(5)]
fig, ax=plt.subplots()
bars=ax.bar(range(5), data)
def update(frame):
for bar, value in zip(bars, (random.randint(0, 100) for _ in range(5))):
bar.set_height(value)
return bars,
ani=FuncAnimation(fig, update, frames=np.arange(100), interval=20, blit=True)
plt.show()
實時監控系統:
# 假設已連接到實時數據源
data_stream=get_realtime_data()
fig, ax=plt.subplots()
line,=ax.plot([], [], lw=2)
def update(frame):
new_data=next(data_stream)
line.set_data(new_data['time'], new_data['value'])
return line,
ani=FuncAnimation(fig, update, frames=np.arange(100), interval=20, blit=True)
start_web_server(ani)
交互式Web應用:
# 假設已搭建Flask環境
from flask import Flask, render_template, jsonify
app=Flask(__name__)
@app.route('/data')
def stream_data():
return jsonify(next(get_realtime_data()))
@app.route('/')
def index():
return render_template('index.html')
if __name__=='__main__':
app.run(debug=True)
在templates/index.html中使用JavaScript庫(如D3.js)對接API,動態更新圖表。
Matplotlib的動畫功能極大地豐富了數據可視化的表現形式,使復雜的數據演變過程得以生動呈現。通過掌握FuncAnimation的使用方法,您可以輕松創建各類動態圖表,如動態散點圖、條形圖等,以適應不同的數據分析需求。在Python Web項目中,結合實時數據源與Web框架(如Flask),您可以構建實時監控系統、交互式Web應用等,將動態圖表融入到線上服務中,提升用戶體驗與數據洞察力。
ode環境安裝
這里以一個Vue3工程為例子
首先安裝Nodehttps://nodejs.org/zh-cn/download/請根據電腦操作系統安裝對應的安裝包
步驟 1 : 雙擊下載后的安裝包,如下所示:
步驟 2 : 點擊上圖的Run(運行),將出現如下界面:
步驟 3 : 勾選接受協議選項,點擊 next(下一步) 按鈕 :
步驟 4 : Node.js默認安裝目錄為 C:\Program Files\nodejs\, 你可以修改目錄,并點擊 next(下一步):
步驟 5 : 點擊樹形圖標來選擇你需要的安裝模式 , 然后點擊下一步 next(下一步)
步驟 6 :點擊 Install(安裝) 開始安裝Node.js。你也可以點擊 Back(返回)來修改先前的配置。 然后并點擊 next(下一步):
安裝過程:
點擊 Finish(完成)按鈕退出安裝向導。
2.Node安裝完成后需要配置環境變量
檢測PATH環境變量是否配置了Node.js,點擊開始=》運行=》輸入"cmd"=> 輸入命令"path", 輸出如下結果:
我們可以看到環境變量中已經包含了 C:\Program Files\nodejs\
如果沒有,我們就需要把我們前面安裝Node 步驟四中安裝目錄設置為環境變量:
找到我的電腦=》鼠標右鍵選擇=》 選擇屬性=》 找到高級系統設置=》 環境變量=》 變量path=》 點擊編輯=》將node安裝目錄填上并確定
最后檢查一下Node.js版本看是否安裝成功
編輯器 vscode
也可以是代碼其他編輯器,這里以vscode為例
1.安裝vscodehttps://code.visualstudio.com/
2.安裝vetur 插件點擊install安裝
3.vscode 命令行權限不足的問題: 例如執行vue、yarn等命令報錯 在安裝了@vue/cli提示vue不是內部命令這種情況,應該以管理員身份運行powerell命令行
4.如果在powerell也無法運行對應的命令就是沒有設置對應的環境變量,比如yarn安裝了,并且用yarn下載了@vue/cli 那么 vue不是內部命令就是yarn或者vue沒有配置對應的環境變量,這里yarn環境配置 默認位置 :C:\Users\Mx\AppData\Local\Yarn\bin
配置完成后再重新安裝@vue/cli就行了
執行命令 設置權限
get-ExecutionPolicy
set-ExecutionPolicy RemoteSigned
選擇并輸入Y或者A,然后再重新啟動vscode打開命令行就好。
項目應用構建
基于Vue-cli構建Vue單頁面應用程序
1.打開命令行安裝vue-cli腳手架工具(已安裝跳過此步驟)
npm install -g @vue/cli
# OR(或)
yarn global add @vue/cli
# 通過查看版本檢查是否安裝成功
vue --version
2.命令行運行命名創建新項目
# 創建名為mxdraw-test-vue3 的一個新Vue項目
vue create mxdraw-test-vue3
# 如果選擇default則會直接創建項目,創建項目包括babel\eslin這些工具,比如Router/Vuex等其他依賴需要自己手動安裝
? P1ease pick a preset:
# 默認選項
Default (vue 3)([vue 3] babel, eslint)
# 手動選擇功能
Manually select features
如果選擇Manually select features(手動安裝)則會進入下一步選項:(這里推薦大家進行手動配置)
? Check the features needed for your project :
(*) Choose vue version # 選擇vue版本
(*) Babel # 代碼編譯
(*) TypeScript # ts
( ) Progressive Web App (PWA)Support # 支持漸進式網頁應用程序
(*) Router # vue路由
( ) vuex # 狀態管理模式
( ) css Pre-processors # css預處理
(*) Linter ; Formatter # 代碼風格、格式校驗
( ) Unit Testing # 單元測試
( ) E2E Testing # 端對端測試
TypeScript 選項配置
# 選擇使用哪個版本的vue框架
? Choose a version of Vue.js that you want to start the project with
2.x # vue2.x
3.x # vue3.x
# 詢問的是是否使用class風格的組件語法,如果在項目中想要保持使用TypeScript的class風格的話,建議大家選擇y。
? Use class-style component syntax? (Y/n)
# 使用Babel與TypeScript一起用于自動檢測的填充?這里一定要選擇y
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? (Y/n)
Router 選項配置
# 路由是否使用history模式?如果項目中存在要求就使用history(即:y),但是一般還是推薦大家使用ha模式,畢竟history模式需要依賴運維。
? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n)
CSS Pre-processors css 選項配置
# 選擇一種CSS預處理類型,根據各個項目的要求使用對應css編譯處理
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): (Use arrow keys)
> Sass/SCSS (with dart-sass)
Sass/SCSS (with node-sass)
Less
Stylus
Linter / Formatter 選項配置
# TSLint只有在選擇TypeScript時才會存在。
? Pick a linter / formatter config: (Use arrow keys)
> ESLint with error prevention only # 只進行報錯提醒
ESLint + Airbnb config # 不嚴謹模式
ESLint + Standard config # 正常模式
ESLint + Prettier # 嚴格模式
TSLint (deprecated) # TypeScript格式驗證工具
# 選擇校驗時機,一般都會選擇保存時校驗,好及時做出調整
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)
(*) Lint on save # 保存時檢測
( ) Lint and fix on commit # 修復和提交時檢測
Unit Testing 選項配置
# 選擇單元測試解決方案,普遍用到最多的是Mocha + chai
? Pick a unit testing solution: (Use arrow keys)
> Mocha + Chai
Jest
E2E Testing E2E(End To End)選項配置
# 選擇端對端測試的類型
? Pick a E2E testing solution: (Use arrow keys)
> Cypress (Chrome only)
Nightwatch (WebDriver-based)
額外選項
# 選擇Babel,PostCSS, ESLint等自定義配置的存放位置。這里建議大家選擇第一個
? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
> In dedicated config files # 存放在專用配置文件中
In package.json # 存放在package.json中
# 是否保存當前選擇的配置項,如果當前配置是經常用到的配置,建議選擇y存儲一下當前配置項
? Save this as a preset for future projects? (y/N)
# 選擇n之后則會直接開始創建項目了,選擇y之后則會輸入一個存儲當前配置項的名稱:
? Save preset as:
3.運行項目
cd mxdraw-test-vue3
yarn serve
詳細說明請參考 [vue-cli文檔指南]
vue框架使用請參考[Vue.js 中文文檔]
安裝 npm
yarn add mxdraw 或 npm install mxdraw
用法
1.引入
import Mx from "mxdraw"
2.加載
<canvas id="mxcad">
</canvas>
3.javascript
import Mx from "mxdraw"
// 動態加載 js庫核心代碼
Mx.loadCoreCode().then(()=> {
// Mx.MxFun.setMxServer("ws://localhost:5090") // 開啟socket通信 可編輯圖紙
// 創建控件對象
Mx.MxFun.createMxObject({
canvasId: "mxcad", // canvas元素的id
cadFile: "/demo/buf/$hhhh.dwg.mxb1.wgh", // http方式(預覽): 加載public/demo文件夾下轉換后的圖紙
// cadFile: "test2.dwg", // socket通信方式請直接提供圖紙名稱 如:text.dwg
callback: (mxDraw, {
canvas,
canvasParent
})=> {
// 可以拿到canvas元素和它的父級元素
console.log(canvas, canvasParent)
console.log(mxDraw)
// 拿到圖層數據
mxDraw.addEvent('uiSetLayerData', (listLayer)=> {
console.log(listLayer)
})
},
isNewFile: true // 是否新建文件
})
})
如何實現一個畫線的功能命令?
1.實現畫線功能
參考資料:
* [MrxDbgUiPrPoint | getPoint] 構建取點對象
* [status] MrxDbgUiPrBaseReturn表示對應狀態
* [McEdGetPointWorldDrawObject | pWorldDraw] 用于構建一個動態繪制回調對象
* [pt1 | pt2 | lastPt] THREE.Vector3 數據類型
javascript
import Mx from "mxdraw"
// 畫線的函數
function BR_Line() {
// 構建取點對象
const getPoint=new Mx.MrxDbgUiPrPoint();
// 構建動態繪制對象
const worldDrawComment=new Mx.McEdGetPointWorldDrawObject();
// 開始動態拖動 行為: 鼠標點擊畫布時只執行一次回調函數,后續點擊無效
getPoint.go((status)=> {
if (status !==0) {
return;
}
// 獲取鼠標在畫布上的第一個點
const pt1=getPoint.value();
// 將第一個點作為起始點
let lastPt=pt1.clone();
// 設置動態繪制的回調函數
worldDrawComment.setDraw((currentPoint, pWorldDraw)=> {
// 繪制當前鼠標移動點到起始點的線段
pWorldDraw.drawLine(currentPoint, lastPt);
});
// 設置取點對象交互過程中的動態繪制調用對象
getPoint.setUserDraw(worldDrawComment)
// 開啟動態拖動,連續取點,直到ESC退出。 行為: 鼠標點擊一下執行一次回調函數
getPoint.goWhile((status)=> {
if (status===0) {
// 獲取第二個點的位置
const pt2=getPoint.value();
// 拿到Three的場景對象
let sence=Mx.MxFun.getCurrentDraw().getScene();
// 創建一條 從起始點到 當前點擊位置的線段
let line=Mx.MxThreeJS.createLine(lastPt, pt2, 0xffffff);
// 將線段添加到場景中
sence.add(line);
// 將第二點作為起始點
lastPt=pt2
}
});
});
}
2.注冊使用命名
參考資料:
* [MxFun.addCommand] 注冊命名方法
* [MxFun.sendStringToExecute] 執行命名方法
* [MxFun.isRunningCommand]檢查是否有命令在運行
javascript
import Mx from "mxdraw"
// 注冊命名
Mx.MxFun.addCommand("BR_Line", ()=> {
if(Mx.MxFun.isRunningCommand()) {
return
}
BR_Line()
})
// 執行命令
Mx.MxFun.sendStringToExecute("BR_Line")
更多Api使用說明請參考[Mx模塊集]對應模塊中的Api接口說明
按需引入配置
使用babel插件babel-plugin-import 實現按需引入
需要安裝 npm i babel-plugin-import-D 然后找到或創建項目根目錄的 .babelrc文件新增如下內容:
json
{
"plugins": [
[
"import", {
"libraryName": "mxdraw",
"libraryDirectory": "dist/lib/MxModule",
"camel2UnderlineComponentName": false,
"camel2DaComponentName": false
}
]
]
}
基于babel-plugin-import 按需引入
javascript
import { MxFun } from "mxdraw"
或者直接通過import MxFun from "mxdraw/dist/lib/MxModule/MxFun" 這樣的方式直接引入對應模塊
*請認真填寫需求信息,我們會在24小時內與您取得聯系。