update code
parent
d9d0e6ad8d
commit
7c659bc337
|
@ -44,6 +44,8 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
|
"@logicflow/core": "^1.2.27",
|
||||||
|
"@logicflow/extension": "^1.2.27",
|
||||||
"@vueuse/core": "^10.9.0",
|
"@vueuse/core": "^10.9.0",
|
||||||
"@wangeditor/editor": "^5.1.23",
|
"@wangeditor/editor": "^5.1.23",
|
||||||
"@wangeditor/editor-for-vue": "5.1.10",
|
"@wangeditor/editor-for-vue": "5.1.10",
|
||||||
|
|
|
@ -0,0 +1,503 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>onnx_viewer</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover, shrink-to-fit=no">
|
||||||
|
|
||||||
|
<link rel="shortcut icon" href="#" />
|
||||||
|
<link rel="stylesheet" href="./onnx_view/grapher.css" />
|
||||||
|
|
||||||
|
<script type="text/javascript" src="./onnx_view/base.js"></script>
|
||||||
|
<script type="text/javascript" src="./onnx_view/dagre.js"></script>
|
||||||
|
<script type="text/javascript" src="./onnx_view/grapher.js"></script>
|
||||||
|
<script type="text/javascript" src="./onnx_view/onnx_model.js"></script>
|
||||||
|
<script type="text/javascript" src="./onnx_view/onnx_view.js"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
html { touch-action: none; overflow: hidden; width: 100%; height: 100%; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; text-rendering: optimizeLegibility; -webkit-text-rendering: optimizeLegibility; -moz-text-rendering: optimizeLegibility; -ms-text-rendering: optimizeLegibility; -o-text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-font-smoothing: antialiased; -ms-font-smoothing: antialiased; -o-font-smoothing: antialiased; }
|
||||||
|
body { touch-action: none; overflow: hidden; width: 100%; height: 100%; margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; font-size: 12px; text-rendering: geometricPrecision; }
|
||||||
|
button { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; }
|
||||||
|
.center { position: absolute; margin: auto; top: 0; right: 0; bottom: 0; left: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||||
|
.select { user-select: text; -webkit-user-select: text; -moz-user-select: text; }
|
||||||
|
.graph { display: flex; height: 100%; width: 100%; overflow: auto; outline: none; touch-action: pan-x pan-y; }
|
||||||
|
.canvas { margin: auto; flex-shrink: 0; text-rendering: geometricPrecision; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||||
|
.default { background-color: #ffffff; }
|
||||||
|
.default .logo { display: none; }
|
||||||
|
.default .graph { display: flex; opacity: 1; }
|
||||||
|
.default .toolbar { display: table; }
|
||||||
|
.toolbar { position: absolute; bottom: 10px; left: 10px; padding: 0; margin: 0; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||||
|
.toolbar button:focus { outline: 0; }
|
||||||
|
.toolbar-button { float: left; background: None; border-radius: 6px; border: 0; margin: 0; margin-right: 1px; padding: 0; fill: None; stroke: #777; cursor: pointer; width: 24px; height: 24px; user-select: none; }
|
||||||
|
.toolbar-path { float: left }
|
||||||
|
.toolbar-path-back-button { float: left; background: #777; border-top-left-radius: 6px; border-bottom-left-radius: 6px; border: 0px solid; border-color: #777; margin: 2px 0px 2px 8px; padding: 0 8px 0 8px; cursor: pointer; height: 20px; color: #ffffff; font-size: 11px; line-height: 0; transition: 0.1s; }
|
||||||
|
.toolbar-path-back-button:hover { background: #000000; border-color: #000000; }
|
||||||
|
.toolbar-path-name-button { float: left; background: #777; border: 0px solid; border-color: #777; color: #ffffff; border-left: 1px; border-left-color: #ffffff; margin: 2px 0 2px 1px; padding: 0 8px 0 8px; cursor: pointer; width: auto; height: 20px; font-size: 11px; line-height: 0; transition: 0.1s; }
|
||||||
|
.toolbar-path-name-button:hover { background: #000000; border-color: #000000; }
|
||||||
|
.toolbar-path-name-button:last-child { border-top-right-radius: 6px; border-bottom-right-radius: 6px; }
|
||||||
|
.toolbar-icon .border { stroke: #fff; }
|
||||||
|
.toolbar-icon .stroke { stroke: #808080; }
|
||||||
|
.toolbar-icon:hover .stroke { stroke: #000000; }
|
||||||
|
.welcome body { background-color: #ececec; }
|
||||||
|
.welcome { background-color: #ececec; color: #242424; }
|
||||||
|
.logo-icon { left: 0px; top: -18px; width: 106px; height: 106px; transition: 0.1s; }
|
||||||
|
.logo-spinner { left: 0px; top: -18px; width: 106px; height: 106px; display: none; }
|
||||||
|
.logo-stroke { stroke: #444444; }
|
||||||
|
.logo-fill { fill: #444444; }
|
||||||
|
.logo-border { stroke: #555555; }
|
||||||
|
.logo-glyph { fill: #444444; }
|
||||||
|
.logo-button { font-size: 12px; font-weight: bold; line-height: 1.25; text-align: center; vertical-align: middle; min-width: 5em; height: 2.7em; border-radius: 1.3em; transition: 0.1s; user-select: none; -webkit-user-select: none; -moz-user-select: none; color: #444444; background-color: #ececec; border: 1px solid #444444; }
|
||||||
|
.logo-button:hover { color: #ececec; background-color: #444444; cursor: pointer; transition: 0.2s; }
|
||||||
|
.logo-button:focus { outline: 0; }
|
||||||
|
.progress { top: 120px; height: 2px; width: 400px; }
|
||||||
|
.progress-bar { height: 100%; width: 0%; background-color: #444444; }
|
||||||
|
.message .progress { display:none; }
|
||||||
|
.welcome .graph { display: none; opacity: 0; }
|
||||||
|
.welcome .menu { background-color: #ffffff; }
|
||||||
|
.welcome.spinner .logo-spinner { display: block; -webkit-animation: orbit 0.5s infinite linear; animation: orbit 0.5s infinite linear; cursor: wait; }
|
||||||
|
.welcome.spinner .menu-button { display: none; }
|
||||||
|
.welcome.message .menu-button { display: none; }
|
||||||
|
.titlebar { color: #aaaaaa; display: none; height: 32px; position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 2; -webkit-app-region: drag; }
|
||||||
|
.titlebar-visible { display: block; }
|
||||||
|
.titlebar-content { display: block; padding: 0 142px; height: 100%; text-align: center; font-size: 14px; line-height: 32px; transition: all .1s ease-in-out; user-select: none; }
|
||||||
|
.titlebar-content-text { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||||
|
.spinner .titlebar-content { opacity: 0; }
|
||||||
|
.active .titlebar { color: #464646; transition: all 0.05s ease-in-out; }
|
||||||
|
.titlebar-control-box { display: none; align-items: center; flex-direction: row-reverse; height: 100%; position: absolute; top: 0; right: 0; width: 138px; }
|
||||||
|
.titlebar-control-box-visible { display: flex; }
|
||||||
|
.titlebar-icon { width: 1em; height: 1em; vertical-align: -0.15em; fill: currentColor; overflow: hidden; }
|
||||||
|
.titlebar-button { display: flex; justify-content: center; align-items: center; width: 46px; height: 32px; user-select: none; -webkit-app-region: no-drag; }
|
||||||
|
.titlebar-button:hover { color: #000000; background-color: rgba(0, 0, 0, 0.15); }
|
||||||
|
.titlebar-button-close:hover { color: #ffffff; background-color: #b43029; }
|
||||||
|
.menu-button { display: flex; justify-content: center; align-items: center; color: #aaaaaa; font-size: 20px; height: 32px; width: 32px; position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 2; -webkit-app-region: no-drag; -webkit-app-region: no-drag; user-select: none; }
|
||||||
|
.menu-button:hover { color: #000000; }
|
||||||
|
.menu { display: block; position: absolute; left: -17em; width: 17em; top: 0; height: 100%; z-index: 2; background-color: #ececec; border-right: 1px solid rgba(255, 255, 255, 0.5); padding-top: 40px; padding-bottom: 2px; margin-left: 0; margin-top: 0; overflow: hidden; transition: 0.1s; }
|
||||||
|
.menu .menu-group { margin-bottom: 12px; }
|
||||||
|
.menu .menu-group .menu-group-header { display: block; border: none; border-radius: 0; color: black; width: 100%; text-align: left; margin: 4px 12px 5px 12px; white-space: no-wrap; font-size: 11px; font-weight: bold; color: #bbbbbb; white-space: nowrap; }
|
||||||
|
.menu .menu-group .menu-command { display: block; border: none; border-radius: 0; background-color: transparent; color: black; width: 100%; text-align: left; padding: 4px 12px 5px 12px; font-size: 12px; }
|
||||||
|
.menu .menu-group .menu-command:focus { color: #ffffff; background-color: #2e6bd2; outline: none; }
|
||||||
|
.menu .menu-group .menu-command:disabled { color: #888888; }
|
||||||
|
.menu .menu-group .menu-command .menu-label { display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
||||||
|
.menu .menu-group .menu-command .menu-shortcut { display: block; float: right; margin-left: 25px; color: #888888; }
|
||||||
|
.menu .menu-group .menu-separator { border-top: 1px; border-bottom: 0; border-style: solid; border-color: #e5e5e5; margin-left: 12px; margin-right: 12px; }
|
||||||
|
@-webkit-keyframes orbit { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } }
|
||||||
|
@keyframes orbit { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); transform: rotate(360deg); } }
|
||||||
|
.welcome.spinner .logo-spinner-stroke { stroke: #ececec; }
|
||||||
|
.welcome.spinner .graph { display: flex; opacity: 0; }
|
||||||
|
.welcome .toolbar { display: none; }
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root { color-scheme: dark; }
|
||||||
|
.default { background-color: #404040; }
|
||||||
|
.graph { background-color: #404040; }
|
||||||
|
.welcome { background-color: #1e1e1e; color: #888888; }
|
||||||
|
.logo-stroke { stroke: #888888; }
|
||||||
|
.logo-fill { fill: #888888; }
|
||||||
|
.logo-border { stroke: #000000; }
|
||||||
|
.logo-glyph { fill: #888888; }
|
||||||
|
.logo-spinner-stroke { stroke: #ffffff; }
|
||||||
|
.logo-button { color: #888888; background-color: #1e1e1e; border-color: #888888; }
|
||||||
|
.logo-button:hover { color: #1e1e1e; background-color: #888888; }
|
||||||
|
.welcome .progress-bar { background-color: #888888; }
|
||||||
|
.welcome .menu { background-color: #2d2d2d }
|
||||||
|
.toolbar-icon .border { stroke: #1d1d1d; }
|
||||||
|
.toolbar-icon .stroke { stroke: #aaaaaa; }
|
||||||
|
.toolbar-icon:hover .stroke { stroke: #dfdfdf; }
|
||||||
|
.toolbar-path-back-button { background: #aaaaaa; border-color: #aaaaaa; color: #333333; }
|
||||||
|
.toolbar-path-back-button:hover { background: #dfdfdf; border-color: #dfdfdf; }
|
||||||
|
.toolbar-path-name-button { background: #aaaaaa ; border-color: #aaaaaa; color: #404040; }
|
||||||
|
.toolbar-path-name-button:hover { background: #dfdfdf; border-color: #dfdfdf; }
|
||||||
|
.titlebar { color: #949494; }
|
||||||
|
.welcome body { background-color: #1e1e1e; }
|
||||||
|
.default body { background-color: #404040; }
|
||||||
|
.active .titlebar { color: #c4c4c4; }
|
||||||
|
.titlebar-button:hover { color: #ffffff; background-color: rgba(0, 0, 0, 0.15); }
|
||||||
|
.titlebar-button-close:hover { color: #ffffff; background-color: #b43029; }
|
||||||
|
.menu-button { color: #aaaaaa; }
|
||||||
|
.menu-button:hover { color: #ffffff; }
|
||||||
|
.menu { background-color: #2d2d2d; border-color: rgba(0, 0, 0, 0); }
|
||||||
|
.menu .menu-group .menu-group-header { color: #666666; }
|
||||||
|
.menu .menu-group .menu-command { color: #ffffff; }
|
||||||
|
.menu .menu-group .menu-command:focus { color: #ffffff; background-color: #2e6bd2; }
|
||||||
|
.menu .menu-group .menu-command:disabled { color: #888888; }
|
||||||
|
.menu .menu-group .menu-command .shortcut { color: #888888; }
|
||||||
|
.menu .menu-group .menu-separator { border-color: #363636; }
|
||||||
|
}
|
||||||
|
@media all and (max-width: 640px) {
|
||||||
|
.logo { width: 240px; }
|
||||||
|
.logo-icon { left: 0; top: 0; width: 128px; height: 128px; }
|
||||||
|
.logo-spinner { left: 0; top: 0; width: 128px; height: 128px; }
|
||||||
|
.progress { top: 160px; height: 2px; width: 100px; }
|
||||||
|
}
|
||||||
|
@media only screen and (max-device-width: 1024px) {
|
||||||
|
.toolbar-button { width: 32px; height: 32px; }
|
||||||
|
.toolbar-path-back-button { margin-top: 6px; margin-bottom: 6px; }
|
||||||
|
.toolbar-path-name-button { margin-top: 6px; margin-bottom: 6px; }
|
||||||
|
}
|
||||||
|
.sidebar { display: flex; flex-direction: column; font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif; font-size: 12px; height: 100%; right: -100%; position: fixed; transition: 0.1s; top: 0; background-color: #ececec; color: #242424; overflow: hidden; border-left: 1px solid rgba(255, 255, 255, 0.5); opacity: 0; }
|
||||||
|
.sidebar-title { font-weight: bold; font-size: 12px; letter-spacing: 0.5px; text-transform: uppercase; height: 20px; margin: 0; padding: 20px; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||||
|
.sidebar-closebutton { padding: 8px 8px 8px 32px; text-decoration: none; font-size: 25px; color: #777777; opacity: 1.0; display: block; transition: 0.2s; position: absolute; top: 0; right: 15px; margin-left: 50px; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||||
|
.sidebar-closebutton:hover { color: #242424; }
|
||||||
|
.sidebar-content { display: flex; flex-direction: column; flex-grow: 1; height: 0; }
|
||||||
|
.sidebar-header { font-weight: bold; font-size: 11px; text-transform: uppercase; line-height: 1.25; margin-top: 16px; margin-bottom: 16px; border-bottom: 1px solid #ececec; display: block; user-select: none; -webkit-user-select: none; -moz-user-select: none; cursor: default; }
|
||||||
|
.sidebar-object { flex-grow: 1; padding: 0px 20px 20px 20px; overflow-y: auto; }
|
||||||
|
.sidebar-item { margin-bottom: 0px; display: block; }
|
||||||
|
.sidebar-item-name { float: left; font-size: 11px; min-width: 95px; max-width: 95px; padding-right: 5px; padding-top: 7px; display: block; }
|
||||||
|
.sidebar-item-name input { color: #777; font-family: inherit; font-size: inherit; color: inherit; background-color: inherit; width: 100%; text-align: right; margin: 0; padding: 0; border: 0; outline: none; text-overflow: ellipsis; }
|
||||||
|
.sidebar-item-value-list { margin: 0; margin-left: 105px; overflow: hidden; display: block; padding: 0; }
|
||||||
|
.sidebar-item-value { font-size: 11px; background-color: #fcfcfc; border-radius: 2px; border: 1px solid #fcfcfc; margin-top: 3px; margin-bottom: 3px; overflow: auto; }
|
||||||
|
.sidebar-item-value-dark { background-color: #f8f8f8; border: 1px solid #f8f8f8; }
|
||||||
|
.sidebar-item-value b { font-weight: bold; }
|
||||||
|
.sidebar-item-value code { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; overflow: auto; white-space: pre-wrap; word-wrap: break-word; }
|
||||||
|
.sidebar-item-value pre { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; margin: 0; overflow: auto; white-space: pre; word-wrap: normal; display: block; }
|
||||||
|
.sidebar-item-value-line { padding: 4px 6px 4px 6px; }
|
||||||
|
.sidebar-item-value-line-link { padding: 4px 6px 4px 6px; cursor: default; overflow-x: auto; }
|
||||||
|
.sidebar-item-value-line-link:hover { text-decoration: underline; }
|
||||||
|
.sidebar-item-value-line-border { padding: 4px 6px 4px 6px; border-top: 1px solid rgba(27, 31, 35, 0.05); }
|
||||||
|
.sidebar-item-value-line-content { white-space: pre; word-wrap: normal; overflow: auto; display: block; }
|
||||||
|
.sidebar-item-value-expander { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; float: right; color: #aaa; cursor: pointer; user-select: none; -webkit-user-select: none; -moz-user-select: none; padding: 4px 6px 4px 6px; }
|
||||||
|
.sidebar-item-value-expander:hover { color: #000; }
|
||||||
|
.sidebar-item-select {
|
||||||
|
font-family: inherit; font-size: 12px;
|
||||||
|
background-color: #fcfcfc; border: #fcfcfc; color: #333;
|
||||||
|
border-radius: 2px; width: 100%; height: 23px; padding: 3px 12px 3px 7px;
|
||||||
|
margin-top: 3px; margin-bottom: 3px; outline: none;
|
||||||
|
box-sizing: border-box; -moz-box-sizing: border-box;
|
||||||
|
appearance: none; -webkit-appearance: none; -moz-appearance: none;
|
||||||
|
background-image: linear-gradient(45deg, transparent 50%, #333 50%), linear-gradient(135deg, #333 50%, transparent 50%);
|
||||||
|
background-position: calc(100% - 12px) calc(10px), calc(100% - 7px) calc(10px);
|
||||||
|
background-size: 5px 5px, 5px 5px;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
.sidebar-separator { margin-bottom: 20px; }
|
||||||
|
.sidebar-find-search { font-family: inherit; font-size: 13px; margin: 0px 20px 8px 20px; padding: 8px 16px 8px 16px; background: #fff; border-radius: 16px; border: 0; outline: 0; }
|
||||||
|
.sidebar-find-content { flex-grow: 1; padding: 0px 20px 20px 20px; padding-right: 20px; overflow-y: auto; list-style-type: none; overflow-y: auto; margin: 0; }
|
||||||
|
.sidebar-find-content li { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; margin: 0; padding: 5px 8px 5px 18px; outline: 0; white-space: nowrap; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||||
|
.sidebar-find-content li:hover { background: #e5e5e5; }
|
||||||
|
.sidebar-documentation { flex-grow: 1; padding: 0px 20px 20px 20px; overflow-y: auto; font-size: 13px; line-height: 1.5; margin: 0; }
|
||||||
|
.sidebar-documentation h1 { font-weight: bold; font-size: 13px; line-height: 1.25; border-bottom: 1px solid #e8e8e8; padding-bottom: 0.3em; margin-top: 0; margin-bottom: 16px; }
|
||||||
|
.sidebar-documentation h2 { font-weight: bold; font-size: 11px; line-height: 1.25; margin-top: 20px; margin-bottom: 16px; text-transform: uppercase; border: 0; }
|
||||||
|
.sidebar-documentation h3 { font-weight: bold; font-size: 11px; line-height: 1.25; }
|
||||||
|
.sidebar-documentation p { margin-top: 4px; margin-bottom: 4px; margin-left: 0px; }
|
||||||
|
.sidebar-documentation a { color: #237; }
|
||||||
|
.sidebar-documentation code { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; background-color: rgba(27, 31, 35, 0.05); padding: 0.2em 0.4em; margin: 0; border-radius: 3px; }
|
||||||
|
.sidebar-documentation pre { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 12px; padding: 16px; overflow: auto; line-height: 1.45; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px; }
|
||||||
|
.sidebar-documentation pre code { font-size: 13px; padding: 16px; line-height: 1.45; background-color: transparent; padding: 0; border-radius: 0; }
|
||||||
|
.sidebar-documentation tt { font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-weight: bold; font-size: 90%; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px; padding: 0.2em 0.4em; margin: 0; }
|
||||||
|
.sidebar-documentation dl dt { font-size: 13px; font-weight: bold; padding: 0; margin-top: 16px; margin-left: 0px; }
|
||||||
|
.sidebar-documentation dd { padding: 0 16px; margin-left: 0; margin-bottom: 16px; }
|
||||||
|
.sidebar-documentation ul { margin-top: 6px; margin-bottom: 6px; padding-left: 20px; }
|
||||||
|
.sidebar-documentation blockquote { margin-left: 15px; margin-right: 15px; }
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.sidebar html { color: #dfdfdf; }
|
||||||
|
.sidebar { background-color: #2d2d2d; color: #dfdfdf; border-left: 1px solid rgba(0, 0, 0, 0); }
|
||||||
|
.sidebar-closebutton { padding: 8px 8px 8px 32px; text-decoration: none; font-size: 25px; color: #777777; opacity: 1.0; display: block; transition: 0.2s; position: absolute; top: 0; right: 15px; margin-left: 50px; user-select: none; -webkit-user-select: none; -moz-user-select: none; }
|
||||||
|
.sidebar-closebutton:hover { color: #ffffff; }
|
||||||
|
.sidebar-item-value { background-color: #383838; border-color: #383838; }
|
||||||
|
.sidebar-item-value-dark { background-color: #3e3e3e; border-color: #3e3e3e; }
|
||||||
|
.sidebar-item-value-line-border { border-color: rgba(0, 0, 0, 0.09); }
|
||||||
|
.sidebar-item-select { background-color: #383838; border: #383838; color: #dfdfdf; background-image: linear-gradient(45deg, transparent 50%, #aaa 50%), linear-gradient(135deg, #aaa 50%, transparent 50%); }
|
||||||
|
.sidebar-header { border-bottom-color: #2d2d2d; color: #dfdfdf; }
|
||||||
|
.sidebar-documentation h1 { border-bottom: 1px solid #424242; color: #dfdfdf; }
|
||||||
|
.sidebar-documentation h2 { color: #dfdfdf; }
|
||||||
|
.sidebar-documentation p { color: #aaaaaa; }
|
||||||
|
.sidebar-documentation a { color: #6688aa; }
|
||||||
|
.sidebar-documentation tt { background-color:#1e1e1e; }
|
||||||
|
.sidebar-documentation code { background-color: #1e1e1e; }
|
||||||
|
.sidebar-documentation pre { background-color: #1e1e1e; }
|
||||||
|
.sidebar-find-search { background: #383838; color: #dfdfdf; border-color: #424242; }
|
||||||
|
.sidebar-find-content li:hover { background: #383838; }
|
||||||
|
}
|
||||||
|
@media screen and (prefers-reduced-motion: reduce) {
|
||||||
|
.menu { transition: none; }
|
||||||
|
.sidebar { transition: none; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="welcome spinner">
|
||||||
|
<div id="graph" class="graph" tabindex="0">
|
||||||
|
<svg id="canvas" class="canvas" preserveaspectratio="xMidYMid meet" width="100%" height="100%"></svg>
|
||||||
|
</div>
|
||||||
|
<div id="sidebar" class="sidebar">
|
||||||
|
<h1 id="sidebar-title" class="sidebar-title"></h1>
|
||||||
|
<a id="sidebar-closebutton" class="sidebar-closebutton" href="javascript:void(0)" draggable="false">×</a>
|
||||||
|
<div id="sidebar-content" class="sidebar-content"></div>
|
||||||
|
</div>
|
||||||
|
<div id="toolbar" class="toolbar">
|
||||||
|
<button id="sidebar-button" class="toolbar-button" title="Model Properties">
|
||||||
|
<svg class="toolbar-icon" viewbox="0 0 100 100">
|
||||||
|
<rect class="border" x="12" y="12" width="76" height="76" rx="16" ry="16" stroke-width="8"></rect>
|
||||||
|
<line class="border" x1="28" y1="37" x2="32" y2="37" stroke-width="8" stroke-linecap="round"
|
||||||
|
stroke="#fff"></line>
|
||||||
|
<line class="border" x1="28" y1="50" x2="32" y2="50" stroke-width="8" stroke-linecap="round"
|
||||||
|
stroke="#fff"></line>
|
||||||
|
<line class="border" x1="28" y1="63" x2="32" y2="63" stroke-width="8" stroke-linecap="round"
|
||||||
|
stroke="#fff"></line>
|
||||||
|
<line class="border" x1="40" y1="37" x2="70" y2="37" stroke-width="8" stroke-linecap="round"
|
||||||
|
stroke="#fff"></line>
|
||||||
|
<line class="border" x1="40" y1="50" x2="70" y2="50" stroke-width="8" stroke-linecap="round"
|
||||||
|
stroke="#fff"></line>
|
||||||
|
<line class="border" x1="40" y1="63" x2="70" y2="63" stroke-width="8" stroke-linecap="round"
|
||||||
|
stroke="#fff"></line>
|
||||||
|
<rect class="stroke" x="12" y="12" width="76" height="76" rx="16" ry="16" stroke-width="4"></rect>
|
||||||
|
<line class="stroke" x1="28" y1="37" x2="32" y2="37" stroke-width="4" stroke-linecap="round"></line>
|
||||||
|
<line class="stroke" x1="28" y1="50" x2="32" y2="50" stroke-width="4" stroke-linecap="round"></line>
|
||||||
|
<line class="stroke" x1="28" y1="63" x2="32" y2="63" stroke-width="4" stroke-linecap="round"></line>
|
||||||
|
<line class="stroke" x1="40" y1="37" x2="70" y2="37" stroke-width="4" stroke-linecap="round"></line>
|
||||||
|
<line class="stroke" x1="40" y1="50" x2="70" y2="50" stroke-width="4" stroke-linecap="round"></line>
|
||||||
|
<line class="stroke" x1="40" y1="63" x2="70" y2="63" stroke-width="4" stroke-linecap="round"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button id="zoom-in-button" class="toolbar-button" title="Zoom In">
|
||||||
|
<svg class="toolbar-icon" viewbox="0 0 100 100">
|
||||||
|
<circle class="border" cx="50" cy="50" r="35" stroke-width="8" stroke="#fff"></circle>
|
||||||
|
<line class="border" x1="50" y1="38" x2="50" y2="62" stroke-width="8" stroke-linecap="round"
|
||||||
|
stroke="#fff"></line>
|
||||||
|
<line class="border" x1="38" y1="50" x2="62" y2="50" stroke-width="8" stroke-linecap="round"
|
||||||
|
stroke="#fff"></line>
|
||||||
|
<line class="border" x1="78" y1="78" x2="82" y2="82" stroke-width="12" stroke-linecap="square"
|
||||||
|
stroke="#fff"></line>
|
||||||
|
<circle class="stroke" cx="50" cy="50" r="35" stroke-width="4"></circle>
|
||||||
|
<line class="stroke" x1="50" y1="38" x2="50" y2="62" stroke-width="4" stroke-linecap="round"></line>
|
||||||
|
<line class="stroke" x1="38" y1="50" x2="62" y2="50" stroke-width="4" stroke-linecap="round"></line>
|
||||||
|
<line class="stroke" x1="78" y1="78" x2="82" y2="82" stroke-width="8" stroke-linecap="square"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button id="zoom-out-button" class="toolbar-button" title="Zoom Out">
|
||||||
|
<svg class="toolbar-icon" viewbox="0 0 100 100">
|
||||||
|
<circle class="border" cx="50" cy="50" r="35" stroke-width="8" stroke="#fff"></circle>
|
||||||
|
<line class="border" x1="38" y1="50" x2="62" y2="50" stroke-width="8" stroke-linecap="round"
|
||||||
|
stroke="#fff"></line>
|
||||||
|
<line class="border" x1="78" y1="78" x2="82" y2="82" stroke-width="12" stroke-linecap="square"
|
||||||
|
stroke="#fff"></line>
|
||||||
|
<circle class="stroke" cx="50" cy="50" r="35" stroke-width="4"></circle>
|
||||||
|
<line class="stroke" x1="38" y1="50" x2="62" y2="50" stroke-width="4" stroke-linecap="round"></line>
|
||||||
|
<line class="stroke" x1="78" y1="78" x2="82" y2="82" stroke-width="8" stroke-linecap="square"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div id="toolbar-path" class="toolbar-path">
|
||||||
|
<button id="toolbar-path-back-button" class="toolbar-path-back-button" title="Back">
|
||||||
|
❮
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="logo" class="center logo">
|
||||||
|
<a href="javascript:;" target="blank_">
|
||||||
|
<svg class="center logo-icon" viewbox="0 0 1024 1024">
|
||||||
|
<circle class="logo-stroke" cx="512" cy="512" r="431" fill="none" stroke-width="32"></circle>
|
||||||
|
<circle class="logo-border" cx="512" cy="512" r="450" fill="none" stroke-width="6"></circle>
|
||||||
|
<circle class="logo-border" cx="512" cy="512" r="412" fill="none" stroke-width="6"></circle>
|
||||||
|
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="280" stroke-width="12"></line>
|
||||||
|
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="280" stroke-width="12"></line>
|
||||||
|
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="435" stroke-width="12"></line>
|
||||||
|
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="435" stroke-width="12"></line>
|
||||||
|
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="590" stroke-width="12"></line>
|
||||||
|
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="590" stroke-width="12"></line>
|
||||||
|
<line class="logo-stroke" x1="296" y1="392" x2="540" y2="744" stroke-width="12"></line>
|
||||||
|
<line class="logo-stroke" x1="296" y1="632" x2="540" y2="744" stroke-width="12"></line>
|
||||||
|
<line class="logo-stroke" x1="540" y1="280" x2="785" y2="512" stroke-width="12"></line>
|
||||||
|
<line class="logo-stroke" x1="540" y1="590" x2="785" y2="512" stroke-width="12"></line>
|
||||||
|
<line class="logo-stroke" x1="540" y1="435" x2="785" y2="512" stroke-width="12"></line>
|
||||||
|
<line class="logo-stroke" x1="540" y1="744" x2="785" y2="512" stroke-width="12"></line>
|
||||||
|
<g transform="translate(296, 392)">
|
||||||
|
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||||
|
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(296, 632)">
|
||||||
|
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||||
|
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(540, 280)">
|
||||||
|
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||||
|
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(540, 435)">
|
||||||
|
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||||
|
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(540, 590)">
|
||||||
|
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||||
|
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(540, 744)">
|
||||||
|
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||||
|
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(785, 512)">
|
||||||
|
<circle class="logo-fill" cx="0" cy="0" r="51"></circle>
|
||||||
|
<circle class="logo-border" cx="0" cy="0" r="51" fill="none" stroke-width="6"></circle>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<svg id="logo-spinner" class="center logo-spinner" viewbox="0 0 1024 1024">
|
||||||
|
<g transform="translate(512, 512)" style="opacity: 1">
|
||||||
|
<path class="logo-spinner-stroke" d="M-431,0 A-431,-431 0 0,1 0,-431" stroke-width="24" fill="None">
|
||||||
|
</path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<div class="center progress">
|
||||||
|
<div id="progress-bar" class="progress-bar"></div>
|
||||||
|
</div>
|
||||||
|
<!-- Preload fonts to workaround Chrome SVG layout issue -->
|
||||||
|
<div style="font-weight: normal; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
|
||||||
|
<div style="font-weight: bold; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
|
||||||
|
<div style="font-weight: bold; color: rgba(0, 0, 0, 0.01); user-select: none;">.</div>
|
||||||
|
</div>
|
||||||
|
<div id="titlebar" class="titlebar">
|
||||||
|
<svg style="position: absolute; width: 0px; height: 0px; overflow: hidden;" aria-hidden="true">
|
||||||
|
<symbol id="icon-arrow-right" viewBox="0 0 1024 1024">
|
||||||
|
<path
|
||||||
|
d="M698.75712 565.02272l-191.488 225.4848a81.73568 81.73568 0 0 1-62.48448 28.89728 81.89952 81.89952 0 0 1-62.40256-134.94272l146.432-172.4416-146.432-172.4416a81.92 81.92 0 0 1 124.88704-106.06592l191.488 225.4848a81.87904 81.87904 0 0 1 0 106.02496z">
|
||||||
|
</path>
|
||||||
|
</symbol>
|
||||||
|
</svg>
|
||||||
|
<div id="titlebar-content" class="titlebar-content">
|
||||||
|
<span id="titlebar-content-text" class="titlebar-content-text"></span>
|
||||||
|
</div>
|
||||||
|
<div id="titlebar-control-box" class="titlebar-control-box">
|
||||||
|
<div id="titlebar-close" class="titlebar-button titlebar-button-close" title="Close">
|
||||||
|
<svg class="titlebar-icon" aria-hidden="true">
|
||||||
|
<path
|
||||||
|
d="M 0,0 0,0.7 4.3,5 0,9.3 0,10 0.7,10 5,5.7 9.3,10 10,10 10,9.3 5.7,5 10,0.7 10,0 9.3,0 5,4.3 0.7,0 Z">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div id="titlebar-toggle" class="titlebar-button" title="Maximize">
|
||||||
|
<svg id="titlebar-maximize" class="titlebar-icon" aria-hidden="true" style="position: absolute;">
|
||||||
|
<path d="M 0,0 0,10 10,10 10,0 Z M 1,1 9,1 9,9 1,9 Z"></path>
|
||||||
|
</svg>
|
||||||
|
<svg id="titlebar-restore" class="titlebar-icon" aria-hidden="true" style="position: absolute;">
|
||||||
|
<path
|
||||||
|
d="m 2,1e-5 0,2 -2,0 0,8 8,0 0,-2 2,0 0,-8 z m 1,1 6,0 0,6 -1,0 0,-5 -5,0 z m -2,2 6,0 0,6 -6,0 z">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div id="titlebar-minimize" class="titlebar-button" title="Minimize">
|
||||||
|
<svg class="titlebar-icon" aria-hidden="true">
|
||||||
|
<path d="M 0,5 10,5 10,6 0,6 Z"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="menu" class="menu" style="opacity: 1; left: 0px;display: none;">
|
||||||
|
<div id="menu-item-0" class="menu-group" style="opacity: 1">
|
||||||
|
<div class="menu-group-header"><u>F</u>ile</div>
|
||||||
|
<button class="menu-command" style="display: block" onclick="mainView.export(document.body.title+'.png')">
|
||||||
|
<span class="menu-label">Export as PNG</span>
|
||||||
|
</button>
|
||||||
|
<button class="menu-command" style="display: block" onclick="mainView.export(document.body.title+'.svg')" >
|
||||||
|
<span class="menu-label">Export as SVG</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="menu-item-1" class="menu-group" style="opacity: 1">
|
||||||
|
<div class="menu-group-header"><u>E</u>dit</div>
|
||||||
|
<button class="menu-command" style="display: block" onclick="mainView.find()">
|
||||||
|
<span class="menu-label">Find...</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="menu-item-2" class="menu-group" style="opacity: 1">
|
||||||
|
<div class="menu-group-header"><u>V</u>iew</div>
|
||||||
|
<button class="menu-command" style="display: block" onclick="doToggle('attributes')">
|
||||||
|
<span class="menu-label" id="opAtt">Show Attributes</span></button>
|
||||||
|
<button class="menu-command" style="display: block" onclick="doToggle('weights')">
|
||||||
|
<span class="menu-label" id="opWeight">Show &Weights</span></button>
|
||||||
|
<button class="menu-command" style="display: block" onclick="doToggle('names')">
|
||||||
|
<span class="menu-label" id="opName">Show Names</span></button>
|
||||||
|
<button class="menu-command" style="display: block" onclick="doToggle('direction')">
|
||||||
|
<span class="menu-label" id="opDir">Show Horizontal</span>
|
||||||
|
</button>
|
||||||
|
<button class="menu-command" style="display: block" onclick="doToggle('mousewheel')">
|
||||||
|
<span class="menu-label" id="opMouse">Mouse Wheel: Zoom</span>
|
||||||
|
</button>
|
||||||
|
<div class="menu-separator" style="display: block"></div>
|
||||||
|
<button class="menu-command" style="display: block" onclick="mainView.zoomIn()">
|
||||||
|
<span class="menu-label">Zoom In</span></button>
|
||||||
|
<button class="menu-command" style="display: block" onclick="mainView.zoomOut()">
|
||||||
|
<span class="menu-label">Zoom Out</span></button>
|
||||||
|
<button class="menu-command" style="display: block" onclick="mainView.resetZoom()">
|
||||||
|
<span class="menu-label">Actual Size</span>
|
||||||
|
</button>
|
||||||
|
<div class="menu-separator" style="display: block" ></div>
|
||||||
|
<button class="menu-command" style="display: block" onclick="mainView.showModelProperties()">
|
||||||
|
<span class="menu-label">Properties...</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="menu-button" class="menu-button" onclick="toggleMenu()">≡</div>
|
||||||
|
<script>
|
||||||
|
function init(){
|
||||||
|
var s=location.search;
|
||||||
|
var url="";
|
||||||
|
var onnxModelName="";
|
||||||
|
if(s.indexOf("=")>=0){
|
||||||
|
url=s.substring(s.indexOf("=")+1);
|
||||||
|
if(url.toLocaleLowerCase().indexOf(".onnx")>=0){
|
||||||
|
onnxModelName=url.substring(url.lastIndexOf("/")+1)
|
||||||
|
}else{
|
||||||
|
console.error("使用方法:onnx.html?url=[onnx路径]")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
console.error("使用方法:onnx.html?url=[onnx路径]")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
document.body.title=onnxModelName;
|
||||||
|
//url='./siamRPN_192.onnx'
|
||||||
|
var http=new XMLHttpRequest();
|
||||||
|
http.responseType="arraybuffer"
|
||||||
|
http.open('GET',url);
|
||||||
|
http.onload=function(){
|
||||||
|
if(http.status==200){
|
||||||
|
var reader=proto.protobuf.Reader.create(new Uint8Array(http.response));
|
||||||
|
var onnxProtoModel = window.proto.onnx.ModelProto.decode(reader);
|
||||||
|
let { locations, graphs } = window.getExternalLocations(onnxProtoModel);
|
||||||
|
let model = new window.onnx.Model(onnxProtoModel, graphs, new Map());
|
||||||
|
|
||||||
|
let host = window;
|
||||||
|
let view = new window.View(host);
|
||||||
|
view.start().then((data) => {
|
||||||
|
view.open(model, onnxModelName);
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
window.mainView=view;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
http.send();
|
||||||
|
}
|
||||||
|
init();
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
function exportImg(file, blob) {
|
||||||
|
const element = this.document.createElement('a');
|
||||||
|
element.download = file;
|
||||||
|
element.href = URL.createObjectURL(blob);
|
||||||
|
this.document.body.appendChild(element);
|
||||||
|
element.click();
|
||||||
|
this.document.body.removeChild(element);
|
||||||
|
}
|
||||||
|
function toggleMenu(){
|
||||||
|
let el=document.getElementById("menu");
|
||||||
|
if(el.style.display=="none"){
|
||||||
|
el.style.display="block"
|
||||||
|
updateState();
|
||||||
|
}else{
|
||||||
|
el.style.display="none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function doToggle(att){
|
||||||
|
mainView.toggle(att)
|
||||||
|
updateState();
|
||||||
|
}
|
||||||
|
function updateState(){
|
||||||
|
var op=mainView.options;
|
||||||
|
document.getElementById("opAtt").innerText=op.attributes ? 'Hide Attributes' : 'Show Attributes';
|
||||||
|
document.getElementById("opWeight").innerText=op.weights ? 'Hide Weights' : 'Show Weights';
|
||||||
|
document.getElementById("opName").innerText=op.names ? 'Hide Names' : 'Show Names';
|
||||||
|
document.getElementById("opDir").innerText=op.direction == 'vertical' ? 'Show Horizontal' : 'Show Vertical';
|
||||||
|
document.getElementById("opMouse").innerText=op.mousewheel == 'scroll' ? 'Mouse Wheel: Zoom' : 'Mouse Wheel: Scroll';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,726 @@
|
||||||
|
const base = {};
|
||||||
|
|
||||||
|
base.Int64 = class Int64 {
|
||||||
|
|
||||||
|
constructor(low, high) {
|
||||||
|
this.low = low | 0;
|
||||||
|
this.high = high | 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static create(value) {
|
||||||
|
if (isNaN(value)) {
|
||||||
|
return base.Int64.zero;
|
||||||
|
}
|
||||||
|
if (value <= -9223372036854776000) {
|
||||||
|
return base.Int64.min;
|
||||||
|
}
|
||||||
|
if (value + 1 >= 9223372036854776000) {
|
||||||
|
return base.Int64.max;
|
||||||
|
}
|
||||||
|
if (value < 0) {
|
||||||
|
return base.Int64.create(-value).negate();
|
||||||
|
}
|
||||||
|
return new base.Int64((value % 4294967296) | 0, (value / 4294967296));
|
||||||
|
}
|
||||||
|
|
||||||
|
get isZero() {
|
||||||
|
return this.low === 0 && this.high === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isNegative() {
|
||||||
|
return this.high < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
negate() {
|
||||||
|
if (this.equals(base.Int64.min)) {
|
||||||
|
return base.Int64.min;
|
||||||
|
}
|
||||||
|
return this.not().add(base.Int64.one);
|
||||||
|
}
|
||||||
|
|
||||||
|
not() {
|
||||||
|
return new base.Int64(~this.low, ~this.high);
|
||||||
|
}
|
||||||
|
|
||||||
|
equals(other) {
|
||||||
|
if (!(other instanceof base.Int64) && (this.high >>> 31) === 1 && (other.high >>> 31) === 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.high === other.high && this.low === other.low;
|
||||||
|
}
|
||||||
|
|
||||||
|
compare(other) {
|
||||||
|
if (this.equals(other)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const thisNeg = this.isNegative;
|
||||||
|
const otherNeg = other.isNegative;
|
||||||
|
if (thisNeg && !otherNeg) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!thisNeg && otherNeg) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return this.subtract(other).isNegative ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
add(other) {
|
||||||
|
return base.Utility.add(this, other, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
subtract(other) {
|
||||||
|
return base.Utility.subtract(this, other, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
multiply(other) {
|
||||||
|
return base.Utility.multiply(this, other, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
divide(other) {
|
||||||
|
return base.Utility.divide(this, other, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
toInteger() {
|
||||||
|
return this.low;
|
||||||
|
}
|
||||||
|
|
||||||
|
toNumber() {
|
||||||
|
if (this.high === 0) {
|
||||||
|
return this.low >>> 0;
|
||||||
|
}
|
||||||
|
if (this.high === -1) {
|
||||||
|
return this.low;
|
||||||
|
}
|
||||||
|
return (this.high * 4294967296) + (this.low >>> 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
toString(radix) {
|
||||||
|
const r = radix || 10;
|
||||||
|
if (r < 2 || r > 16) {
|
||||||
|
throw new RangeError('radix');
|
||||||
|
}
|
||||||
|
if (this.isZero) {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
if (this.high < 0) {
|
||||||
|
if (this.equals(base.Int64.min)) {
|
||||||
|
const radix = new base.Int64(r, 0);
|
||||||
|
const div = this.divide(radix);
|
||||||
|
const remainder = div.multiply(radix).subtract(this);
|
||||||
|
return div.toString(radix) + (remainder.low >>> 0).toString(radix);
|
||||||
|
}
|
||||||
|
return '-' + this.negate().toString(r);
|
||||||
|
}
|
||||||
|
if (this.high === 0) {
|
||||||
|
return this.low.toString(radix);
|
||||||
|
}
|
||||||
|
return base.Utility.text(this, false, r);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
base.Int64.min = new base.Int64(0, -2147483648);
|
||||||
|
base.Int64.zero = new base.Int64(0, 0);
|
||||||
|
base.Int64.one = new base.Int64(1, 0);
|
||||||
|
base.Int64.negativeOne = new base.Int64(-1, 0);
|
||||||
|
base.Int64.power24 = new base.Int64(1 << 24, 0);
|
||||||
|
base.Int64.max = new base.Int64(0, 2147483647);
|
||||||
|
|
||||||
|
base.Uint64 = class Uint64 {
|
||||||
|
|
||||||
|
constructor(low, high) {
|
||||||
|
this.low = low | 0;
|
||||||
|
this.high = high | 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static create(value) {
|
||||||
|
if (isNaN(value)) {
|
||||||
|
return base.Uint64.zero;
|
||||||
|
}
|
||||||
|
if (value < 0) {
|
||||||
|
return base.Uint64.zero;
|
||||||
|
}
|
||||||
|
if (value >= 18446744073709552000) {
|
||||||
|
return base.Uint64.max;
|
||||||
|
}
|
||||||
|
if (value < 0) {
|
||||||
|
return base.Uint64.create(-value).negate();
|
||||||
|
}
|
||||||
|
return new base.Uint64((value % 4294967296) | 0, (value / 4294967296));
|
||||||
|
}
|
||||||
|
|
||||||
|
get isZero() {
|
||||||
|
return this.low === 0 && this.high === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isNegative() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
negate() {
|
||||||
|
return this.not().add(base.Int64.one);
|
||||||
|
}
|
||||||
|
|
||||||
|
not() {
|
||||||
|
return new base.Uint64(~this.low, ~this.high);
|
||||||
|
}
|
||||||
|
|
||||||
|
equals(other) {
|
||||||
|
if (!(other instanceof base.Uint64) && (this.high >>> 31) === 1 && (other.high >>> 31) === 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.high === other.high && this.low === other.low;
|
||||||
|
}
|
||||||
|
|
||||||
|
compare(other) {
|
||||||
|
if (this.equals(other)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const thisNeg = this.isNegative;
|
||||||
|
const otherNeg = other.isNegative;
|
||||||
|
if (thisNeg && !otherNeg) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!thisNeg && otherNeg) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return (other.high >>> 0) > (this.high >>> 0) || (other.high === this.high && (other.low >>> 0) > (this.low >>> 0)) ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
add(other) {
|
||||||
|
return base.Utility.add(this, other, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
subtract(other) {
|
||||||
|
return base.Utility.subtract(this, other, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
multiply(other) {
|
||||||
|
return base.Utility.multiply(this, other, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
divide(other) {
|
||||||
|
return base.Utility.divide(this, other, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
toInteger() {
|
||||||
|
return this.low >>> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
toNumber() {
|
||||||
|
if (this.high === 0) {
|
||||||
|
return this.low >>> 0;
|
||||||
|
}
|
||||||
|
return ((this.high >>> 0) * 4294967296) + (this.low >>> 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
toString(radix) {
|
||||||
|
const r = radix || 10;
|
||||||
|
if (r < 2 || 36 < r) {
|
||||||
|
throw new RangeError('radix');
|
||||||
|
}
|
||||||
|
if (this.isZero) {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
if (this.high === 0) {
|
||||||
|
return this.low.toString(radix);
|
||||||
|
}
|
||||||
|
return base.Utility.text(this, true, r);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
base.Utility = class {
|
||||||
|
|
||||||
|
static add(a, b, unsigned) {
|
||||||
|
const a48 = a.high >>> 16;
|
||||||
|
const a32 = a.high & 0xFFFF;
|
||||||
|
const a16 = a.low >>> 16;
|
||||||
|
const a00 = a.low & 0xFFFF;
|
||||||
|
const b48 = b.high >>> 16;
|
||||||
|
const b32 = b.high & 0xFFFF;
|
||||||
|
const b16 = b.low >>> 16;
|
||||||
|
const b00 = b.low & 0xFFFF;
|
||||||
|
let c48 = 0;
|
||||||
|
let c32 = 0;
|
||||||
|
let c16 = 0;
|
||||||
|
let c00 = 0;
|
||||||
|
c00 += a00 + b00;
|
||||||
|
c16 += c00 >>> 16;
|
||||||
|
c00 &= 0xFFFF;
|
||||||
|
c16 += a16 + b16;
|
||||||
|
c32 += c16 >>> 16;
|
||||||
|
c16 &= 0xFFFF;
|
||||||
|
c32 += a32 + b32;
|
||||||
|
c48 += c32 >>> 16;
|
||||||
|
c32 &= 0xFFFF;
|
||||||
|
c48 += a48 + b48;
|
||||||
|
c48 &= 0xFFFF;
|
||||||
|
return base.Utility._create((c16 << 16) | c00, (c48 << 16) | c32, unsigned);
|
||||||
|
}
|
||||||
|
|
||||||
|
static subtract(a, b, unsigned) {
|
||||||
|
return base.Utility.add(a, b.negate(), unsigned);
|
||||||
|
}
|
||||||
|
|
||||||
|
static multiply(a, b, unsigned) {
|
||||||
|
if (a.isZero) {
|
||||||
|
return base.Int64.zero;
|
||||||
|
}
|
||||||
|
if (b.isZero) {
|
||||||
|
return base.Int64.zero;
|
||||||
|
}
|
||||||
|
if (a.equals(base.Int64.min)) {
|
||||||
|
return b.isOdd() ? base.Int64.min : base.Int64.zero;
|
||||||
|
}
|
||||||
|
if (b.equals(base.Int64.min)) {
|
||||||
|
return a.isOdd() ? base.Int64.min : base.Int64.zero;
|
||||||
|
}
|
||||||
|
if (a.isNegative) {
|
||||||
|
if (b.isNegative) {
|
||||||
|
return a.negate().multiply(b.negate());
|
||||||
|
}
|
||||||
|
return a.negate().multiply(b).negate();
|
||||||
|
} else if (b.isNegative) {
|
||||||
|
return a.multiply(b.negate()).negate();
|
||||||
|
}
|
||||||
|
if (a.compare(base.Int64.power24) < 0 && b.compare(base.Int64.power24) < 0) {
|
||||||
|
return unsigned ? base.Uint64.create(a.toNumber() * b.toNumber()) : base.Int64.create(a.toNumber() * b.toNumber());
|
||||||
|
}
|
||||||
|
const a48 = a.high >>> 16;
|
||||||
|
const a32 = a.high & 0xFFFF;
|
||||||
|
const a16 = a.low >>> 16;
|
||||||
|
const a00 = a.low & 0xFFFF;
|
||||||
|
const b48 = b.high >>> 16;
|
||||||
|
const b32 = b.high & 0xFFFF;
|
||||||
|
const b16 = b.low >>> 16;
|
||||||
|
const b00 = b.low & 0xFFFF;
|
||||||
|
let c48 = 0;
|
||||||
|
let c32 = 0;
|
||||||
|
let c16 = 0;
|
||||||
|
let c00 = 0;
|
||||||
|
c00 += a00 * b00;
|
||||||
|
c16 += c00 >>> 16;
|
||||||
|
c00 &= 0xFFFF;
|
||||||
|
c16 += a16 * b00;
|
||||||
|
c32 += c16 >>> 16;
|
||||||
|
c16 &= 0xFFFF;
|
||||||
|
c16 += a00 * b16;
|
||||||
|
c32 += c16 >>> 16;
|
||||||
|
c16 &= 0xFFFF;
|
||||||
|
c32 += a32 * b00;
|
||||||
|
c48 += c32 >>> 16;
|
||||||
|
c32 &= 0xFFFF;
|
||||||
|
c32 += a16 * b16;
|
||||||
|
c48 += c32 >>> 16;
|
||||||
|
c32 &= 0xFFFF;
|
||||||
|
c32 += a00 * b32;
|
||||||
|
c48 += c32 >>> 16;
|
||||||
|
c32 &= 0xFFFF;
|
||||||
|
c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
|
||||||
|
c48 &= 0xFFFF;
|
||||||
|
return base.Utility._create((c16 << 16) | c00, (c48 << 16) | c32, unsigned);
|
||||||
|
}
|
||||||
|
|
||||||
|
static divide(a, b, unsigned) {
|
||||||
|
if (b.isZero) {
|
||||||
|
throw new Error('Division by zero.');
|
||||||
|
}
|
||||||
|
if (a.isZero) {
|
||||||
|
return unsigned ? base.Uint64.zero : base.Int64.zero;
|
||||||
|
}
|
||||||
|
let approx;
|
||||||
|
let remainder;
|
||||||
|
let result;
|
||||||
|
if (!unsigned) {
|
||||||
|
if (a.equals(base.Int64.min)) {
|
||||||
|
if (b.equals(base.Int64.one) || b.equals(base.Int64.negativeOne)) {
|
||||||
|
return base.Int64.min;
|
||||||
|
} else if (b.equals(base.Int64.min)) {
|
||||||
|
return base.Int64.one;
|
||||||
|
}
|
||||||
|
const half = base.Utility._shiftRight(a, unsigned, 1);
|
||||||
|
const halfDivide = half.divide(b);
|
||||||
|
approx = base.Utility._shiftLeft(halfDivide, halfDivide instanceof base.Uint64, 1);
|
||||||
|
if (approx.equals(base.Int64.zero)) {
|
||||||
|
return b.isNegative ? base.Int64.one : base.Int64.negativeOne;
|
||||||
|
}
|
||||||
|
remainder = a.subtract(b.multiply(approx));
|
||||||
|
result = approx.add(remainder.divide(b));
|
||||||
|
return result;
|
||||||
|
} else if (b.equals(base.Int64.min)) {
|
||||||
|
return base.Int64.zero;
|
||||||
|
}
|
||||||
|
if (a.isNegative) {
|
||||||
|
if (b.isNegative) {
|
||||||
|
return this.negate().divide(b.negate());
|
||||||
|
}
|
||||||
|
return a.negate().divide(b).negate();
|
||||||
|
} else if (b.isNegative) {
|
||||||
|
return a.divide(b.negate()).negate();
|
||||||
|
}
|
||||||
|
result = base.Int64.zero;
|
||||||
|
} else {
|
||||||
|
if (!(b instanceof base.Uint64)) {
|
||||||
|
b = new base.Uint64(b.low, b.high);
|
||||||
|
}
|
||||||
|
if (b.compare(a) > 0) {
|
||||||
|
return base.Int64.zero;
|
||||||
|
}
|
||||||
|
if (b.compare(base.Utility._shiftRight(a, unsigned, 1)) > 0) {
|
||||||
|
return base.Uint64.one;
|
||||||
|
}
|
||||||
|
result = base.Uint64.zero;
|
||||||
|
}
|
||||||
|
remainder = a;
|
||||||
|
while (remainder.compare(b) >= 0) {
|
||||||
|
let approx = Math.max(1, Math.floor(remainder.toNumber() / b.toNumber()));
|
||||||
|
const log2 = Math.ceil(Math.log(approx) / Math.LN2);
|
||||||
|
const delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48);
|
||||||
|
let approxResult = base.Int64.create(approx);
|
||||||
|
let approxRemainder = approxResult.multiply(b);
|
||||||
|
while (approxRemainder.isNegative || approxRemainder.compare(remainder) > 0) {
|
||||||
|
approx -= delta;
|
||||||
|
approxResult = unsigned ? base.Uint64.create(approx) : base.Int64.create(approx);
|
||||||
|
approxRemainder = approxResult.multiply(b);
|
||||||
|
}
|
||||||
|
if (approxResult.isZero) {
|
||||||
|
approxResult = base.Int64.one;
|
||||||
|
}
|
||||||
|
result = result.add(approxResult);
|
||||||
|
remainder = remainder.subtract(approxRemainder);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static text(value, unsigned, radix) {
|
||||||
|
const power = unsigned ? base.Uint64.create(Math.pow(radix, 6)) : base.Int64.create(Math.pow(radix, 6));
|
||||||
|
let remainder = value;
|
||||||
|
let result = '';
|
||||||
|
for (; ;) {
|
||||||
|
const remainderDiv = remainder.divide(power);
|
||||||
|
const intval = remainder.subtract(remainderDiv.multiply(power)).toInteger() >>> 0;
|
||||||
|
let digits = intval.toString(radix);
|
||||||
|
remainder = remainderDiv;
|
||||||
|
if (remainder.low === 0 && remainder.high === 0) {
|
||||||
|
return digits + result;
|
||||||
|
}
|
||||||
|
while (digits.length < 6) {
|
||||||
|
digits = '0' + digits;
|
||||||
|
}
|
||||||
|
result = '' + digits + result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static _shiftLeft(value, unsigned, shift) {
|
||||||
|
return base.Utility._create(value.low << shift, (value.high << shift) | (value.low >>> (32 - shift)), unsigned);
|
||||||
|
}
|
||||||
|
|
||||||
|
static _shiftRight(value, unsigned, shift) {
|
||||||
|
return base.Utility._create((value.low >>> shift) | (value.high << (32 - shift)), value.high >> shift, unsigned);
|
||||||
|
}
|
||||||
|
|
||||||
|
static _create(low, high, unsigned) {
|
||||||
|
return unsigned ? new base.Uint64(low, high) : new base.Int64(low, high);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
base.Uint64.zero = new base.Uint64(0, 0);
|
||||||
|
base.Uint64.one = new base.Uint64(1, 0);
|
||||||
|
base.Uint64.max = new base.Uint64(-1, -1);
|
||||||
|
|
||||||
|
base.Complex64 = class Complex {
|
||||||
|
|
||||||
|
constructor(real, imaginary) {
|
||||||
|
this.real = real;
|
||||||
|
this.imaginary = imaginary;
|
||||||
|
}
|
||||||
|
|
||||||
|
static create(real, imaginary) {
|
||||||
|
return new base.Complex64(real, imaginary);
|
||||||
|
}
|
||||||
|
|
||||||
|
toString(/* radix */) {
|
||||||
|
return this.real + ' + ' + this.imaginary + 'i';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
base.Complex128 = class Complex {
|
||||||
|
|
||||||
|
constructor(real, imaginary) {
|
||||||
|
this.real = real;
|
||||||
|
this.imaginary = imaginary;
|
||||||
|
}
|
||||||
|
|
||||||
|
static create(real, imaginary) {
|
||||||
|
return new base.Complex128(real, imaginary);
|
||||||
|
}
|
||||||
|
|
||||||
|
toString(/* radix */) {
|
||||||
|
return this.real + ' + ' + this.imaginary + 'i';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!DataView.prototype.getFloat16) {
|
||||||
|
DataView.prototype.getFloat16 = function (byteOffset, littleEndian) {
|
||||||
|
const value = this.getUint16(byteOffset, littleEndian);
|
||||||
|
const e = (value & 0x7C00) >> 10;
|
||||||
|
let f = value & 0x03FF;
|
||||||
|
if (e == 0) {
|
||||||
|
f = 0.00006103515625 * (f / 1024);
|
||||||
|
} else if (e == 0x1F) {
|
||||||
|
f = f ? NaN : Infinity;
|
||||||
|
} else {
|
||||||
|
f = DataView.__float16_pow[e] * (1 + (f / 1024));
|
||||||
|
}
|
||||||
|
return value & 0x8000 ? -f : f;
|
||||||
|
};
|
||||||
|
DataView.__float16_pow = {
|
||||||
|
1: 1 / 16384, 2: 1 / 8192, 3: 1 / 4096, 4: 1 / 2048, 5: 1 / 1024, 6: 1 / 512, 7: 1 / 256, 8: 1 / 128,
|
||||||
|
9: 1 / 64, 10: 1 / 32, 11: 1 / 16, 12: 1 / 8, 13: 1 / 4, 14: 1 / 2, 15: 1, 16: 2,
|
||||||
|
17: 4, 18: 8, 19: 16, 20: 32, 21: 64, 22: 128, 23: 256, 24: 512,
|
||||||
|
25: 1024, 26: 2048, 27: 4096, 28: 8192, 29: 16384, 30: 32768, 31: 65536
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DataView.prototype.setFloat16) {
|
||||||
|
DataView.prototype.setFloat16 = function (byteOffset, value, littleEndian) {
|
||||||
|
DataView.__float16_float[0] = value;
|
||||||
|
[value] = DataView.__float16_int;
|
||||||
|
const s = (value >>> 16) & 0x8000;
|
||||||
|
const e = (value >>> 23) & 0xff;
|
||||||
|
const f = value & 0x7fffff;
|
||||||
|
const v = s | DataView.__float16_base[e] | (f >> DataView.__float16_shift[e]);
|
||||||
|
this.setUint16(byteOffset, v, littleEndian);
|
||||||
|
};
|
||||||
|
DataView.__float16_float = new Float32Array(1);
|
||||||
|
DataView.__float16_int = new Uint32Array(DataView.__float16_float.buffer, 0, DataView.__float16_float.length);
|
||||||
|
DataView.__float16_base = new Uint32Array(256);
|
||||||
|
DataView.__float16_shift = new Uint32Array(256);
|
||||||
|
for (let i = 0; i < 256; ++i) {
|
||||||
|
const e = i - 127;
|
||||||
|
if (e < -27) {
|
||||||
|
DataView.__float16_base[i] = 0x0000;
|
||||||
|
DataView.__float16_shift[i] = 24;
|
||||||
|
} else if (e < -14) {
|
||||||
|
DataView.__float16_base[i] = 0x0400 >> -e - 14;
|
||||||
|
DataView.__float16_shift[i] = -e - 1;
|
||||||
|
} else if (e <= 15) {
|
||||||
|
DataView.__float16_base[i] = e + 15 << 10;
|
||||||
|
DataView.__float16_shift[i] = 13;
|
||||||
|
} else if (e < 128) {
|
||||||
|
DataView.__float16_base[i] = 0x7c00;
|
||||||
|
DataView.__float16_shift[i] = 24;
|
||||||
|
} else {
|
||||||
|
DataView.__float16_base[i] = 0x7c00;
|
||||||
|
DataView.__float16_shift[i] = 13;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DataView.prototype.getBfloat16) {
|
||||||
|
DataView.prototype.getBfloat16 = function (byteOffset, littleEndian) {
|
||||||
|
if (littleEndian) {
|
||||||
|
DataView.__bfloat16_get_uint16_le[1] = this.getUint16(byteOffset, littleEndian);
|
||||||
|
return DataView.__bfloat16_get_float32_le[0];
|
||||||
|
}
|
||||||
|
DataView.__bfloat16_uint16_be[0] = this.getUint16(byteOffset, littleEndian);
|
||||||
|
return DataView.__bfloat16_get_float32_be[0];
|
||||||
|
};
|
||||||
|
DataView.__bfloat16_get_float32_le = new Float32Array(1);
|
||||||
|
DataView.__bfloat16_get_float32_be = new Float32Array(1);
|
||||||
|
DataView.__bfloat16_get_uint16_le = new Uint16Array(DataView.__bfloat16_get_float32_le.buffer, DataView.__bfloat16_get_float32_le.byteOffset, 2);
|
||||||
|
DataView.__bfloat16_get_uint16_be = new Uint16Array(DataView.__bfloat16_get_float32_be.buffer, DataView.__bfloat16_get_float32_be.byteOffset, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
DataView.__float8e4m3_float32 = new Float32Array(1);
|
||||||
|
DataView.__float8e4m3_uint32 = new Uint32Array(DataView.__float8e4m3_float32.buffer, DataView.__float8e4m3_float32.byteOffset, 1);
|
||||||
|
DataView.prototype.getFloat8e4m3 = function (byteOffset, fn, uz) {
|
||||||
|
const value = this.getUint8(byteOffset);
|
||||||
|
let exponent_bias = 7;
|
||||||
|
if (uz) {
|
||||||
|
exponent_bias = 8;
|
||||||
|
if (value == 0x80) {
|
||||||
|
return NaN;
|
||||||
|
}
|
||||||
|
} else if (value === 255) {
|
||||||
|
return -NaN;
|
||||||
|
} else if (value === 0x7f) {
|
||||||
|
return NaN;
|
||||||
|
}
|
||||||
|
let expo = (value & 0x78) >> 3;
|
||||||
|
let mant = value & 0x07;
|
||||||
|
const sign = value & 0x80;
|
||||||
|
let res = sign << 24;
|
||||||
|
if (expo == 0) {
|
||||||
|
if (mant > 0) {
|
||||||
|
expo = 0x7F - exponent_bias;
|
||||||
|
if (mant & 0x4 == 0) {
|
||||||
|
mant &= 0x3;
|
||||||
|
mant <<= 1;
|
||||||
|
expo -= 1;
|
||||||
|
}
|
||||||
|
if (mant & 0x4 == 0) {
|
||||||
|
mant &= 0x3;
|
||||||
|
mant <<= 1;
|
||||||
|
expo -= 1;
|
||||||
|
}
|
||||||
|
res |= (mant & 0x3) << 21;
|
||||||
|
res |= expo << 23;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res |= mant << 20;
|
||||||
|
expo += 0x7F - exponent_bias;
|
||||||
|
res |= expo << 23;
|
||||||
|
}
|
||||||
|
DataView.__float8e4m3_uint32[0] = res;
|
||||||
|
return DataView.__float8e4m3_float32[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.__float8e5m2_float32 = new Float32Array(1);
|
||||||
|
DataView.__float8e5m2_uint32 = new Uint32Array(DataView.__float8e5m2_float32.buffer, DataView.__float8e5m2_float32.byteOffset, 1);
|
||||||
|
DataView.prototype.getFloat8e5m2 = function (byteOffset, fn, uz) {
|
||||||
|
const value = this.getUint8(byteOffset);
|
||||||
|
let exponent_bias = NaN;
|
||||||
|
if (fn && uz) {
|
||||||
|
if (value == 0x80) {
|
||||||
|
return NaN;
|
||||||
|
}
|
||||||
|
exponent_bias = 16;
|
||||||
|
} else if (!fn && !uz) {
|
||||||
|
if (value >= 253 && value <= 255) {
|
||||||
|
return -NaN;
|
||||||
|
}
|
||||||
|
if (value >= 126 && value <= 127) {
|
||||||
|
return NaN;
|
||||||
|
}
|
||||||
|
if (value === 252) {
|
||||||
|
return -Infinity;
|
||||||
|
}
|
||||||
|
if (value === 124) {
|
||||||
|
return Infinity;
|
||||||
|
}
|
||||||
|
exponent_bias = 15;
|
||||||
|
}
|
||||||
|
let expo = (value & 0x7C) >> 2;
|
||||||
|
let mant = value & 0x03;
|
||||||
|
let res = (value & 0x80) << 24;
|
||||||
|
if (expo == 0) {
|
||||||
|
if (mant > 0) {
|
||||||
|
expo = 0x7F - exponent_bias;
|
||||||
|
if (mant & 0x2 == 0) {
|
||||||
|
mant &= 0x1;
|
||||||
|
mant <<= 1;
|
||||||
|
expo -= 1;
|
||||||
|
}
|
||||||
|
res |= (mant & 0x1) << 22;
|
||||||
|
res |= expo << 23;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res |= mant << 21;
|
||||||
|
expo += 0x7F - exponent_bias;
|
||||||
|
res |= expo << 23;
|
||||||
|
}
|
||||||
|
DataView.__float8e5m2_uint32[0] = res;
|
||||||
|
return DataView.__float8e5m2_float32[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.getInt64 = DataView.prototype.getInt64 || function (byteOffset, littleEndian) {
|
||||||
|
return littleEndian ?
|
||||||
|
new base.Int64(this.getUint32(byteOffset, true), this.getUint32(byteOffset + 4, true)) :
|
||||||
|
new base.Int64(this.getUint32(byteOffset + 4, true), this.getUint32(byteOffset, true));
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.setInt64 = DataView.prototype.setInt64 || function (byteOffset, value, littleEndian) {
|
||||||
|
if (littleEndian) {
|
||||||
|
this.setUint32(byteOffset, value.low, true);
|
||||||
|
this.setUint32(byteOffset + 4, value.high, true);
|
||||||
|
} else {
|
||||||
|
this.setUint32(byteOffset + 4, value.low, false);
|
||||||
|
this.setUint32(byteOffset, value.high, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.getIntBits = DataView.prototype.getUintBits || function (offset, bits) {
|
||||||
|
offset = offset * bits;
|
||||||
|
const available = (this.byteLength << 3) - offset;
|
||||||
|
if (bits > available) {
|
||||||
|
throw new RangeError("Invalid bit size '" + bits + "'.");
|
||||||
|
}
|
||||||
|
let value = 0;
|
||||||
|
let index = 0;
|
||||||
|
while (index < bits) {
|
||||||
|
const remainder = offset & 7;
|
||||||
|
const size = Math.min(bits - index, 8 - remainder);
|
||||||
|
value <<= size;
|
||||||
|
value |= (this.getUint8(offset >> 3) >> (8 - size - remainder)) & ~(0xff << size);
|
||||||
|
offset += size;
|
||||||
|
index += size;
|
||||||
|
}
|
||||||
|
return (value < (2 << (bits - 1)) ? value : (2 << bits));
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.getUint64 = DataView.prototype.getUint64 || function (byteOffset, littleEndian) {
|
||||||
|
return littleEndian ?
|
||||||
|
new base.Uint64(this.getUint32(byteOffset, true), this.getUint32(byteOffset + 4, true)) :
|
||||||
|
new base.Uint64(this.getUint32(byteOffset + 4, true), this.getUint32(byteOffset, true));
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.setUint64 = DataView.prototype.setUint64 || function (byteOffset, value, littleEndian) {
|
||||||
|
if (littleEndian) {
|
||||||
|
this.setUint32(byteOffset, value.low, true);
|
||||||
|
this.setUint32(byteOffset + 4, value.high, true);
|
||||||
|
} else {
|
||||||
|
this.setUint32(byteOffset + 4, value.low, false);
|
||||||
|
this.setUint32(byteOffset, value.high, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.getUintBits = DataView.prototype.getUintBits || function (offset, bits) {
|
||||||
|
offset = offset * bits;
|
||||||
|
const available = (this.byteLength << 3) - offset;
|
||||||
|
if (bits > available) {
|
||||||
|
throw new RangeError("Invalid bit size '" + bits + "'.");
|
||||||
|
}
|
||||||
|
let value = 0;
|
||||||
|
let index = 0;
|
||||||
|
while (index < bits) {
|
||||||
|
const remainder = offset & 7;
|
||||||
|
const size = Math.min(bits - index, 8 - remainder);
|
||||||
|
value <<= size;
|
||||||
|
value |= (this.getUint8(offset >> 3) >> (8 - size - remainder)) & ~(0xff << size);
|
||||||
|
offset += size;
|
||||||
|
index += size;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.getComplex64 = DataView.prototype.getComplex64 || function (byteOffset, littleEndian) {
|
||||||
|
const real = littleEndian ? this.getFloat32(byteOffset, littleEndian) : this.getFloat32(byteOffset + 4, littleEndian);
|
||||||
|
const imaginary = littleEndian ? this.getFloat32(byteOffset + 4, littleEndian) : this.getFloat32(byteOffset, littleEndian);
|
||||||
|
return base.Complex64.create(real, imaginary);
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.setComplex64 = DataView.prototype.setComplex64 || function (byteOffset, value, littleEndian) {
|
||||||
|
if (littleEndian) {
|
||||||
|
this.setFloat32(byteOffset, value.real, littleEndian);
|
||||||
|
this.setFloat32(byteOffset + 4, value.imaginary, littleEndian);
|
||||||
|
} else {
|
||||||
|
this.setFloat32(byteOffset + 4, value.real, littleEndian);
|
||||||
|
this.setFloat32(byteOffset, value.imaginary, littleEndian);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.getComplex128 = DataView.prototype.getComplex128 || function (byteOffset, littleEndian) {
|
||||||
|
const real = littleEndian ? this.getFloat64(byteOffset, littleEndian) : this.getFloat64(byteOffset + 8, littleEndian);
|
||||||
|
const imaginary = littleEndian ? this.getFloat64(byteOffset + 8, littleEndian) : this.getFloat64(byteOffset, littleEndian);
|
||||||
|
return base.Complex128.create(real, imaginary);
|
||||||
|
};
|
||||||
|
|
||||||
|
DataView.prototype.setComplex128 = DataView.prototype.setComplex128 || function (byteOffset, value, littleEndian) {
|
||||||
|
if (littleEndian) {
|
||||||
|
this.setFloat64(byteOffset, value.real, littleEndian);
|
||||||
|
this.setFloat64(byteOffset + 8, value.imaginary, littleEndian);
|
||||||
|
} else {
|
||||||
|
this.setFloat64(byteOffset + 8, value.real, littleEndian);
|
||||||
|
this.setFloat64(byteOffset, value.imaginary, littleEndian);
|
||||||
|
}
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,142 @@
|
||||||
|
/* this file is from https://github.com/lutzroeder/netron/blob/main/source/grapher.css */
|
||||||
|
.node path { stroke: #333; fill: none; stroke-width: 1px; }
|
||||||
|
.node line { stroke: #333; fill: none; stroke-width: 1px; }
|
||||||
|
|
||||||
|
.node-item path { stroke-width: 0; stroke: #000; fill: #fff; }
|
||||||
|
.node-item text { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; font-size: 11px; text-rendering: geometricPrecision; user-select: none; }
|
||||||
|
|
||||||
|
.node-item-function path { fill: #fff; }
|
||||||
|
.node-item-function text { fill: #000; }
|
||||||
|
.node-item-function:hover { cursor: pointer; }
|
||||||
|
.node-item-function:hover path { fill: #eee; }
|
||||||
|
|
||||||
|
.node-item-type path { fill: #000; }
|
||||||
|
.node-item-type text { fill: #fff; }
|
||||||
|
.node-item-type:hover { cursor: pointer; }
|
||||||
|
.node-item-type:hover path { fill: #fff; }
|
||||||
|
.node-item-type:hover text { fill: #000; }
|
||||||
|
|
||||||
|
.node-item-type-constant path { fill: #eee; }
|
||||||
|
.node-item-type-constant text { fill: #000; }
|
||||||
|
.node-item-type-constant:hover path { fill: #fff; }
|
||||||
|
|
||||||
|
.node-item-type-control path { fill: #eee; }
|
||||||
|
.node-item-type-control text { fill: #000; }
|
||||||
|
.node-item-type-control:hover path { fill: #fff; }
|
||||||
|
|
||||||
|
.node-item-type-layer path { fill: rgb(51, 85, 136); }
|
||||||
|
.node-item-type-wrapper path { fill: rgb(238, 238, 238); }
|
||||||
|
.node-item-type-wrapper text { fill: rgb(0, 0, 0) }
|
||||||
|
.node-item-type-activation path { fill: rgb(112, 41, 33); }
|
||||||
|
.node-item-type-pool path { fill: rgb(51, 85, 51); }
|
||||||
|
.node-item-type-normalization path { fill: rgb(51, 85, 68); }
|
||||||
|
.node-item-type-dropout path { fill: rgb(69, 71, 112); }
|
||||||
|
.node-item-type-shape path { fill: rgb(108, 79, 71); }
|
||||||
|
.node-item-type-tensor path { fill: rgb(89, 66, 59); }
|
||||||
|
.node-item-type-transform path { fill: rgb(51, 85, 68); }
|
||||||
|
.node-item-type-data path { fill: rgb(85, 85, 85); }
|
||||||
|
.node-item-type-quantization path { fill: rgb(80, 40, 0); }
|
||||||
|
.node-item-type-custom path { fill: rgb(128, 128, 128); }
|
||||||
|
|
||||||
|
.node-item-input path { fill: #fff; }
|
||||||
|
.node-item-input:hover { cursor: pointer; }
|
||||||
|
.node-item-input:hover path { fill: #fff; }
|
||||||
|
|
||||||
|
.node-item-constant path { fill: #eee; }
|
||||||
|
.node-item-constant:hover { cursor: pointer; }
|
||||||
|
.node-item-constant:hover path { fill: #fff; }
|
||||||
|
|
||||||
|
.node-item-undefined path { fill: #f00; }
|
||||||
|
.node-item-undefined:hover { cursor: pointer; }
|
||||||
|
.node-item-undefined:hover path { fill: #fff; }
|
||||||
|
|
||||||
|
.node-attribute-list > path { fill: #fff; stroke-width: 0; stroke: #000; }
|
||||||
|
.node-attribute-list:hover { cursor: pointer; }
|
||||||
|
.node-attribute-list:hover > path { fill: #f6f6f6; }
|
||||||
|
.node-attribute > text { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; font-size: 9px; font-weight: normal; text-rendering: geometricPrecision; user-select: none; }
|
||||||
|
|
||||||
|
.graph-item-input path { fill: #eee; }
|
||||||
|
.graph-item-input:hover { cursor: pointer; }
|
||||||
|
.graph-item-input:hover path { fill: #fff; }
|
||||||
|
|
||||||
|
.graph-item-output path { fill: #eee; }
|
||||||
|
.graph-item-output:hover { cursor: pointer; }
|
||||||
|
.graph-item-output:hover path { fill: #fff; }
|
||||||
|
|
||||||
|
#arrowhead { fill: #000; }
|
||||||
|
#arrowhead-select { fill: #e00; }
|
||||||
|
|
||||||
|
.edge-path { stroke: #000; stroke-width: 1px; fill: none; marker-end: url("#arrowhead"); }
|
||||||
|
.edge-path-hit-test { pointer-events: stroke; stroke-width: 0.5em; fill: none; stroke: #000; stroke-opacity: 0.001; }
|
||||||
|
|
||||||
|
.select > .node.node-border { stroke: #e00; stroke-width: 2px; }
|
||||||
|
.select.edge-path { stroke: #e00; stroke-width: 1px; marker-end: url("#arrowhead-select"); }
|
||||||
|
|
||||||
|
.edge-label { font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "PingFang SC"; font-size: 10px; }
|
||||||
|
.edge-path-control-dependency { stroke-dasharray: 3, 2; }
|
||||||
|
|
||||||
|
.cluster rect { stroke: #000; fill: #000; fill-opacity: 0.02; stroke-opacity: 0.06; stroke-width: 1px; }
|
||||||
|
|
||||||
|
@keyframes pulse { from { stroke-dashoffset: 100px; } to { stroke-dashoffset: 0; } }
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
|
||||||
|
.edge-path { stroke: #888; }
|
||||||
|
|
||||||
|
.node path { stroke: #1d1d1d; }
|
||||||
|
.node line { stroke: #1d1d1d; }
|
||||||
|
|
||||||
|
.select > .node.node-border { stroke: #b00; }
|
||||||
|
.select.edge-path { stroke: #b00; }
|
||||||
|
|
||||||
|
#arrowhead { fill: #888; }
|
||||||
|
#arrowhead-hover { fill: #b00; }
|
||||||
|
#arrowhead-select { fill: #b00 }
|
||||||
|
|
||||||
|
.edge-label { fill: #b2b2b2; }
|
||||||
|
|
||||||
|
.node-item-function path { fill: #404040; }
|
||||||
|
.node-item-function text { fill: #dfdfdfdf; }
|
||||||
|
.node-item-function:hover { cursor: pointer; }
|
||||||
|
.node-item-function:hover path { fill: #666666; }
|
||||||
|
|
||||||
|
.node-item-type path { fill: #303030; }
|
||||||
|
.node-item-type text { fill: #dfdfdf; }
|
||||||
|
.node-item-type:hover { cursor: pointer; }
|
||||||
|
.node-item-type:hover path { fill: #808080; }
|
||||||
|
.node-item-type:hover text { fill: #dfdfdf; }
|
||||||
|
|
||||||
|
.node-item path { stroke: #fff; }
|
||||||
|
.node-item text { fill: #dfdfdf; }
|
||||||
|
|
||||||
|
.node-attribute > text { fill: #b2b2b2; }
|
||||||
|
.node-attribute-list > path { fill: #2d2d2d; }
|
||||||
|
.node-attribute-list:hover > path { fill: #666666; }
|
||||||
|
|
||||||
|
.graph-item-input path { fill: #404040; }
|
||||||
|
.graph-item-input:hover { cursor: pointer; }
|
||||||
|
.graph-item-input:hover path { fill: #666666; }
|
||||||
|
|
||||||
|
.graph-item-output path { fill: #404040; }
|
||||||
|
.graph-item-output:hover { cursor: pointer; }
|
||||||
|
.graph-item-output:hover path { fill: #666666; }
|
||||||
|
|
||||||
|
.node-item-input path { fill: #404040; }
|
||||||
|
.node-item-input:hover path { fill: #666666; }
|
||||||
|
.node-item-constant path { fill: #4b4b4b; }
|
||||||
|
.node-item-constant:hover path { fill: #666666; }
|
||||||
|
|
||||||
|
.node-item-type-layer path { fill: rgba(51, 85, 136, 0.7); }
|
||||||
|
.node-item-type-activation path { fill: rgba(75, 27, 22, 0.7); }
|
||||||
|
.node-item-type-activation path { fill: rgba(75, 27, 22, 0.7); }
|
||||||
|
.node-item-type-pool path { fill: rgba(51, 85, 51, 0.7); }
|
||||||
|
.node-item-type-pool path { fill: rgba(51, 85, 51, 0.7); }
|
||||||
|
.node-item-type-normalization path { fill: rgba(51, 85, 68, 0.7); }
|
||||||
|
.node-item-type-dropout path { fill: rgba(69, 71, 112, 0.7); }
|
||||||
|
.node-item-type-shape path { fill: rgba(108, 79, 71, 0.7); }
|
||||||
|
.node-item-type-tensor path { fill: rgba(89, 66, 59, 0.7); }
|
||||||
|
.node-item-type-transform path { fill: rgba(51, 85, 68, 0.7); }
|
||||||
|
.node-item-type-data path { fill: rgba(85, 85, 85, 0.7); }
|
||||||
|
.node-item-type-quantization path { fill: rgb(80, 40, 0, 0.7); }
|
||||||
|
.node-item-type-custom path { fill: rgb(64, 64, 64, 0.7); }
|
||||||
|
}
|
|
@ -0,0 +1,885 @@
|
||||||
|
// this file is from https://github.com/lutzroeder/netron/blob/main/source/grapher.js
|
||||||
|
var grapher = grapher || {};
|
||||||
|
var dagre = window.dagre;
|
||||||
|
|
||||||
|
grapher.Graph = class {
|
||||||
|
|
||||||
|
constructor(compound, layout) {
|
||||||
|
this._layout = layout;
|
||||||
|
this._isCompound = compound;
|
||||||
|
this._nodes = new Map();
|
||||||
|
this._edges = new Map();
|
||||||
|
this._children = {};
|
||||||
|
this._children['\x00'] = {};
|
||||||
|
this._parent = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
setNode(node) {
|
||||||
|
const key = node.name;
|
||||||
|
const value = this._nodes.get(key);
|
||||||
|
if (value) {
|
||||||
|
value.label = node;
|
||||||
|
} else {
|
||||||
|
this._nodes.set(key, { v: key, label: node });
|
||||||
|
if (this._isCompound) {
|
||||||
|
this._parent[key] = '\x00';
|
||||||
|
this._children[key] = {};
|
||||||
|
this._children['\x00'][key] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setEdge(edge) {
|
||||||
|
if (!this._nodes.has(edge.v)) {
|
||||||
|
throw new grapher.Error("Invalid edge '" + JSON.stringify(edge.v) + "'.");
|
||||||
|
}
|
||||||
|
if (!this._nodes.has(edge.w)) {
|
||||||
|
throw new grapher.Error("Invalid edge '" + JSON.stringify(edge.w) + "'.");
|
||||||
|
}
|
||||||
|
const key = edge.v + ':' + edge.w;
|
||||||
|
if (!this._edges.has(key)) {
|
||||||
|
this._edges.set(key, { v: edge.v, w: edge.w, label: edge });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setParent(node, parent) {
|
||||||
|
if (!this._isCompound) {
|
||||||
|
throw new Error("Cannot set parent in a non-compound graph");
|
||||||
|
}
|
||||||
|
parent += "";
|
||||||
|
for (let ancestor = parent; ancestor; ancestor = this.parent(ancestor)) {
|
||||||
|
if (ancestor === node) {
|
||||||
|
throw new Error("Setting " + parent + " as parent of " + node + " would create a cycle");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete this._children[this._parent[node]][node];
|
||||||
|
this._parent[node] = parent;
|
||||||
|
this._children[parent][node] = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
get nodes() {
|
||||||
|
return this._nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasNode(key) {
|
||||||
|
return this._nodes.has(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
node(key) {
|
||||||
|
return this._nodes.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
get edges() {
|
||||||
|
return this._edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent(key) {
|
||||||
|
if (this._isCompound) {
|
||||||
|
const parent = this._parent[key];
|
||||||
|
if (parent !== '\x00') {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
children(key) {
|
||||||
|
key = key === undefined ? '\x00' : key;
|
||||||
|
if (this._isCompound) {
|
||||||
|
const children = this._children[key];
|
||||||
|
if (children) {
|
||||||
|
return Object.keys(children);
|
||||||
|
}
|
||||||
|
} else if (key === '\x00') {
|
||||||
|
return this.nodes.keys();
|
||||||
|
} else if (this.hasNode(key)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
build(document, origin) {
|
||||||
|
const createGroup = (name) => {
|
||||||
|
const element = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||||
|
element.setAttribute('id', name);
|
||||||
|
element.setAttribute('class', name);
|
||||||
|
origin.appendChild(element);
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
|
||||||
|
const clusterGroup = createGroup('clusters');
|
||||||
|
const edgePathGroup = createGroup('edge-paths');
|
||||||
|
const edgeLabelGroup = createGroup('edge-labels');
|
||||||
|
const nodeGroup = createGroup('nodes');
|
||||||
|
|
||||||
|
const edgePathGroupDefs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
|
||||||
|
edgePathGroup.appendChild(edgePathGroupDefs);
|
||||||
|
const marker = (id) => {
|
||||||
|
const element = document.createElementNS('http://www.w3.org/2000/svg', 'marker');
|
||||||
|
element.setAttribute('id', id);
|
||||||
|
element.setAttribute('viewBox', '0 0 10 10');
|
||||||
|
element.setAttribute('refX', 9);
|
||||||
|
element.setAttribute('refY', 5);
|
||||||
|
element.setAttribute('markerUnits', 'strokeWidth');
|
||||||
|
element.setAttribute('markerWidth', 8);
|
||||||
|
element.setAttribute('markerHeight', 6);
|
||||||
|
element.setAttribute('orient', 'auto');
|
||||||
|
const markerPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||||
|
markerPath.setAttribute('d', 'M 0 0 L 10 5 L 0 10 L 4 5 z');
|
||||||
|
markerPath.style.setProperty('stroke-width', 1);
|
||||||
|
element.appendChild(markerPath);
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
edgePathGroupDefs.appendChild(marker("arrowhead"));
|
||||||
|
edgePathGroupDefs.appendChild(marker("arrowhead-select"));
|
||||||
|
edgePathGroupDefs.appendChild(marker("arrowhead-hover"));
|
||||||
|
for (const nodeId of this.nodes.keys()) {
|
||||||
|
const entry = this.node(nodeId);
|
||||||
|
const node = entry.label;
|
||||||
|
if (this.children(nodeId).length == 0) {
|
||||||
|
node.build(document, nodeGroup);
|
||||||
|
} else {
|
||||||
|
// cluster
|
||||||
|
node.rectangle = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||||
|
if (node.rx) {
|
||||||
|
node.rectangle.setAttribute('rx', entry.rx);
|
||||||
|
}
|
||||||
|
if (node.ry) {
|
||||||
|
node.rectangle.setAttribute('ry', entry.ry);
|
||||||
|
}
|
||||||
|
node.element = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||||
|
node.element.setAttribute('class', 'cluster');
|
||||||
|
node.element.appendChild(node.rectangle);
|
||||||
|
clusterGroup.appendChild(node.element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const edge of this.edges.values()) {
|
||||||
|
edge.label.build(document, edgePathGroup, edgeLabelGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
measure() {
|
||||||
|
for (const key of this.nodes.keys()) {
|
||||||
|
const entry = this.node(key);
|
||||||
|
if (this.children(key).length == 0) {
|
||||||
|
const node = entry.label;
|
||||||
|
node.measure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
layout() {
|
||||||
|
dagre.layout(this, this._layout);
|
||||||
|
for (const key of this.nodes.keys()) {
|
||||||
|
const entry = this.node(key);
|
||||||
|
if (this.children(key).length == 0) {
|
||||||
|
const node = entry.label;
|
||||||
|
node.layout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
for (const nodeId of this.nodes.keys()) {
|
||||||
|
if (this.children(nodeId).length == 0) {
|
||||||
|
// node
|
||||||
|
const entry = this.node(nodeId);
|
||||||
|
const node = entry.label;
|
||||||
|
node.update();
|
||||||
|
} else {
|
||||||
|
// cluster
|
||||||
|
const entry = this.node(nodeId);
|
||||||
|
const node = entry.label;
|
||||||
|
node.element.setAttribute('transform', 'translate(' + node.x + ',' + node.y + ')');
|
||||||
|
node.rectangle.setAttribute('x', - node.width / 2);
|
||||||
|
node.rectangle.setAttribute('y', - node.height / 2);
|
||||||
|
node.rectangle.setAttribute('width', node.width);
|
||||||
|
node.rectangle.setAttribute('height', node.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const edge of this.edges.values()) {
|
||||||
|
edge.label.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
grapher.Node = class {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._blocks = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
header() {
|
||||||
|
const block = new grapher.Node.Header();
|
||||||
|
this._blocks.push(block);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
list() {
|
||||||
|
const block = new grapher.Node.List();
|
||||||
|
this._blocks.push(block);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas() {
|
||||||
|
const block = new grapher.Node.Canvas();
|
||||||
|
this._blocks.push(block);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
build(document, parent) {
|
||||||
|
this.element = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||||
|
if (this.id) {
|
||||||
|
this.element.setAttribute('id', this.id);
|
||||||
|
}
|
||||||
|
this.element.setAttribute('class', this.class ? 'node ' + this.class : 'node');
|
||||||
|
this.element.style.opacity = 0;
|
||||||
|
parent.appendChild(this.element);
|
||||||
|
this.border = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||||
|
this.border.setAttribute('class', 'node node-border');
|
||||||
|
for (let i = 0; i < this._blocks.length; i++) {
|
||||||
|
const block = this._blocks[i];
|
||||||
|
block.first = i === 0;
|
||||||
|
block.last = i === this._blocks.length - 1;
|
||||||
|
block.build(document, this.element);
|
||||||
|
}
|
||||||
|
this.element.appendChild(this.border);
|
||||||
|
}
|
||||||
|
|
||||||
|
measure() {
|
||||||
|
this.height = 0;
|
||||||
|
for (const block of this._blocks) {
|
||||||
|
block.measure();
|
||||||
|
this.height = this.height + block.height;
|
||||||
|
}
|
||||||
|
this.width = Math.max(...this._blocks.map((block) => block.width));
|
||||||
|
for (const block of this._blocks) {
|
||||||
|
block.width = this.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
layout() {
|
||||||
|
let y = 0;
|
||||||
|
for (const block of this._blocks) {
|
||||||
|
block.x = 0;
|
||||||
|
block.y = y;
|
||||||
|
block.width = this.width;
|
||||||
|
block.layout();
|
||||||
|
y += block.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
for (const block of this._blocks) {
|
||||||
|
block.update();
|
||||||
|
}
|
||||||
|
this.border.setAttribute('d', grapher.Node.roundedRect(0, 0, this.width, this.height, true, true, true, true));
|
||||||
|
this.element.setAttribute('transform', 'translate(' + (this.x - (this.width / 2)) + ',' + (this.y - (this.height / 2)) + ')');
|
||||||
|
this.element.style.removeProperty('opacity');
|
||||||
|
}
|
||||||
|
|
||||||
|
select() {
|
||||||
|
if (this.element) {
|
||||||
|
this.element.classList.add('select');
|
||||||
|
return [ this.element ];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
deselect() {
|
||||||
|
if (this.element) {
|
||||||
|
this.element.classList.remove('select');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static roundedRect(x, y, width, height, r1, r2, r3, r4) {
|
||||||
|
const radius = 5;
|
||||||
|
r1 = r1 ? radius : 0;
|
||||||
|
r2 = r2 ? radius : 0;
|
||||||
|
r3 = r3 ? radius : 0;
|
||||||
|
r4 = r4 ? radius : 0;
|
||||||
|
return "M" + (x + r1) + "," + y +
|
||||||
|
"h" + (width - r1 - r2) +
|
||||||
|
"a" + r2 + "," + r2 + " 0 0 1 " + r2 + "," + r2 +
|
||||||
|
"v" + (height - r2 - r3) +
|
||||||
|
"a" + r3 + "," + r3 + " 0 0 1 " + -r3 + "," + r3 +
|
||||||
|
"h" + (r3 + r4 - width) +
|
||||||
|
"a" + r4 + "," + r4 + " 0 0 1 " + -r4 + "," + -r4 +
|
||||||
|
'v' + (-height + r4 + r1) +
|
||||||
|
"a" + r1 + "," + r1 + " 0 0 1 " + r1 + "," + -r1 +
|
||||||
|
"z";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
grapher.Node.Header = class {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._entries = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
add(id, classList, content, tooltip, handler) {
|
||||||
|
const entry = new grapher.Node.Header.Entry(id, classList, content, tooltip, handler);
|
||||||
|
this._entries.push(entry);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
build(document, parent) {
|
||||||
|
this._document = document;
|
||||||
|
for (const entry of this._entries) {
|
||||||
|
entry.build(document, parent);
|
||||||
|
}
|
||||||
|
if (!this.first) {
|
||||||
|
this.line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||||
|
parent.appendChild(this.line);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < this._entries.length; i++) {
|
||||||
|
const entry = this._entries[i];
|
||||||
|
if (i != 0) {
|
||||||
|
entry.line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||||
|
parent.appendChild(entry.line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
measure() {
|
||||||
|
this.width = 0;
|
||||||
|
this.height = 0;
|
||||||
|
for (const entry of this._entries) {
|
||||||
|
entry.measure();
|
||||||
|
this.height = Math.max(this.height, entry.height);
|
||||||
|
this.width += entry.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
layout() {
|
||||||
|
let x = this.width;
|
||||||
|
for (let i = this._entries.length - 1; i >= 0; i--) {
|
||||||
|
const entry = this._entries[i];
|
||||||
|
if (i > 0) {
|
||||||
|
x -= entry.width;
|
||||||
|
entry.x = x;
|
||||||
|
} else {
|
||||||
|
entry.x = 0;
|
||||||
|
entry.width = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
for (let i = 0; i < this._entries.length; i++) {
|
||||||
|
const entry = this._entries[i];
|
||||||
|
entry.element.setAttribute('transform', 'translate(' + entry.x + ',' + this.y + ')');
|
||||||
|
const r1 = i == 0 && this.first;
|
||||||
|
const r2 = i == this._entries.length - 1 && this.first;
|
||||||
|
const r3 = i == this._entries.length - 1 && this.last;
|
||||||
|
const r4 = i == 0 && this.last;
|
||||||
|
entry.path.setAttribute('d', grapher.Node.roundedRect(0, 0, entry.width, entry.height, r1, r2, r3, r4));
|
||||||
|
entry.text.setAttribute('x', 6);
|
||||||
|
entry.text.setAttribute('y', entry.ty);
|
||||||
|
}
|
||||||
|
for (let i = 1; i < this._entries.length; i++) {
|
||||||
|
const entry = this._entries[i];
|
||||||
|
const line = entry.line;
|
||||||
|
line.setAttribute('class', 'node');
|
||||||
|
line.setAttribute('x1', entry.x);
|
||||||
|
line.setAttribute('x2', entry.x);
|
||||||
|
line.setAttribute('y1', this.y);
|
||||||
|
line.setAttribute('y2', this.y + this.height);
|
||||||
|
}
|
||||||
|
if (this.line) {
|
||||||
|
this.line.setAttribute('class', 'node');
|
||||||
|
this.line.setAttribute('x1', 0);
|
||||||
|
this.line.setAttribute('x2', this.width);
|
||||||
|
this.line.setAttribute('y1', this.y);
|
||||||
|
this.line.setAttribute('y2', this.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
grapher.Node.Header.Entry = class {
|
||||||
|
|
||||||
|
constructor(id, classList, content, tooltip, handler) {
|
||||||
|
this.id = id;
|
||||||
|
this.classList = classList;
|
||||||
|
this.content = content;
|
||||||
|
this.tooltip = tooltip;
|
||||||
|
this.handler = handler;
|
||||||
|
this._events = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
on(event, callback) {
|
||||||
|
this._events[event] = this._events[event] || [];
|
||||||
|
this._events[event].push(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(event, data) {
|
||||||
|
if (this._events && this._events[event]) {
|
||||||
|
for (const callback of this._events[event]) {
|
||||||
|
callback(this, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build(document, parent) {
|
||||||
|
this.element = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||||
|
parent.appendChild(this.element);
|
||||||
|
this.path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||||
|
this.text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||||
|
this.element.appendChild(this.path);
|
||||||
|
this.element.appendChild(this.text);
|
||||||
|
const classList = [ 'node-item' ];
|
||||||
|
if (this.classList) {
|
||||||
|
classList.push(...this.classList);
|
||||||
|
}
|
||||||
|
this.element.setAttribute('class', classList.join(' '));
|
||||||
|
if (this.id) {
|
||||||
|
this.element.setAttribute('id', this.id);
|
||||||
|
}
|
||||||
|
if (this._events.click) {
|
||||||
|
this.element.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
this.emit('click');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.tooltip) {
|
||||||
|
const title = document.createElementNS('http://www.w3.org/2000/svg', 'title');
|
||||||
|
title.textContent = this.tooltip;
|
||||||
|
this.element.appendChild(title);
|
||||||
|
}
|
||||||
|
this.text.textContent = this.content || '\u00A0';
|
||||||
|
}
|
||||||
|
|
||||||
|
measure() {
|
||||||
|
const yPadding = 4;
|
||||||
|
const xPadding = 7;
|
||||||
|
const boundingBox = this.text.getBBox();
|
||||||
|
this.width = boundingBox.width + xPadding + xPadding;
|
||||||
|
this.height = boundingBox.height + yPadding + yPadding;
|
||||||
|
this.tx = xPadding;
|
||||||
|
this.ty = yPadding - boundingBox.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
layout() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
grapher.Node.List = class {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._items = [];
|
||||||
|
this._events = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
add(name, value, tooltip, separator) {
|
||||||
|
const item = new grapher.Node.List.Item(name, value, tooltip, separator);
|
||||||
|
this._items.push(item);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
on(event, callback) {
|
||||||
|
this._events[event] = this._events[event] || [];
|
||||||
|
this._events[event].push(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(event, data) {
|
||||||
|
if (this._events && this._events[event]) {
|
||||||
|
for (const callback of this._events[event]) {
|
||||||
|
callback(this, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build(document, parent) {
|
||||||
|
this._document = document;
|
||||||
|
this.element = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||||
|
this.element.setAttribute('class', 'node-attribute-list');
|
||||||
|
if (this._events.click) {
|
||||||
|
this.element.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
this.emit('click');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.background = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||||
|
this.element.appendChild(this.background);
|
||||||
|
parent.appendChild(this.element);
|
||||||
|
for (const item of this._items) {
|
||||||
|
const group = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||||
|
group.setAttribute('class', 'node-attribute');
|
||||||
|
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||||
|
text.setAttribute('xml:space', 'preserve');
|
||||||
|
if (item.tooltip) {
|
||||||
|
const title = document.createElementNS('http://www.w3.org/2000/svg', 'title');
|
||||||
|
title.textContent = item.tooltip;
|
||||||
|
text.appendChild(title);
|
||||||
|
}
|
||||||
|
const colon = item.type === 'node' || item.type === 'node[]';
|
||||||
|
const name = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
||||||
|
name.textContent = colon ? item.name + ':' : item.name;
|
||||||
|
if (item.separator.trim() !== '=' && !colon) {
|
||||||
|
name.style.fontWeight = 'bold';
|
||||||
|
}
|
||||||
|
text.appendChild(name);
|
||||||
|
group.appendChild(text);
|
||||||
|
this.element.appendChild(group);
|
||||||
|
item.group = group;
|
||||||
|
item.text = text;
|
||||||
|
if (item.type === 'node') {
|
||||||
|
const node = item.value;
|
||||||
|
node.build(document, item.group);
|
||||||
|
} else if (item.type === 'node[]') {
|
||||||
|
for (const node of item.value) {
|
||||||
|
node.build(document, item.group);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
||||||
|
tspan.textContent = item.separator + item.value;
|
||||||
|
item.text.appendChild(tspan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.first) {
|
||||||
|
this.line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||||
|
this.line.setAttribute('class', 'node');
|
||||||
|
this.element.appendChild(this.line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
measure() {
|
||||||
|
this.width = 75;
|
||||||
|
this.height = 3;
|
||||||
|
const yPadding = 1;
|
||||||
|
const xPadding = 6;
|
||||||
|
for (let i = 0; i < this._items.length; i++) {
|
||||||
|
const item = this._items[i];
|
||||||
|
const size = item.text.getBBox();
|
||||||
|
item.width = xPadding + size.width + xPadding;
|
||||||
|
item.height = yPadding + size.height + yPadding;
|
||||||
|
item.offset = size.y;
|
||||||
|
this.height += item.height;
|
||||||
|
if (item.type === 'node') {
|
||||||
|
const node = item.value;
|
||||||
|
node.measure();
|
||||||
|
this.width = Math.max(150, this.width, node.width + (2 * xPadding));
|
||||||
|
this.height += node.height + yPadding + yPadding + yPadding + yPadding;
|
||||||
|
if (i === this._items.length - 1) {
|
||||||
|
this.height += 3;
|
||||||
|
}
|
||||||
|
} else if (item.type === 'node[]') {
|
||||||
|
for (const node of item.value) {
|
||||||
|
node.measure();
|
||||||
|
this.width = Math.max(150, this.width, node.width + (2 * xPadding));
|
||||||
|
this.height += node.height + yPadding + yPadding + yPadding + yPadding;
|
||||||
|
}
|
||||||
|
if (i === this._items.length - 1) {
|
||||||
|
this.height += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.width = Math.max(this.width, item.width);
|
||||||
|
}
|
||||||
|
this.height += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
layout() {
|
||||||
|
const yPadding = 1;
|
||||||
|
const xPadding = 6;
|
||||||
|
let y = 3;
|
||||||
|
for (const item of this._items) {
|
||||||
|
item.x = this.x + xPadding;
|
||||||
|
item.y = y + yPadding - item.offset;
|
||||||
|
y += item.height;
|
||||||
|
if (item.type === 'node') {
|
||||||
|
const node = item.value;
|
||||||
|
node.width = this.width - xPadding - xPadding;
|
||||||
|
node.layout();
|
||||||
|
node.x = this.x + xPadding + (node.width / 2);
|
||||||
|
node.y = y + (node.height / 2) + yPadding + yPadding;
|
||||||
|
y += node.height + yPadding + yPadding + yPadding + yPadding;
|
||||||
|
} else if (item.type === 'node[]') {
|
||||||
|
for (const node of item.value) {
|
||||||
|
node.width = this.width - xPadding - xPadding;
|
||||||
|
node.layout();
|
||||||
|
node.x = this.x + xPadding + (node.width / 2);
|
||||||
|
node.y = y + (node.height / 2) + yPadding + yPadding;
|
||||||
|
y += node.height + yPadding + yPadding + yPadding + yPadding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.element.setAttribute('transform', 'translate(' + this.x + ',' + this.y + ')');
|
||||||
|
this.background.setAttribute('d', grapher.Node.roundedRect(0, 0, this.width, this.height, this.first, this.first, this.last, this.last));
|
||||||
|
for (const item of this._items) {
|
||||||
|
const text = item.text;
|
||||||
|
text.setAttribute('x', item.x);
|
||||||
|
text.setAttribute('y', item.y);
|
||||||
|
if (item.type === 'node') {
|
||||||
|
const node = item.value;
|
||||||
|
node.update();
|
||||||
|
} else if (item.type === 'node[]') {
|
||||||
|
for (const node of item.value) {
|
||||||
|
node.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.line) {
|
||||||
|
this.line.setAttribute('x1', 0);
|
||||||
|
this.line.setAttribute('x2', this.width);
|
||||||
|
this.line.setAttribute('y1', 0);
|
||||||
|
this.line.setAttribute('y2', 0);
|
||||||
|
}
|
||||||
|
for (const item of this._items) {
|
||||||
|
if (item.value instanceof grapher.Node) {
|
||||||
|
const node = item.value;
|
||||||
|
node.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
grapher.Node.List.Item = class {
|
||||||
|
|
||||||
|
constructor(name, value, tooltip, separator) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
this.tooltip = tooltip;
|
||||||
|
this.separator = separator;
|
||||||
|
if (value instanceof grapher.Node) {
|
||||||
|
this.type = 'node';
|
||||||
|
} else if (Array.isArray(value) && value.every((value) => value instanceof grapher.Node)) {
|
||||||
|
this.type = 'node[]';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
grapher.Node.Canvas = class {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.width = 0;
|
||||||
|
this.height = 80;
|
||||||
|
}
|
||||||
|
|
||||||
|
build(/* document, parent */) {
|
||||||
|
}
|
||||||
|
|
||||||
|
update(/* parent, top, width , first, last */) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
grapher.Edge = class {
|
||||||
|
|
||||||
|
constructor(from, to) {
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
build(document, edgePathGroupElement, edgeLabelGroupElement) {
|
||||||
|
const createElement = (name) => {
|
||||||
|
return document.createElementNS('http://www.w3.org/2000/svg', name);
|
||||||
|
};
|
||||||
|
this.element = createElement('path');
|
||||||
|
if (this.id) {
|
||||||
|
this.element.setAttribute('id', this.id);
|
||||||
|
}
|
||||||
|
this.element.setAttribute('class', this.class ? 'edge-path ' + this.class : 'edge-path');
|
||||||
|
edgePathGroupElement.appendChild(this.element);
|
||||||
|
this.hitTest = createElement('path');
|
||||||
|
this.hitTest.setAttribute('class', 'edge-path-hit-test');
|
||||||
|
this.hitTest.addEventListener('pointerover', () => this.emit('pointerover'));
|
||||||
|
this.hitTest.addEventListener('pointerleave', () => this.emit('pointerleave'));
|
||||||
|
this.hitTest.addEventListener('click', () => this.emit('click'));
|
||||||
|
edgePathGroupElement.appendChild(this.hitTest);
|
||||||
|
if (this.label) {
|
||||||
|
const tspan = createElement('tspan');
|
||||||
|
tspan.setAttribute('xml:space', 'preserve');
|
||||||
|
tspan.setAttribute('dy', '1em');
|
||||||
|
tspan.setAttribute('x', '1');
|
||||||
|
tspan.appendChild(document.createTextNode(this.label));
|
||||||
|
this.labelElement = createElement('text');
|
||||||
|
this.labelElement.appendChild(tspan);
|
||||||
|
this.labelElement.style.opacity = 0;
|
||||||
|
this.labelElement.setAttribute('class', 'edge-label');
|
||||||
|
if (this.id) {
|
||||||
|
this.labelElement.setAttribute('id', 'edge-label-' + this.id);
|
||||||
|
}
|
||||||
|
edgeLabelGroupElement.appendChild(this.labelElement);
|
||||||
|
const edgeBox = this.labelElement.getBBox();
|
||||||
|
this.width = edgeBox.width;
|
||||||
|
this.height = edgeBox.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
const intersectRect = (node, point) => {
|
||||||
|
const x = node.x;
|
||||||
|
const y = node.y;
|
||||||
|
const dx = point.x - x;
|
||||||
|
const dy = point.y - y;
|
||||||
|
let h = node.height / 2;
|
||||||
|
let w = node.width / 2;
|
||||||
|
if (Math.abs(dy) * w > Math.abs(dx) * h) {
|
||||||
|
if (dy < 0) {
|
||||||
|
h = -h;
|
||||||
|
}
|
||||||
|
return { x: x + (dy === 0 ? 0 : h * dx / dy), y: y + h };
|
||||||
|
}
|
||||||
|
if (dx < 0) {
|
||||||
|
w = -w;
|
||||||
|
}
|
||||||
|
return { x: x + w, y: y + (dx === 0 ? 0 : w * dy / dx) };
|
||||||
|
};
|
||||||
|
const curvePath = (edge, tail, head) => {
|
||||||
|
const points = edge.points.slice(1, edge.points.length - 1);
|
||||||
|
points.unshift(intersectRect(tail, points[0]));
|
||||||
|
points.push(intersectRect(head, points[points.length - 1]));
|
||||||
|
return new grapher.Edge.Curve(points).path.data;
|
||||||
|
};
|
||||||
|
const edgePath = curvePath(this, this.from, this.to);
|
||||||
|
this.element.setAttribute('d', edgePath);
|
||||||
|
this.hitTest.setAttribute('d', edgePath);
|
||||||
|
if (this.labelElement) {
|
||||||
|
this.labelElement.setAttribute('transform', 'translate(' + (this.x - (this.width / 2)) + ',' + (this.y - (this.height / 2)) + ')');
|
||||||
|
this.labelElement.style.opacity = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
select() {
|
||||||
|
if (this.element) {
|
||||||
|
if (!this.element.classList.contains('select')) {
|
||||||
|
const path = this.element;
|
||||||
|
path.classList.add('select');
|
||||||
|
this.element = path.cloneNode(true);
|
||||||
|
path.parentNode.replaceChild(this.element, path);
|
||||||
|
}
|
||||||
|
return [ this.element ];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
deselect() {
|
||||||
|
if (this.element && this.element.classList.contains('select')) {
|
||||||
|
const path = this.element;
|
||||||
|
path.classList.remove('select');
|
||||||
|
this.element = path.cloneNode(true);
|
||||||
|
path.parentNode.replaceChild(this.element, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
grapher.Edge.Curve = class {
|
||||||
|
|
||||||
|
constructor(points) {
|
||||||
|
this._path = new grapher.Edge.Path();
|
||||||
|
this._x0 = NaN;
|
||||||
|
this._x1 = NaN;
|
||||||
|
this._y0 = NaN;
|
||||||
|
this._y1 = NaN;
|
||||||
|
this._state = 0;
|
||||||
|
for (let i = 0; i < points.length; i++) {
|
||||||
|
const point = points[i];
|
||||||
|
this.point(point.x, point.y);
|
||||||
|
if (i === points.length - 1) {
|
||||||
|
switch (this._state) {
|
||||||
|
case 3:
|
||||||
|
this.curve(this._x1, this._y1);
|
||||||
|
this._path.lineTo(this._x1, this._y1);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
this._path.lineTo(this._x1, this._y1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (this._line || (this._line !== 0 && this._point === 1)) {
|
||||||
|
this._path.closePath();
|
||||||
|
}
|
||||||
|
this._line = 1 - this._line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get path() {
|
||||||
|
return this._path;
|
||||||
|
}
|
||||||
|
|
||||||
|
point(x, y) {
|
||||||
|
x = +x;
|
||||||
|
y = +y;
|
||||||
|
switch (this._state) {
|
||||||
|
case 0:
|
||||||
|
this._state = 1;
|
||||||
|
if (this._line) {
|
||||||
|
this._path.lineTo(x, y);
|
||||||
|
} else {
|
||||||
|
this._path.moveTo(x, y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
this._state = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
this._state = 3;
|
||||||
|
this._path.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6);
|
||||||
|
this.curve(x, y);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.curve(x, y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this._x0 = this._x1;
|
||||||
|
this._x1 = x;
|
||||||
|
this._y0 = this._y1;
|
||||||
|
this._y1 = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
curve(x, y) {
|
||||||
|
this._path.bezierCurveTo(
|
||||||
|
(2 * this._x0 + this._x1) / 3,
|
||||||
|
(2 * this._y0 + this._y1) / 3,
|
||||||
|
(this._x0 + 2 * this._x1) / 3,
|
||||||
|
(this._y0 + 2 * this._y1) / 3,
|
||||||
|
(this._x0 + 4 * this._x1 + x) / 6,
|
||||||
|
(this._y0 + 4 * this._y1 + y) / 6
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
grapher.Edge.Path = class {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._x0 = null;
|
||||||
|
this._y0 = null;
|
||||||
|
this._x1 = null;
|
||||||
|
this._y1 = null;
|
||||||
|
this._data = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
moveTo(x, y) {
|
||||||
|
this._data += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y);
|
||||||
|
}
|
||||||
|
|
||||||
|
lineTo(x, y) {
|
||||||
|
this._data += "L" + (this._x1 = +x) + "," + (this._y1 = +y);
|
||||||
|
}
|
||||||
|
|
||||||
|
bezierCurveTo(x1, y1, x2, y2, x, y) {
|
||||||
|
this._data += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
|
||||||
|
}
|
||||||
|
|
||||||
|
closePath() {
|
||||||
|
if (this._x1 !== null) {
|
||||||
|
this._x1 = this._x0;
|
||||||
|
this._y1 = this._y0;
|
||||||
|
this._data += "Z";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get data() {
|
||||||
|
return this._data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined' && typeof window === 'object') {
|
||||||
|
window.grapher = grapher;
|
||||||
|
}
|
|
@ -0,0 +1,134 @@
|
||||||
|
|
||||||
|
var host = host || {};
|
||||||
|
|
||||||
|
host.BrowserHost = class {
|
||||||
|
|
||||||
|
constructor(vscode) {
|
||||||
|
this._vscode = vscode;
|
||||||
|
this._window = window;
|
||||||
|
this._document = window.document;
|
||||||
|
|
||||||
|
this._environment = {
|
||||||
|
name: this._document.title,
|
||||||
|
menu: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get window() {
|
||||||
|
return this._window;
|
||||||
|
}
|
||||||
|
|
||||||
|
get document() {
|
||||||
|
return this._document;
|
||||||
|
}
|
||||||
|
|
||||||
|
async view(view) {
|
||||||
|
this._view = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
async start() {
|
||||||
|
this.document.addEventListener('dragover', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
this.document.addEventListener('drop', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
this.document.body.addEventListener('drop', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
this._view.show('welcome');
|
||||||
|
}
|
||||||
|
|
||||||
|
environment(name) {
|
||||||
|
return this._environment[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
error(message, detail) {
|
||||||
|
this._vscode.postMessage({ type: 'error', message: detail });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* save numpy tensor
|
||||||
|
* @param {*} name
|
||||||
|
* @param {*} extension
|
||||||
|
* @param {*} defaultPath
|
||||||
|
* @param {*} callback
|
||||||
|
*/
|
||||||
|
save(name, extension, defaultPath, callback) {
|
||||||
|
callback(defaultPath + '.' + extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* export png and svg images
|
||||||
|
* @param {string} file the file name
|
||||||
|
* @param {Blob} blob data blob
|
||||||
|
*/
|
||||||
|
export(file, blob) {
|
||||||
|
// const element = this.document.createElement('a');
|
||||||
|
// element.download = file;
|
||||||
|
// element.href = URL.createObjectURL(blob);
|
||||||
|
// this.document.body.appendChild(element);
|
||||||
|
// element.click();
|
||||||
|
// this.document.body.removeChild(element);
|
||||||
|
|
||||||
|
blob.arrayBuffer().then((arrayBuf)=>{
|
||||||
|
let data = new Uint8Array(arrayBuf);
|
||||||
|
this._vscode.postMessage({ type: 'export', fileName: file, data: data });
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
exception(error, fatal) {
|
||||||
|
//send telemetry, do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
event(name, params) {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
_element(id) {
|
||||||
|
return this.document.getElementById(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!('scrollBehavior' in window.document.documentElement.style)) {
|
||||||
|
const __scrollTo__ = Element.prototype.scrollTo;
|
||||||
|
Element.prototype.scrollTo = function(options) {
|
||||||
|
if (options !== undefined) {
|
||||||
|
if (options === null || typeof options !== 'object' || options.behavior === undefined || arguments[0].behavior === 'auto' || options.behavior === 'instant') {
|
||||||
|
if (__scrollTo__) {
|
||||||
|
__scrollTo__.apply(this, arguments);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const now = () => window.performance && window.performance.now ? window.performance.now() : Date.now();
|
||||||
|
const ease = (k) => 0.5 * (1 - Math.cos(Math.PI * k));
|
||||||
|
const step = (context) => {
|
||||||
|
const value = ease(Math.min((now() - context.startTime) / 468, 1));
|
||||||
|
const x = context.startX + (context.x - context.startX) * value;
|
||||||
|
const y = context.startY + (context.y - context.startY) * value;
|
||||||
|
context.element.scrollLeft = x;
|
||||||
|
context.element.scrollTop = y;
|
||||||
|
if (x !== context.x || y !== context.y) {
|
||||||
|
window.requestAnimationFrame(step.bind(window, context));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const context = {
|
||||||
|
element: this,
|
||||||
|
x: typeof options.left === 'undefined' ? this.scrollLeft : ~~options.left,
|
||||||
|
y: typeof options.top === 'undefined' ? this.scrollTop : ~~options.top,
|
||||||
|
startX: this.scrollLeft,
|
||||||
|
startY: this.scrollTop,
|
||||||
|
startTime: now()
|
||||||
|
};
|
||||||
|
step(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined' && typeof window === 'object') {
|
||||||
|
window.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined' && typeof module.exports === 'object') {
|
||||||
|
module.exports = host;
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
|
||||||
|
// This script is run within the webview itself
|
||||||
|
(function () {
|
||||||
|
const vscode = acquireVsCodeApi();
|
||||||
|
|
||||||
|
//the onnx proto model
|
||||||
|
let onnxProtoModel = null;
|
||||||
|
//the onnx proto graphs
|
||||||
|
let onnxProtoGraphs = null;
|
||||||
|
//the onnx model name
|
||||||
|
let onnxModelName = '';
|
||||||
|
//the tensor external data map. key: location, value: Uint8Array
|
||||||
|
let externalTensorMap = new Map();
|
||||||
|
//the tensor external locations
|
||||||
|
let externalTensorLocations = [];
|
||||||
|
|
||||||
|
// Handle messages from the extension
|
||||||
|
window.addEventListener('message', e => {
|
||||||
|
const { type, body } = e.data;
|
||||||
|
switch (type) {
|
||||||
|
case 'init':
|
||||||
|
{
|
||||||
|
//the onnx file content, Uint8Array
|
||||||
|
let onnxValue = body.modelData;
|
||||||
|
//the onnx file name
|
||||||
|
onnxModelName = body.modelName;
|
||||||
|
|
||||||
|
onnxProtoModel = window.proto.onnx.ModelProto.decode(onnxValue);
|
||||||
|
let { locations, graphs } = window.getExternalLocations(onnxProtoModel);
|
||||||
|
|
||||||
|
//refer to https://github.com/onnx/onnx/blob/main/docs/ExternalData.md
|
||||||
|
if (locations.length > 0) {
|
||||||
|
onnxProtoGraphs = graphs;
|
||||||
|
externalTensorMap.clear();
|
||||||
|
externalTensorLocations = locations;
|
||||||
|
//load tensor external data
|
||||||
|
vscode.postMessage({ type: 'external_tensor', external_locations: locations });
|
||||||
|
} else {
|
||||||
|
let model = new window.onnx.Model(onnxProtoModel, graphs, new Map());
|
||||||
|
|
||||||
|
let host = new window.host.BrowserHost(vscode);
|
||||||
|
let view = new window.View(host);
|
||||||
|
view.start().then((data) => {
|
||||||
|
view.open(model, onnxModelName);
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'external_tensor': {
|
||||||
|
//the external tensor data, Uint8Array
|
||||||
|
let tensorData = body.tensorData;
|
||||||
|
let loc = body.location;
|
||||||
|
|
||||||
|
externalTensorMap.set(loc, tensorData);
|
||||||
|
if (externalTensorMap.size == externalTensorLocations.length) {
|
||||||
|
let model = new window.onnx.Model(onnxProtoModel, onnxProtoGraphs, externalTensorMap);
|
||||||
|
|
||||||
|
let host = new window.host.BrowserHost(vscode);
|
||||||
|
let view = new window.View(host);
|
||||||
|
view.start().then((data) => {
|
||||||
|
view.open(model, onnxModelName);
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Signal to VS Code that the webview is initialized.
|
||||||
|
vscode.postMessage({ type: 'ready' });
|
||||||
|
}());
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -50,10 +50,10 @@ class MenuAPI {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/internetProtocol",
|
path: "/flow",
|
||||||
component: "Layout",
|
component: "Layout",
|
||||||
redirect: "/internetProtocol/index",
|
redirect: "/flow/demo",
|
||||||
name: "/internetProtocol",
|
name: "/flow",
|
||||||
meta: {
|
meta: {
|
||||||
title: "互联协议",
|
title: "互联协议",
|
||||||
icon: "web",
|
icon: "web",
|
||||||
|
@ -63,9 +63,9 @@ class MenuAPI {
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "user",
|
path: "demo",
|
||||||
component: "system/user/index",
|
component: "flow/demo/index",
|
||||||
name: "User",
|
name: "demo",
|
||||||
meta: {
|
meta: {
|
||||||
title: "互联协议1",
|
title: "互联协议1",
|
||||||
icon: "user",
|
icon: "user",
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { PolylineEdge, PolylineEdgeModel } from "@logicflow/core";
|
||||||
|
|
||||||
|
class FlowLinkModel extends PolylineEdgeModel {
|
||||||
|
getEdgeStyle() {
|
||||||
|
const style = super.getEdgeStyle();
|
||||||
|
style.strokeWidth = 1;
|
||||||
|
style.stroke = this.isSelected ? '#ff7f0e' : '#999';
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class FlowLink extends PolylineEdge {}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
type: 'ai-link',
|
||||||
|
view: FlowLink,
|
||||||
|
model: FlowLinkModel
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
import BaseNode from './nodes/BaseNode.js'
|
||||||
|
import FlowLink from './FlowLink.js'
|
||||||
|
class NodeRedExtension{
|
||||||
|
static pluginName = 'NodeAiExtension'
|
||||||
|
constructor ({ lf }) {
|
||||||
|
lf.register(BaseNode)
|
||||||
|
lf.register(FlowLink)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default NodeRedExtension
|
|
@ -0,0 +1,11 @@
|
||||||
|
import "@logicflow/extension/lib/style/index.css";
|
||||||
|
|
||||||
|
export default function(lf) {
|
||||||
|
const menuConfig = {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
lf.extension.menu.menuTypeMap.get("lf:defaultNodeMenu").splice(1,2)
|
||||||
|
lf.extension.menu.menuTypeMap.get("lf:defaultEdgeMenu").splice(1,1)
|
||||||
|
lf.extension.menu.addMenuConfig(menuConfig);
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
import { RectNode, RectNodeModel, h } from "@logicflow/core"
|
||||||
|
import { getBytesLength } from '../util'
|
||||||
|
|
||||||
|
|
||||||
|
class RedNodeModel extends RectNodeModel {
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
*/
|
||||||
|
initNodeData(data) {
|
||||||
|
super.initNodeData(data)
|
||||||
|
this.width = 200;
|
||||||
|
this.height = 30;
|
||||||
|
this.radius = 5;
|
||||||
|
this.text.x = this.x + 10;
|
||||||
|
this.defaultFill = data.fill||'rgb(253, 208, 162)'
|
||||||
|
}
|
||||||
|
getData () {
|
||||||
|
const data = super.getData()
|
||||||
|
data.properties.ui = 'node-ai'
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
updateText(val) {
|
||||||
|
super.updateText(val)
|
||||||
|
this.setAttributes();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 重写节点样式
|
||||||
|
*/
|
||||||
|
getNodeStyle() {
|
||||||
|
const style = super.getNodeStyle();
|
||||||
|
const dataStyle = this.properties.style || {};
|
||||||
|
if (this.isSelected) {
|
||||||
|
style.strokeWidth = Number(dataStyle.borderWidth) || 2;
|
||||||
|
style.stroke = dataStyle.borderColor || '#ff7f0e';
|
||||||
|
} else {
|
||||||
|
style.strokeWidth = Number(dataStyle.borderWidth) || 1;
|
||||||
|
style.stroke = dataStyle.borderColor || '#999';
|
||||||
|
}
|
||||||
|
style.fill = dataStyle.backgroundColor || this.defaultFill;
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 重写定义锚点
|
||||||
|
*/
|
||||||
|
getDefaultAnchor() {
|
||||||
|
const { x, y, id, width, height } = this;
|
||||||
|
const anchors = [
|
||||||
|
{
|
||||||
|
x: x ,
|
||||||
|
y: y+ height / 2,
|
||||||
|
id: `${id}_right`,
|
||||||
|
type: "right"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: x ,
|
||||||
|
y: y- height / 2,
|
||||||
|
id: `${id}_left`,
|
||||||
|
type: "left"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return anchors;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
getOutlineStyle() {
|
||||||
|
const style = super.getOutlineStyle();
|
||||||
|
style.stroke = 'transparent';
|
||||||
|
style.hover.stroke = 'transparent';
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
handleContextMenu(ev){
|
||||||
|
debugger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class RedNode extends RectNode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1.1.7版本后支持在view中重写锚点形状。
|
||||||
|
* 重写锚点新增
|
||||||
|
*/
|
||||||
|
getAnchorShape(anchorData) {
|
||||||
|
const { x, y, type } = anchorData;
|
||||||
|
return h("rect", {
|
||||||
|
x: x - 5,
|
||||||
|
y: y - 5,
|
||||||
|
width: 10,
|
||||||
|
height: 10,
|
||||||
|
className: 'custom-anchor'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getShape() {
|
||||||
|
const {
|
||||||
|
text,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
radius
|
||||||
|
} = this.props.model;
|
||||||
|
const style = this.props.model.getNodeStyle()
|
||||||
|
return h(
|
||||||
|
'g',
|
||||||
|
{
|
||||||
|
className: 'lf-ai-node'
|
||||||
|
},
|
||||||
|
[
|
||||||
|
h('rect', {
|
||||||
|
...style,
|
||||||
|
x: x - width / 2,
|
||||||
|
y: y - height / 2,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
rx: radius,
|
||||||
|
ry: radius
|
||||||
|
})
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
type: 'ai-node',
|
||||||
|
model: RedNodeModel,
|
||||||
|
view: RedNode
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
/* 求字符串的字节长度 */
|
||||||
|
export const getBytesLength = (word) => {
|
||||||
|
if (!word) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
let totalLength = 0;
|
||||||
|
for (let i = 0; i < word.length; i++) {
|
||||||
|
const c = word.charCodeAt(i);
|
||||||
|
if ((word.match(/[A-Z]/))) {
|
||||||
|
totalLength += 1.5;
|
||||||
|
} else if ((c >= 0x0001 && c <= 0x007e) || (c >= 0xff60 && c <= 0xff9f)) {
|
||||||
|
totalLength += 1;
|
||||||
|
} else {
|
||||||
|
totalLength += 1.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return totalLength;
|
||||||
|
};
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<section class="app-main">
|
<section class="app-main">
|
||||||
<el-scrollbar max-height="calc(100vh - 76px)">
|
<el-scrollbar height="calc(100vh - 76px)">
|
||||||
<router-view>
|
<router-view>
|
||||||
<template #default="{ Component, route }">
|
<template #default="{ Component, route }">
|
||||||
<transition
|
<transition
|
||||||
|
@ -29,6 +29,9 @@ const cachedViews = computed(() => useTagsViewStore().cachedViews); // 缓存页
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: calc(100vh - 100px);
|
min-height: calc(100vh - 100px);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
:deep(.el-scrollbar__view){
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.hasTagsView .app-main {
|
.hasTagsView .app-main {
|
||||||
|
|
|
@ -0,0 +1,190 @@
|
||||||
|
<template>
|
||||||
|
<div class="flow-demo1">
|
||||||
|
<el-row :gutter="20" style="height: 100%;">
|
||||||
|
<el-col :span="4">
|
||||||
|
<NodePanel :lf="lf" ref="nodePanel"/>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-card class="flow-card">
|
||||||
|
<div ref="flow" class="viewport" id="flowMain" @click="hideProp"/>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="4">
|
||||||
|
<el-card v-if="showProp" :key="nodePropKey">
|
||||||
|
<template #header>节点属性</template>
|
||||||
|
<div>
|
||||||
|
节点ID:{{nodeData.properties.node }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
节点名称:{{nodeData.text.value }}
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import LogicFlow from '@logicflow/core';
|
||||||
|
// 引入整体背景的样式
|
||||||
|
import '@logicflow/core/dist/style/index.css';
|
||||||
|
import { Menu } from "@logicflow/extension";
|
||||||
|
import AiNodeExtension from '@/components/flow/index'
|
||||||
|
import RegisteMenu from '@/components/flow/menu.js'
|
||||||
|
import NodePanel from './nodePanel.vue'
|
||||||
|
const themeApprove = {
|
||||||
|
rect: { // 矩形样式
|
||||||
|
radius: 8,
|
||||||
|
stroke: '#3CB371'
|
||||||
|
},
|
||||||
|
circle: {
|
||||||
|
r: 25,
|
||||||
|
stroke: '#FF6347'
|
||||||
|
},
|
||||||
|
polygon: {
|
||||||
|
stroke: '#6495ED',
|
||||||
|
},
|
||||||
|
polyline: {
|
||||||
|
strokeWidth: 1,
|
||||||
|
stroke: '#3CB371'
|
||||||
|
},
|
||||||
|
edgeText: {
|
||||||
|
background: {
|
||||||
|
fill: 'white',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
let showProp=ref(false)
|
||||||
|
let nodeData=reactive(null)
|
||||||
|
const nodePanel=ref()
|
||||||
|
const config = {
|
||||||
|
stopScrollGraph: true,
|
||||||
|
stopZoomGraph: true,
|
||||||
|
grid: {
|
||||||
|
size: 10,
|
||||||
|
visible: true,
|
||||||
|
type: 'mesh',
|
||||||
|
config: {
|
||||||
|
color: '#DCDCDC',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
keyboard: { enabled: true },
|
||||||
|
style: themeApprove,
|
||||||
|
plugins: [AiNodeExtension,Menu]
|
||||||
|
};
|
||||||
|
const flow = ref()
|
||||||
|
let lf = ref(null)
|
||||||
|
let nodePropKey=ref(1)
|
||||||
|
const hideProp=(e)=>{
|
||||||
|
if(e.target.classList.contains("lf-drag-able")){
|
||||||
|
showProp.value=false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const initEvent=(lf)=>{
|
||||||
|
lf.on("element:click",node=>{
|
||||||
|
nodeData=node.data
|
||||||
|
showProp.value=true
|
||||||
|
nodePropKey.value++
|
||||||
|
console.log("-->",nodeData)
|
||||||
|
});
|
||||||
|
lf.on("node:dnd-add",data=>{
|
||||||
|
nodeData=data.data;
|
||||||
|
showProp.value=true
|
||||||
|
nodePropKey.value++
|
||||||
|
doUpdateState()
|
||||||
|
});
|
||||||
|
lf.on("node:delete",data=>{
|
||||||
|
if(data.data.text.value=="目标绘图"){
|
||||||
|
ElMessage.error("目标绘图节点不能删除");
|
||||||
|
setTimeout(() => {
|
||||||
|
lf.undo();
|
||||||
|
}, 400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
doUpdateState()
|
||||||
|
});
|
||||||
|
lf.on("node:contextmenu",(d,e,p)=>{
|
||||||
|
if(d.data.text.value=="目标绘图"){
|
||||||
|
setTimeout(()=>{
|
||||||
|
document.querySelector(".lf-menu").style.display="none";
|
||||||
|
},0)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const doUpdateState=()=>{
|
||||||
|
nodePanel.value.updateNode(lf.value.getGraphData());
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
const logicFlow = new LogicFlow({
|
||||||
|
...config,
|
||||||
|
container: flow.value
|
||||||
|
})
|
||||||
|
lf.value = logicFlow
|
||||||
|
RegisteMenu(logicFlow)
|
||||||
|
initEvent(logicFlow);
|
||||||
|
window.lf=lf
|
||||||
|
logicFlow.render({
|
||||||
|
nodes: [
|
||||||
|
{
|
||||||
|
id: 'node_1',
|
||||||
|
type: 'ai-node',
|
||||||
|
x: 150,
|
||||||
|
y: 20,
|
||||||
|
fill:'#409effaa',
|
||||||
|
text: '图像缩放',
|
||||||
|
properties:{
|
||||||
|
node:201
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'node_2',
|
||||||
|
type: 'ai-node',
|
||||||
|
x: 150,
|
||||||
|
y: 80,
|
||||||
|
fill:'#50e904',
|
||||||
|
text: '目标绘图',
|
||||||
|
properties:{
|
||||||
|
node:900
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
edges: [
|
||||||
|
|
||||||
|
]
|
||||||
|
})
|
||||||
|
doUpdateState();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style lang='scss'>
|
||||||
|
.flow-demo1 {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
.viewport {
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-anchor {
|
||||||
|
stroke: #999;
|
||||||
|
stroke-width: 1;
|
||||||
|
fill: #d9d9d9;
|
||||||
|
cursor: crosshair;
|
||||||
|
rx: 3;
|
||||||
|
ry: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-anchor:hover {
|
||||||
|
fill: #ff7f0e;
|
||||||
|
stroke: #ff7f0e;
|
||||||
|
}
|
||||||
|
.flow-card{
|
||||||
|
height: 80%;
|
||||||
|
.el-card__body{
|
||||||
|
height:100%;
|
||||||
|
padding:4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,87 @@
|
||||||
|
<template>
|
||||||
|
<div class="node-panel">
|
||||||
|
<el-tabs type="border-card">
|
||||||
|
<el-tab-pane label="前处理算子">
|
||||||
|
<div v-for="(it1, idx1) in list1" :key="idx1" class="div-item" @mousedown="dragNode(it1, 1)" v-show="it1.show">
|
||||||
|
{{ it1.text }}
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="后处理算子">
|
||||||
|
<div v-for="(it2, idx2) in list2" :key="idx2" class="div-item item2" @mousedown="dragNode(it2, 2)" v-show="it2.show">
|
||||||
|
{{ it2.text }}
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
lf: {
|
||||||
|
type: Object,
|
||||||
|
require: true,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const dragNode = (it, t) => {
|
||||||
|
props.lf.dnd.startDrag({
|
||||||
|
type: 'ai-node',
|
||||||
|
text: it.text,
|
||||||
|
fill: t == 1 ? '#409effaa' : '#ccccccaa',
|
||||||
|
properties:{
|
||||||
|
node:it.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const list1 = reactive([
|
||||||
|
{ text: "图像缩放", id: 201,show:true },
|
||||||
|
{ text: "RGB12图像格式转换", id: 202,show:true },
|
||||||
|
{ text: "RGB24图像格式转换", id: 203,show:true },
|
||||||
|
{ text: "RGB36图像格式转换", id: 204,show:true },
|
||||||
|
{ text: "RGB48图像格式转换", id: 205,show:true },
|
||||||
|
{ text: "RGB72图像格式转换", id: 206,show:true }
|
||||||
|
])
|
||||||
|
|
||||||
|
const list2 = reactive([
|
||||||
|
{ text: "VIT推理算子1", id: 301,show:true },
|
||||||
|
{ text: "VIT推理算子2", id: 301,show:true },
|
||||||
|
{ text: "VIT后处理算子1", id: 301,show:true },
|
||||||
|
{ text: "VIT后处理算子2", id: 301,show:true },
|
||||||
|
{ text: "VIT后处理算子3", id: 301,show:true },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const updateNode=(nodes)=>{
|
||||||
|
let nds=nodes.nodes.map(d=>d.properties.node);
|
||||||
|
list2.forEach(d=>{
|
||||||
|
d.show=nds.indexOf(d.id)==-1
|
||||||
|
})
|
||||||
|
list1.forEach(d=>{
|
||||||
|
d.show=nds.indexOf(d.id)==-1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
updateNode
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style lang='scss'>
|
||||||
|
.node-panel {
|
||||||
|
.div-item {
|
||||||
|
font-size: 12px;
|
||||||
|
border: solid 1px #888;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
line-height: 30px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #409effaa;
|
||||||
|
user-select: none;
|
||||||
|
cursor: move;
|
||||||
|
|
||||||
|
&.item2 {
|
||||||
|
background: #ccccccaa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -5,16 +5,21 @@
|
||||||
</div>
|
</div>
|
||||||
<div style="text-align: center;">
|
<div style="text-align: center;">
|
||||||
建设中。。。。。
|
建设中。。。。。
|
||||||
</div>
|
</div>
|
||||||
|
<iframe :src="url" style="width:100%;height:100%;position: absolute;top:0px;"></iframe>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang='ts' setup>
|
<script setup>
|
||||||
|
let url=ref("")
|
||||||
|
onMounted(()=>{
|
||||||
|
url.value="./onnx/onnx.html?url=/ai/siamRPN_192.onnx"
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang='scss'>
|
<style scoped lang='scss'>
|
||||||
.split-split1-index{
|
.split-split1-index{
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 12px 24px;
|
padding: 12px 24px;
|
||||||
|
height:100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
Loading…
Reference in New Issue