增加对于 mac 的支持 | 重构按键映射代码
This commit is contained in:
parent
703ba8a58c
commit
55f0c5c93b
26
README.md
26
README.md
@ -1,24 +1,6 @@
|
|||||||
# digital-wavetrace
|
|
||||||
|
|
||||||
## Project setup
|
## build
|
||||||
```
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compiles and hot-reloads for development
|
```bash
|
||||||
```
|
python scripts/vscode-package.py
|
||||||
npm run serve
|
```
|
||||||
```
|
|
||||||
|
|
||||||
### Compiles and minifies for production
|
|
||||||
```
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lints and fixes files
|
|
||||||
```
|
|
||||||
npm run lint
|
|
||||||
```
|
|
||||||
|
|
||||||
### Customize configuration
|
|
||||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
|
13
package-lock.json
generated
13
package-lock.json
generated
@ -26,6 +26,7 @@
|
|||||||
"@vue/cli-plugin-eslint": "~5.0.0",
|
"@vue/cli-plugin-eslint": "~5.0.0",
|
||||||
"@vue/cli-service": "~5.0.0",
|
"@vue/cli-service": "~5.0.0",
|
||||||
"eslint-plugin-vue": "^8.0.3",
|
"eslint-plugin-vue": "^8.0.3",
|
||||||
|
"ignore-loader": "^0.1.2",
|
||||||
"unplugin-auto-import": "^0.17.5",
|
"unplugin-auto-import": "^0.17.5",
|
||||||
"unplugin-vue-components": "^0.26.0"
|
"unplugin-vue-components": "^0.26.0"
|
||||||
}
|
}
|
||||||
@ -6991,6 +6992,12 @@
|
|||||||
"node": ">= 4"
|
"node": ">= 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ignore-loader": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ignore-loader/-/ignore-loader-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-yOJQEKrNwoYqrWLS4DcnzM7SEQhRKis5mB+LdKKh4cPmGYlLPR0ozRzHV5jmEk2IxptqJNQA5Cc0gw8Fj12bXA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/import-fresh": {
|
"node_modules/import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz",
|
"resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||||
@ -17333,6 +17340,12 @@
|
|||||||
"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
|
"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"ignore-loader": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ignore-loader/-/ignore-loader-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-yOJQEKrNwoYqrWLS4DcnzM7SEQhRKis5mB+LdKKh4cPmGYlLPR0ozRzHV5jmEk2IxptqJNQA5Cc0gw8Fj12bXA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"import-fresh": {
|
"import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz",
|
"resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
"@vue/cli-plugin-eslint": "~5.0.0",
|
"@vue/cli-plugin-eslint": "~5.0.0",
|
||||||
"@vue/cli-service": "~5.0.0",
|
"@vue/cli-service": "~5.0.0",
|
||||||
"eslint-plugin-vue": "^8.0.3",
|
"eslint-plugin-vue": "^8.0.3",
|
||||||
|
"ignore-loader": "^0.1.2",
|
||||||
"unplugin-auto-import": "^0.17.5",
|
"unplugin-auto-import": "^0.17.5",
|
||||||
"unplugin-vue-components": "^0.26.0"
|
"unplugin-vue-components": "^0.26.0"
|
||||||
},
|
},
|
||||||
|
@ -1,16 +1,43 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 4440655 */
|
font-family: "iconfont"; /* Project id 4440655 */
|
||||||
src: url('iconfont.woff2?t=1713691301672') format('woff2');
|
src: url('iconfont.woff2?t=1715948037690') format('woff2');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
font-family: "iconfont" !important;
|
font-family: "iconfont" !important;
|
||||||
font-size: 16px;
|
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-arrow-right:before {
|
||||||
|
content: "\eb08";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-arrow-left:before {
|
||||||
|
content: "\eb09";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-arrow-down:before {
|
||||||
|
content: "\eb0a";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-arrow-up:before {
|
||||||
|
content: "\eb0b";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-command:before {
|
||||||
|
content: "\e604";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-minus:before {
|
||||||
|
content: "\e656";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-equal:before {
|
||||||
|
content: "\e701";
|
||||||
|
}
|
||||||
|
|
||||||
.icon-ctrl:before {
|
.icon-ctrl:before {
|
||||||
content: "\e605";
|
content: "\e605";
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
@ -11,11 +11,12 @@
|
|||||||
<link rel="stylesheet" href="vscode.css">
|
<link rel="stylesheet" href="vscode.css">
|
||||||
<link rel="stylesheet" href="vcd.css">
|
<link rel="stylesheet" href="vcd.css">
|
||||||
<link rel="stylesheet" href="iconfont.css">
|
<link rel="stylesheet" href="iconfont.css">
|
||||||
<script src="vcd.js"></script>
|
<!-- <script src="vcd.js"></script> -->
|
||||||
|
<script></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
window.readVcdFile = async () => {
|
window.readVcdFile = async () => {
|
||||||
const response = await fetch('pe_tb.vcd');
|
const response = await fetch('test.vcd');
|
||||||
const blob = await response.blob();
|
const blob = await response.blob();
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -26,6 +27,8 @@
|
|||||||
reader.readAsArrayBuffer(blob);
|
reader.readAsArrayBuffer(blob);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
window.workerPath = 'worker.js';
|
||||||
|
window.workerRoot = '';
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
File diff suppressed because one or more lines are too long
BIN
public/vcd.wasm
BIN
public/vcd.wasm
Binary file not shown.
@ -1,9 +1,18 @@
|
|||||||
importScripts('vcd.js');
|
|
||||||
|
|
||||||
self.onmessage = async event => {
|
self.onmessage = async event => {
|
||||||
const arrayBuffer = event.data;
|
const { arrayBuffer, workerRoot } = event.data;
|
||||||
|
|
||||||
|
self.locateFile = wasmBinaryFile => {
|
||||||
|
if (workerRoot) {
|
||||||
|
return workerRoot + (workerRoot.endsWith('/') ? '': '/') + wasmBinaryFile;
|
||||||
|
} else {
|
||||||
|
return wasmBinaryFile;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
importScripts('vcd.js');
|
||||||
|
|
||||||
const vcdstream = await makeVcdStream();
|
const vcdstream = await makeVcdStream();
|
||||||
vcdstream.consume(arrayBuffer);
|
vcdstream.consume(arrayBuffer);
|
||||||
const info = vcdstream.getBasicInfo();
|
const info = vcdstream.getBasicInfo();
|
||||||
self.postMessage(info);
|
self.postMessage(info);
|
||||||
}
|
};
|
14
scripts/vscode-package.py
Normal file
14
scripts/vscode-package.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
os.system('npm run build')
|
||||||
|
for file in os.listdir('dist'):
|
||||||
|
if file.endswith('.vcd'):
|
||||||
|
os.remove('dist/' + file)
|
||||||
|
|
||||||
|
with open('./dist/index.html', 'r', encoding='utf-8') as fp:
|
||||||
|
html = fp.read()
|
||||||
|
|
||||||
|
html = html.replace("''", "'<workerRoot>'")
|
||||||
|
|
||||||
|
with open('./dist/index.html', 'w', encoding='utf-8') as fp:
|
||||||
|
fp.write(html)
|
@ -22,6 +22,7 @@ import { ElLoading } from 'element-plus';
|
|||||||
|
|
||||||
import { emitter, globalLookup, globalSetting } from '@/hook/global';
|
import { emitter, globalLookup, globalSetting } from '@/hook/global';
|
||||||
import { makeWaveView } from '@/hook/render';
|
import { makeWaveView } from '@/hook/render';
|
||||||
|
import { getCrossOriginWorkerURL } from '@/hook/network';
|
||||||
|
|
||||||
import Sidebar from '@/components/sidebar.vue';
|
import Sidebar from '@/components/sidebar.vue';
|
||||||
import RightNav from '@/components/right-nav.vue';
|
import RightNav from '@/components/right-nav.vue';
|
||||||
@ -83,13 +84,13 @@ onMounted(async () => {
|
|||||||
|
|
||||||
// 初始化载入 vcd 文件
|
// 初始化载入 vcd 文件
|
||||||
const arrayBuffer = await window.readVcdFile();
|
const arrayBuffer = await window.readVcdFile();
|
||||||
|
const url = await getCrossOriginWorkerURL(window.workerPath);
|
||||||
const worker = new Worker('worker.js', {
|
const worker = new Worker(url, {
|
||||||
name: 'vcd-stream',
|
name: 'vcd-stream',
|
||||||
type: 'classic'
|
type: 'classic'
|
||||||
});
|
});
|
||||||
|
|
||||||
worker.postMessage(arrayBuffer, [arrayBuffer]);
|
worker.postMessage({ arrayBuffer, workerRoot: window.workerRoot }, [arrayBuffer]);
|
||||||
|
|
||||||
worker.addEventListener('message', event => {
|
worker.addEventListener('message', event => {
|
||||||
const workerVars = event.data;
|
const workerVars = event.data;
|
||||||
|
@ -3,17 +3,42 @@
|
|||||||
<div class="usermanual">
|
<div class="usermanual">
|
||||||
<h2>{{ t('usermanual') }}</h2>
|
<h2>{{ t('usermanual') }}</h2>
|
||||||
<div class="usermanual-item">
|
<div class="usermanual-item">
|
||||||
<div v-html="t('usermanual.left-right-scroll.title')"></div>
|
<div><span class="iconfont icon-mouse"/><span class="iconfont icon-up-down"/></div>
|
||||||
<div>{{ t('usermanual.left-right-scroll.caption') }}</div>
|
<div>{{ t('usermanual.left-right-scroll.caption') }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="usermanual-item">
|
<div class="usermanual-item">
|
||||||
<div v-html="t('usermanual.up-down-scroll.title')"></div>
|
<div><span class="iconfont icon-mouse"/><span class="iconfont icon-left-right"/></div>
|
||||||
<div>{{ t('usermanual.up-down-scroll.caption') }}</div>
|
<div>{{ t('usermanual.up-down-scroll.caption') }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="usermanual-item">
|
<div class="usermanual-item">
|
||||||
<div v-html="t('usermanual.xscale.title')"></div>
|
<div><span class="iconfont icon-ctrl"/> + <span class="iconfont icon-mouse"/><span class="iconfont icon-up-down"/></div>
|
||||||
<div>{{ t('usermanual.xscale.caption') }}</div>
|
<div>{{ t('usermanual.xscale.caption') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="usermanual-item">
|
||||||
|
<div><span class="iconfont icon-shift"/> + <span class="iconfont icon-mouse"/><span class="iconfont icon-up-down"/></div>
|
||||||
|
<div>{{ t('usermanual.up-down-scroll.caption') }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="usermanual-item" v-if="platform.startsWith('Mac')">
|
||||||
|
<div><span class="iconfont icon-command"/> + <span class="iconfont icon-mouse"/><span class="iconfont icon-up-down"/></div>
|
||||||
|
<div>{{ t('usermanual.xscale.caption') }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="usermanual-item" v-else>
|
||||||
|
<div><span class="iconfont icon-ctrl"/> + <span class="iconfont icon-equal"/> / <span class="iconfont icon-minus"/></div>
|
||||||
|
<div>{{ t('usermanual.xscale.caption') }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="usermanual-item">
|
||||||
|
<div><span class="iconfont icon-shift"/> + <span class="iconfont icon-arrow-up"/> / <span class="iconfont icon-arrow-down"/></div>
|
||||||
|
<div>{{ t('usermanual.left-right-scroll.caption') }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="usermanual-item">
|
||||||
|
<div><span class="iconfont icon-shift"/> + <span class="iconfont icon-arrow-left"/> / <span class="iconfont icon-arrow-right"/></div>
|
||||||
|
<div>{{ t('usermanual.up-down-scroll.caption') }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
@ -44,11 +69,14 @@ export default {
|
|||||||
window.open(url, '_blank');
|
window.open(url, '_blank');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const platform = navigator.platform;
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
goto,
|
goto,
|
||||||
t
|
t,
|
||||||
|
platform
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,6 @@ export default {
|
|||||||
/* 沿着纵轴(垂直方向)对齐 */
|
/* 沿着纵轴(垂直方向)对齐 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.time-scale-value {}
|
|
||||||
|
|
||||||
.time-scale-line {
|
.time-scale-line {
|
||||||
width: 1px;
|
width: 1px;
|
||||||
|
@ -52,7 +52,6 @@ export default {
|
|||||||
emitter.emit('tree-view', signals);
|
emitter.emit('tree-view', signals);
|
||||||
// color change into selected
|
// color change into selected
|
||||||
globalLookup.currentModule = module;
|
globalLookup.currentModule = module;
|
||||||
console.log(module);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const expandManage = reactive({
|
const expandManage = reactive({
|
||||||
|
@ -107,6 +107,7 @@ export default {
|
|||||||
padding-left: 3px;
|
padding-left: 3px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
51
src/hook/network.js
Normal file
51
src/hook/network.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
const type = 'application/javascript';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} originalWorkerUrl
|
||||||
|
* @param {{
|
||||||
|
* useBlob?: boolean
|
||||||
|
* skipSameOrigin?: boolean
|
||||||
|
* }} options
|
||||||
|
* @returns {Promise<string>}
|
||||||
|
*/
|
||||||
|
async function getCrossOriginWorkerURL (originalWorkerUrl, options = {}) {
|
||||||
|
const skipSameOrigin = options.skipSameOrigin || true;
|
||||||
|
const useBlob = options.useBlob || true;
|
||||||
|
|
||||||
|
// 本来就是同源的,不需要额外进行处理,直接返回
|
||||||
|
if (!originalWorkerUrl.includes('://') || originalWorkerUrl.includes(window.location.origin)) {
|
||||||
|
return originalWorkerUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 worker 的 js 代码
|
||||||
|
const res = await fetch(originalWorkerUrl);
|
||||||
|
const workerJsCode = await res.text();
|
||||||
|
|
||||||
|
// worker 所在的文件夹 url
|
||||||
|
const workerPath = new URL(originalWorkerUrl).href.split('/');
|
||||||
|
workerPath.pop();
|
||||||
|
|
||||||
|
// 给 importScripts 的每一个引入的js文件增加 workerPath 组成绝对路径
|
||||||
|
const importScriptsFix = `const _importScripts = importScripts;
|
||||||
|
const _fixImports = (url) => new URL(url, '${workerPath.join('/') + '/'}').href;
|
||||||
|
|
||||||
|
importScripts = (...urls) => _importScripts(...urls.map(_fixImports));
|
||||||
|
`;
|
||||||
|
|
||||||
|
// 以 MIME 协议组成 blob,从而进行装载
|
||||||
|
let resultURL = `data:${type},` + encodeURIComponent(importScriptsFix + workerJsCode);
|
||||||
|
if (useBlob) {
|
||||||
|
// 在外面再套一层 importScripts,这样第二次请求得到的 worker 就不是 blob worker 了
|
||||||
|
// 直接使用 createObjectURL 请求一个 worker 的源码是不行的,因为这样得到的 blob worker
|
||||||
|
// 会有原本 worker 的 feature 无法使用
|
||||||
|
resultURL = URL.createObjectURL(
|
||||||
|
new Blob([`importScripts("${resultURL}")`], { type })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return resultURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
getCrossOriginWorkerURL
|
||||||
|
}
|
@ -1,8 +1,13 @@
|
|||||||
import { globalLookup, globalSetting } from "./global";
|
import { globalLookup, globalSetting } from "./global";
|
||||||
import { domContainer, pluginRenderTimeGrid, pluginRenderValues, mountTree,
|
import { domContainer, pluginRenderTimeGrid, pluginRenderValues, mountTree,
|
||||||
genOnWheel, genKeyHandler, keyEvent } from './wave-view';
|
eventHandler } from './wave-view';
|
||||||
|
|
||||||
|
import registerWheelEvent from "./wave-view/wheel-event";
|
||||||
|
import { registerTouchendEvent, registerTouchmoveEvent, registerTouchstartEvent } from "./wave-view/touch-event";
|
||||||
|
|
||||||
|
|
||||||
import { findCurrentSignalValue } from './utils';
|
import { findCurrentSignalValue } from './utils';
|
||||||
|
import { registerKeyEvent } from "./wave-view/key-event";
|
||||||
|
|
||||||
let mainRenderEl = null;
|
let mainRenderEl = null;
|
||||||
const canvasMap = new Map();
|
const canvasMap = new Map();
|
||||||
@ -36,6 +41,8 @@ function pluginLocalStore(desc, pstate /* , els */) {
|
|||||||
* @param {HTMLElement} parentElement
|
* @param {HTMLElement} parentElement
|
||||||
*/
|
*/
|
||||||
function makeWaveView(parentElement) {
|
function makeWaveView(parentElement) {
|
||||||
|
const platform = navigator.platform;
|
||||||
|
|
||||||
if (!parentElement) {
|
if (!parentElement) {
|
||||||
parentElement = getMainRenderEl();
|
parentElement = getMainRenderEl();
|
||||||
}
|
}
|
||||||
@ -57,7 +64,29 @@ function makeWaveView(parentElement) {
|
|||||||
console.log('updater');
|
console.log('updater');
|
||||||
};
|
};
|
||||||
|
|
||||||
container.elo.container.addEventListener('wheel', genOnWheel(parentElement, container.pstate, globalLookup, keyEvent));
|
// 注册基本的响应事件
|
||||||
|
container.elo.container.addEventListener('wheel',
|
||||||
|
registerWheelEvent(parentElement, container.pstate, globalLookup, eventHandler)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 好像必须是 document
|
||||||
|
document.addEventListener('keydown',
|
||||||
|
registerKeyEvent(parentElement, container.pstate, globalLookup, eventHandler)
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: 触控支持
|
||||||
|
// container.elo.container.addEventListener('touchstart',
|
||||||
|
// registerTouchstartEvent(parentElement, container.pstate, globalLookup, eventHandler)
|
||||||
|
// );
|
||||||
|
|
||||||
|
// container.elo.container.addEventListener('touchmove',
|
||||||
|
// registerTouchmoveEvent(parentElement, container.pstate, globalLookup, eventHandler)
|
||||||
|
// );
|
||||||
|
|
||||||
|
// container.elo.container.addEventListener('touchend',
|
||||||
|
// registerTouchendEvent(parentElement, container.pstate, globalLookup, eventHandler)
|
||||||
|
// );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -78,7 +107,7 @@ function toggleRender(signal) {
|
|||||||
} else {
|
} else {
|
||||||
globalLookup.currentWires.add(signal);
|
globalLookup.currentWires.add(signal);
|
||||||
const signalItem = globalLookup.chango[signal.link];
|
const signalItem = globalLookup.chango[signal.link];
|
||||||
console.log(signalItem, signal.link);
|
// console.log(signalItem, signal.link);
|
||||||
|
|
||||||
const { wave, kind } = signalItem;
|
const { wave, kind } = signalItem;
|
||||||
const time = globalLookup.currentTime;
|
const time = globalLookup.currentTime;
|
||||||
|
@ -183,7 +183,7 @@ const domContainer = (obj) => {
|
|||||||
// TODO : 使用更新的属性替换 contentRect
|
// TODO : 使用更新的属性替换 contentRect
|
||||||
// 未来版本 contentRect 可能会被丢弃
|
// 未来版本 contentRect 可能会被丢弃
|
||||||
let { width, height } = entry.contentRect;
|
let { width, height } = entry.contentRect;
|
||||||
console.log(width, height);
|
// console.log(width, height);
|
||||||
// height = height || 888;
|
// height = height || 888;
|
||||||
// console.log('resizeObserver', width, height);
|
// console.log('resizeObserver', width, height);
|
||||||
resizeHandler(width, height);
|
resizeHandler(width, height);
|
||||||
|
@ -16,10 +16,10 @@ const xScaleLevels = {
|
|||||||
|
|
||||||
// TODO: 优化横向滚动体验
|
// TODO: 优化横向滚动体验
|
||||||
const xOffsetLevel = {
|
const xOffsetLevel = {
|
||||||
1: 500,
|
1: 0.035,
|
||||||
2: 20,
|
2: 0.1,
|
||||||
3: 5,
|
3: 0.2,
|
||||||
4: 1,
|
4: 0.4,
|
||||||
5: 0.5
|
5: 0.5
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -31,12 +31,12 @@ const yOffsetLevel = {
|
|||||||
5: 320
|
5: 320
|
||||||
};
|
};
|
||||||
|
|
||||||
const pluso = {
|
const scaleUp = {
|
||||||
desc: 'Zoom in time',
|
desc: 'Zoom in time',
|
||||||
fn: pstate => xScaleUpdate(pstate, () => pstate.xScale * xScaleLevels[globalSetting.HorizontalScalingRatio])
|
fn: pstate => xScaleUpdate(pstate, () => pstate.xScale * xScaleLevels[globalSetting.HorizontalScalingRatio])
|
||||||
};
|
};
|
||||||
|
|
||||||
const minuso = {
|
const scaleDown = {
|
||||||
desc: 'Zoom out time',
|
desc: 'Zoom out time',
|
||||||
fn: pstate => xScaleUpdate(pstate, () => pstate.xScale / xScaleLevels[globalSetting.HorizontalScalingRatio])
|
fn: pstate => xScaleUpdate(pstate, () => pstate.xScale / xScaleLevels[globalSetting.HorizontalScalingRatio])
|
||||||
};
|
};
|
||||||
@ -49,11 +49,19 @@ const fullo = {
|
|||||||
const scroll = {
|
const scroll = {
|
||||||
left: {
|
left: {
|
||||||
desc: 'Scroll into the past',
|
desc: 'Scroll into the past',
|
||||||
fn: pstate => xOffsetUpdate(pstate, () => pstate.xOffset + pstate.time / xOffsetLevel[globalSetting.HorizontalRollRatio])
|
fn: pstate => {
|
||||||
|
const offset = xOffsetLevel[globalSetting.HorizontalRollRatio] * pstate.width;
|
||||||
|
// console.log(`change from ${pstate.xOffset} to ${pstate.xOffset + pstate.time / xOffsetLevel[globalSetting.HorizontalRollRatio]}`);
|
||||||
|
return xOffsetUpdate(pstate, () => pstate.xOffset + offset);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
desc: 'Scroll into the future',
|
desc: 'Scroll into the future',
|
||||||
fn: pstate => xOffsetUpdate(pstate, () => pstate.xOffset - pstate.time / xOffsetLevel[globalSetting.HorizontalRollRatio])
|
fn: pstate => {
|
||||||
|
// console.log(`change from ${pstate.xOffset} to ${pstate.xOffset - pstate.time / xOffsetLevel[globalSetting.HorizontalRollRatio]}`);
|
||||||
|
const offset = xOffsetLevel[globalSetting.HorizontalRollRatio] * pstate.width;
|
||||||
|
return xOffsetUpdate(pstate, () => pstate.xOffset - offset)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
up: {
|
up: {
|
||||||
desc: 'scroll up',
|
desc: 'scroll up',
|
||||||
@ -73,31 +81,16 @@ const editable = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
// Alt + <, >. left / right
|
|
||||||
// 'Alt+,': scroll.left,
|
|
||||||
// 'Alt+.': scroll.right,
|
|
||||||
|
|
||||||
// // Alt + [ ] home / end
|
|
||||||
// 'Alt+[': { desc: 'Jump to beginning of time', fn: pstate => xOffsetUpdate(pstate, pstate.sidebarWidth) }, // Home
|
|
||||||
|
|
||||||
// 'Alt+]': { desc: 'Jump to end time', fn: pstate => xOffsetUpdate(pstate, pstate.width - pstate.xScale * pstate.time) }, // End
|
|
||||||
|
|
||||||
// // ALT + - +
|
|
||||||
// 'Alt+=': pluso, // '+': pluso, '=': pluso,
|
|
||||||
// 'Alt+-': minuso, // '-': minuso, '_': minuso,
|
|
||||||
// 'Alt+0': fullo, // 'Shift+f': fullo, F: fullo, 'Shift+F': fullo,
|
|
||||||
|
|
||||||
// wheel
|
// wheel
|
||||||
scrollLeft: scroll.left,
|
scrollLeft: scroll.left,
|
||||||
scrollRight: scroll.right,
|
scrollRight: scroll.right,
|
||||||
scrollUp: scroll.up,
|
scrollUp: scroll.up,
|
||||||
scrollDown: scroll.down,
|
scrollDown: scroll.down,
|
||||||
|
scaleUp: scaleUp,
|
||||||
|
scaleDown: scaleDown,
|
||||||
|
|
||||||
'Shift+icon:scrollUp': scroll.left,
|
// key
|
||||||
'Shift+icon:scrollDown': scroll.right,
|
|
||||||
'Ctrl+icon:scrollUp': pluso,
|
|
||||||
'Ctrl+icon:scrollDown': minuso,
|
|
||||||
|
|
||||||
|
|
||||||
nop: { fn: () => false }
|
nop: { fn: () => false }
|
||||||
};
|
};
|
@ -1,31 +0,0 @@
|
|||||||
const { keyName } = require('w3c-keyname');
|
|
||||||
|
|
||||||
const executeKeyHandler = (key, keyEvent, pstate, cm) => {
|
|
||||||
return (keyEvent[key] || keyEvent.nop).fn(pstate, cm);
|
|
||||||
};
|
|
||||||
|
|
||||||
const genKeyHandler = (div, pstate, deso, cm, keyEvent, plugins) => {
|
|
||||||
return event => {
|
|
||||||
|
|
||||||
const modifier = (
|
|
||||||
(event.ctrlKey ? 'Ctrl+' : '') +
|
|
||||||
(event.shiftKey ? 'Shift+' : '') +
|
|
||||||
(event.altKey ? 'Alt+' : '')
|
|
||||||
);
|
|
||||||
// const key = modifier + event.key;
|
|
||||||
const key = modifier + keyName(event);
|
|
||||||
|
|
||||||
if (executeKeyHandler(key, keyEvent, pstate, cm)) {
|
|
||||||
event.stopPropagation();
|
|
||||||
if (plugins != undefined) {
|
|
||||||
plugins.map(fn => fn(key, event));
|
|
||||||
}
|
|
||||||
deso.render();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default {
|
|
||||||
executeKeyHandler,
|
|
||||||
genKeyHandler
|
|
||||||
};
|
|
@ -1,45 +0,0 @@
|
|||||||
const genOnWheel = (element, pstate, deso, keyEvent, plugins) =>
|
|
||||||
event => {
|
|
||||||
const { deltaX, deltaY } = event;
|
|
||||||
if (event.ctrlKey) {
|
|
||||||
const key = (deltaY < 0)
|
|
||||||
? 'Ctrl+icon:scrollUp'
|
|
||||||
: ((deltaY > 0) ? 'Ctrl+icon:scrollDown' : 'nop');
|
|
||||||
if (keyEvent[key].fn(pstate)) {
|
|
||||||
if (plugins != undefined) {
|
|
||||||
plugins.map(fn => fn(key, event));
|
|
||||||
}
|
|
||||||
deso.render({ type: 'action' });
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
} else if (event.shiftKey) {
|
|
||||||
const key = (deltaY < 0) ? 'Shift+icon:scrollUp' : ((deltaY > 0) ? 'Shift+icon:scrollDown' : 'nop');
|
|
||||||
if (keyEvent[key].fn(pstate)) {
|
|
||||||
if (plugins != undefined) {
|
|
||||||
plugins.map(fn => fn(key, event));
|
|
||||||
}
|
|
||||||
deso.render({ type: 'action' });
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
} else if (deltaX !== 0 && deltaY === 0) {
|
|
||||||
const key = (deltaX < 0) ? 'scrollLeft': 'scrollRight';
|
|
||||||
if (keyEvent[key].fn(pstate)) {
|
|
||||||
if (plugins != undefined) {
|
|
||||||
plugins.map(fn => fn(key, event));
|
|
||||||
}
|
|
||||||
deso.render({ type: 'action' });
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
} else if (deltaX === 0 && deltaY !== 0) {
|
|
||||||
const key = (deltaY < 0) ? 'scrollUp': 'scrollDown';
|
|
||||||
if (keyEvent[key].fn(pstate)) {
|
|
||||||
if (plugins != undefined) {
|
|
||||||
plugins.map(fn => fn(key, event));
|
|
||||||
}
|
|
||||||
deso.render({ type: 'action' });
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default genOnWheel;
|
|
@ -3,10 +3,9 @@ import getListing from './get-listing';
|
|||||||
import domContainer from './dom-container';
|
import domContainer from './dom-container';
|
||||||
import pluginRenderValues from './plugin-render-values';
|
import pluginRenderValues from './plugin-render-values';
|
||||||
import pluginRenderTimeGrid from './plugin-render-time-grid';
|
import pluginRenderTimeGrid from './plugin-render-time-grid';
|
||||||
import keyEvent from './keyEvent';
|
import eventHandler from './event-handler';
|
||||||
import mountTree from './mount-tree';
|
import mountTree from './mount-tree';
|
||||||
import genKeyHandler from './gen-key-handler';
|
import registerWheelEvent from './wheel-event';
|
||||||
import genOnWheel from './gen-on-wheel';
|
|
||||||
import xOffsetUpdate from './x-offset-update';
|
import xOffsetUpdate from './x-offset-update';
|
||||||
import getX from './get-x';
|
import getX from './get-x';
|
||||||
import getT from './get-t';
|
import getT from './get-t';
|
||||||
@ -18,10 +17,9 @@ export {
|
|||||||
domContainer,
|
domContainer,
|
||||||
pluginRenderValues,
|
pluginRenderValues,
|
||||||
pluginRenderTimeGrid,
|
pluginRenderTimeGrid,
|
||||||
keyEvent,
|
eventHandler,
|
||||||
mountTree,
|
mountTree,
|
||||||
genKeyHandler,
|
registerWheelEvent,
|
||||||
genOnWheel,
|
|
||||||
xOffsetUpdate,
|
xOffsetUpdate,
|
||||||
getX,
|
getX,
|
||||||
getT
|
getT
|
||||||
|
101
src/hook/wave-view/jsdoc.js
Normal file
101
src/hook/wave-view/jsdoc.js
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* @typedef {Object} WaveElements
|
||||||
|
* @property {HTMLDivElement} grid
|
||||||
|
* @property {HTMLDivElement} view
|
||||||
|
* @property {HTMLDivElement} values
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* @typedef {Object} ChangoItem
|
||||||
|
* @property {string} kind
|
||||||
|
* @property {Array<number | string>} wave
|
||||||
|
* @property {WebGLVertexArrayObject} lineVao
|
||||||
|
* @property {WebGLVertexArrayObject} maskVao
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 装载在 globalLookup 中的记录 vcd 数据的字典
|
||||||
|
* @typedef {Record<string, ChangoItem>} Chango
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* @typedef {Object} WireItem
|
||||||
|
* @property {string} kind
|
||||||
|
* @property {string} link
|
||||||
|
* @property {string} name
|
||||||
|
* @property {number} size
|
||||||
|
* @property {WireItem} parent
|
||||||
|
* @property {string} type
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* @typedef {Array<{ ref: string }>} View
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* @typedef {Set<WireItem>} CurrentWires
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* @typedef {Object} GlobalLookup
|
||||||
|
* @property {Chango} chango
|
||||||
|
* @property {View} view
|
||||||
|
* @property {CurrentWires} currentWires
|
||||||
|
* @property {number} time
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* @typedef {Object} Pstate
|
||||||
|
* @property {number} width
|
||||||
|
* @property {number} height
|
||||||
|
* @property {number} xScale
|
||||||
|
* @property {number} xOffset
|
||||||
|
* @property {number} yOffset
|
||||||
|
* @property {number} yStep
|
||||||
|
* @property {number} yDuty
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* @typedef {Object} Rgba
|
||||||
|
* @property {number} red
|
||||||
|
* @property {number} green
|
||||||
|
* @property {number} blue
|
||||||
|
* @property {number} alpha
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* @typedef {Object} Updater
|
||||||
|
* @property {number} index
|
||||||
|
* @property {Rgba} rgba
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* @typedef {Object} RenderConfig
|
||||||
|
* @property {'common' | 'action' | undefined} type
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} Handler
|
||||||
|
* @property {string} desc
|
||||||
|
* @property {(arg1: Pstate, arg2: any) => boolean} fn
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} Deso
|
||||||
|
* @property {(config: RenderConfig) => void} render
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {'scrollLeft' | 'scrollRight' | 'scrollUp' | 'scrollDown' | 'scaleUp' | 'scaleDown'} EventHandlerKind
|
||||||
|
*/
|
163
src/hook/wave-view/key-event.js
Normal file
163
src/hook/wave-view/key-event.js
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
|
||||||
|
const platform = navigator.platform;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {WaveElements} element
|
||||||
|
* @param {Pstate} pstate
|
||||||
|
* @param {Deso} deso
|
||||||
|
* @param {Record<EventHandlerKind, Handler>} eventHandler
|
||||||
|
* @param {KeyboardEvent} event
|
||||||
|
*/
|
||||||
|
function windowsKeydown(element, pstate, deso, eventHandler, event) {
|
||||||
|
if (event.ctrlKey) {
|
||||||
|
if (event.key === '=') {
|
||||||
|
eventHandler['scaleUp'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
} else if (event.key === '-') {
|
||||||
|
eventHandler['scaleDown'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.shiftKey) {
|
||||||
|
switch (event.key) {
|
||||||
|
case 'ArrowLeft':
|
||||||
|
eventHandler['scrollLeft'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
break;
|
||||||
|
case 'ArrowRight':
|
||||||
|
eventHandler['scrollRight'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
break;
|
||||||
|
case 'ArrowUp':
|
||||||
|
eventHandler['scrollUp'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
break;
|
||||||
|
case 'ArrowDown':
|
||||||
|
eventHandler['scrollDown'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {WaveElements} element
|
||||||
|
* @param {Pstate} pstate
|
||||||
|
* @param {Deso} deso
|
||||||
|
* @param {Record<EventHandlerKind, Handler>} eventHandler
|
||||||
|
* @param {KeyboardEvent} event
|
||||||
|
*/
|
||||||
|
function linuxKeydown(element, pstate, deso, eventHandler, event) {
|
||||||
|
if (event.ctrlKey) {
|
||||||
|
if (event.key === '=') {
|
||||||
|
eventHandler['scaleUp'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
} else if (event.key === '-') {
|
||||||
|
eventHandler['scaleDown'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.shiftKey) {
|
||||||
|
switch (event.key) {
|
||||||
|
case 'ArrowLeft':
|
||||||
|
eventHandler['scrollLeft'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
break;
|
||||||
|
case 'ArrowRight':
|
||||||
|
eventHandler['scrollRight'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
break;
|
||||||
|
case 'ArrowUp':
|
||||||
|
eventHandler['scrollUp'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
break;
|
||||||
|
case 'ArrowDown':
|
||||||
|
eventHandler['scrollDown'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {WaveElements} element
|
||||||
|
* @param {Pstate} pstate
|
||||||
|
* @param {Deso} deso
|
||||||
|
* @param {Record<EventHandlerKind, Handler>} eventHandler
|
||||||
|
* @param {KeyboardEvent} event
|
||||||
|
*/
|
||||||
|
function macOsKeydown(element, pstate, deso, eventHandler, event) {
|
||||||
|
if (event.metaKey) {
|
||||||
|
if (event.key === '=') {
|
||||||
|
eventHandler['scaleUp'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
} else if (event.key === '-') {
|
||||||
|
eventHandler['scaleDown'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.shiftKey) {
|
||||||
|
switch (event.key) {
|
||||||
|
case 'ArrowLeft':
|
||||||
|
eventHandler['scrollLeft'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
break;
|
||||||
|
case 'ArrowRight':
|
||||||
|
eventHandler['scrollRight'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
break;
|
||||||
|
case 'ArrowUp':
|
||||||
|
eventHandler['scrollUp'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
break;
|
||||||
|
case 'ArrowDown':
|
||||||
|
eventHandler['scrollDown'].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {WaveElements} element
|
||||||
|
* @param {Pstate} pstate
|
||||||
|
* @param {Deso} deso
|
||||||
|
* @param {Record<string, Handler>} eventHandler
|
||||||
|
* @returns {(event: KeyboardEvent) => void}
|
||||||
|
*/
|
||||||
|
function registerKeyEvent(element, pstate, deso, eventHandler) {
|
||||||
|
const platform = navigator.platform;
|
||||||
|
if (platform.startsWith('Win')) {
|
||||||
|
return event => windowsKeydown(element, pstate, deso, eventHandler, event);
|
||||||
|
} else if (platform.startsWith('Linux')) {
|
||||||
|
return event => linuxKeydown(element, pstate, deso, eventHandler, event);
|
||||||
|
} else if (platform.startsWith('Mac')) {
|
||||||
|
return event => macOsKeydown(element, pstate, deso, eventHandler, event);
|
||||||
|
} else {
|
||||||
|
throw Error('不支持的操作系统!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export {
|
||||||
|
registerKeyEvent
|
||||||
|
};
|
@ -3,46 +3,15 @@ import { globalSetting, globalStyle } from '../global';
|
|||||||
import { gl_Colors, gl_Shifts, gl_Shifts_for_bar, gl_Shifts_map, gl_WidthShifts, barShift, getRatio, screenHeightPixel } from './render-utils.js';
|
import { gl_Colors, gl_Shifts, gl_Shifts_for_bar, gl_Shifts_map, gl_WidthShifts, barShift, getRatio, screenHeightPixel } from './render-utils.js';
|
||||||
import { vertexShader, fragmentShader } from './render-shader.js';
|
import { vertexShader, fragmentShader } from './render-shader.js';
|
||||||
|
|
||||||
|
|
||||||
// const { ChangoItem } = require('./types.d.ts');
|
// const { ChangoItem } = require('./types.d.ts');
|
||||||
|
|
||||||
|
|
||||||
class WebGL2WaveRender {
|
class WebGL2WaveRender {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {{
|
* @param {WaveElements} elements
|
||||||
* grid: HTMLDivElement,
|
* @param {GlobalLookup} globalLookup
|
||||||
* view: HTMLDivElement,
|
* @param {Pstate} pstate
|
||||||
* values: HTMLDivElement
|
* @param {Array} plugins
|
||||||
* }} elements
|
|
||||||
* @param {{
|
|
||||||
* chango: Record<string, {
|
|
||||||
* kind: string,
|
|
||||||
* wave: Array<number | string>,
|
|
||||||
* lineVao: WebGLVertexArrayObject
|
|
||||||
* maskVao: WebGLVertexArrayObject
|
|
||||||
* }>
|
|
||||||
* view: Array<{ ref: string }>,
|
|
||||||
* currentWires: Set<{
|
|
||||||
* kind: string,
|
|
||||||
* link: string,
|
|
||||||
* name: string,
|
|
||||||
* size: number,
|
|
||||||
* parent: object,
|
|
||||||
* type: string
|
|
||||||
* }>,
|
|
||||||
* time: number
|
|
||||||
* }} globalLookup
|
|
||||||
* @param {{
|
|
||||||
* width: number,
|
|
||||||
* height: number,
|
|
||||||
* xScale: number,
|
|
||||||
* xOffset: number,
|
|
||||||
* yOffset: number,
|
|
||||||
* yStep: number,
|
|
||||||
* yDuty: number
|
|
||||||
* }} pstate
|
|
||||||
* @param { Array } plugins
|
|
||||||
*/
|
*/
|
||||||
constructor(elements, globalLookup, pstate, plugins) {
|
constructor(elements, globalLookup, pstate, plugins) {
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
@ -144,9 +113,6 @@ class WebGL2WaveRender {
|
|||||||
} else if (kind === 'vec') {
|
} else if (kind === 'vec') {
|
||||||
const { lineVertices, maskVertices } = this.makeVecVertex(wave, time);
|
const { lineVertices, maskVertices } = this.makeVecVertex(wave, time);
|
||||||
return { lineVertices, maskVertices };
|
return { lineVertices, maskVertices };
|
||||||
} else if (kind === '') {
|
|
||||||
const { lineVertices, maskVertices } = this.makeVecVertex(wave, time);
|
|
||||||
return { lineVertices, maskVertices };
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
lineVertices: undefined,
|
lineVertices: undefined,
|
||||||
@ -277,7 +243,7 @@ class WebGL2WaveRender {
|
|||||||
perspectivePoints.push({ x: t1, y: renderParam1.y, color: renderParam1.color });
|
perspectivePoints.push({ x: t1, y: renderParam1.y, color: renderParam1.color });
|
||||||
perspectivePoints.push({ x: t2, y: renderParam1.y, color: renderParam1.color });
|
perspectivePoints.push({ x: t2, y: renderParam1.y, color: renderParam1.color });
|
||||||
} else {
|
} else {
|
||||||
const lastPoint = perspectivePoints.at(-1);
|
const lastPoint = perspectivePoints[perspectivePoints.length - 1];
|
||||||
if ((lastPoint.y !== renderParam1.y) || (lastPoint.color !== renderParam1.color)) {
|
if ((lastPoint.y !== renderParam1.y) || (lastPoint.color !== renderParam1.color)) {
|
||||||
perspectivePoints.push({ x: t1, y: renderParam1.y, color: renderParam1.color });
|
perspectivePoints.push({ x: t1, y: renderParam1.y, color: renderParam1.color });
|
||||||
}
|
}
|
||||||
@ -288,7 +254,7 @@ class WebGL2WaveRender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 确保最后一个点延申到了 time
|
// 确保最后一个点延申到了 time
|
||||||
const lastPoint = perspectivePoints.at(-1);
|
const lastPoint = perspectivePoints[perspectivePoints.length - 1];
|
||||||
if (lastPoint.x < time) {
|
if (lastPoint.x < time) {
|
||||||
perspectivePoints.push({ x: time, y: lastPoint.y, color: lastPoint.color });
|
perspectivePoints.push({ x: time, y: lastPoint.y, color: lastPoint.color });
|
||||||
}
|
}
|
||||||
@ -520,15 +486,7 @@ class WebGL2WaveRender {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {Array<{
|
* @param {Array<Updater>} updaters
|
||||||
* index: number
|
|
||||||
* rgba: {
|
|
||||||
* red: number,
|
|
||||||
* green: number,
|
|
||||||
* blue: number,
|
|
||||||
* alpha: number
|
|
||||||
* }
|
|
||||||
* }>} updaters
|
|
||||||
* @param {{
|
* @param {{
|
||||||
* updateMask: boolean
|
* updateMask: boolean
|
||||||
* }} config
|
* }} config
|
||||||
@ -559,9 +517,7 @@ class WebGL2WaveRender {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {{
|
* @param {RenderConfig} renderConfig
|
||||||
* type: 'common' | 'action'
|
|
||||||
* } | undefined} renderConfig
|
|
||||||
*/
|
*/
|
||||||
render(renderConfig) {
|
render(renderConfig) {
|
||||||
renderConfig = renderConfig || { type: 'common' };
|
renderConfig = renderConfig || { type: 'common' };
|
||||||
|
127
src/hook/wave-view/touch-event.js
Normal file
127
src/hook/wave-view/touch-event.js
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
// 触控事件
|
||||||
|
|
||||||
|
|
||||||
|
const platform = navigator.platform;
|
||||||
|
const touchState = {
|
||||||
|
startX: undefined,
|
||||||
|
startY: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: 完成这个 和 手势控制
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {WaveElements} element
|
||||||
|
* @param {Pstate} pstate
|
||||||
|
* @param {Deso} deso
|
||||||
|
* @param {Record<string, Handler>} eventHandler
|
||||||
|
* @param {TouchEvent} event
|
||||||
|
*/
|
||||||
|
function macTouchmove(element, pstate, deso, eventHandler, event) {
|
||||||
|
const touch = event.touches[0];
|
||||||
|
if (touch) {
|
||||||
|
const { pageX, pageY } = touch;
|
||||||
|
const deltaX = pageX - touchState.startX;
|
||||||
|
const deltaY = pageY - touchState.startY;
|
||||||
|
|
||||||
|
const updownKey = (deltaY < 0) ? 'scrollDown' : 'scrollUp';
|
||||||
|
const leftrightKey = (deltaX < 0) ? 'scrollRight' : 'scrollLeft';
|
||||||
|
|
||||||
|
eventHandler[updownKey].fn(pstate);
|
||||||
|
deso.render();
|
||||||
|
|
||||||
|
// eventHandler[leftrightKey].fn(pstate);
|
||||||
|
// deso.render();
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {WaveElements} element
|
||||||
|
* @param {Pstate} pstate
|
||||||
|
* @param {Deso} deso
|
||||||
|
* @param {Record<string, Handler>} eventHandler
|
||||||
|
* @param {TouchEvent} event
|
||||||
|
*/
|
||||||
|
function macTouchstart(element, pstate, deso, eventHandler, event) {
|
||||||
|
const touch = event.touches[0];
|
||||||
|
if (touch) {
|
||||||
|
const { pageX, pageY } = touch;
|
||||||
|
touchState.startX = pageX;
|
||||||
|
touchState.startY = pageY;
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {WaveElements} element
|
||||||
|
* @param {Pstate} pstate
|
||||||
|
* @param {Deso} deso
|
||||||
|
* @param {Record<string, Handler>} eventHandler
|
||||||
|
* @param {TouchEvent} event
|
||||||
|
*/
|
||||||
|
function macTouchend(element, pstate, deso, eventHandler, event) {
|
||||||
|
touchState.startX = undefined;
|
||||||
|
touchState.startY = undefined;
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {WaveElements} element
|
||||||
|
* @param {Pstate} pstate
|
||||||
|
* @param {Deso} deso
|
||||||
|
* @param {Record<string, Handler>} eventHandler
|
||||||
|
* @returns {(event: TouchEvent) => void}
|
||||||
|
*/
|
||||||
|
function registerTouchmoveEvent(element, pstate, deso, eventHandler) {
|
||||||
|
if (platform.startsWith('Mac')) {
|
||||||
|
// IOS
|
||||||
|
return event => macTouchmove(element, pstate, deso, eventHandler, event);
|
||||||
|
} else {
|
||||||
|
return event => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {WaveElements} element
|
||||||
|
* @param {Pstate} pstate
|
||||||
|
* @param {Deso} deso
|
||||||
|
* @param {Record<string, Handler>} eventHandler
|
||||||
|
* @returns {(event: TouchEvent) => void}
|
||||||
|
*/
|
||||||
|
function registerTouchstartEvent(element, pstate, deso, eventHandler) {
|
||||||
|
if (platform.startsWith('Mac')) {
|
||||||
|
return event => macTouchstart(element, pstate, deso, eventHandler, event);
|
||||||
|
} else {
|
||||||
|
return event => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {WaveElements} element
|
||||||
|
* @param {Pstate} pstate
|
||||||
|
* @param {Deso} deso
|
||||||
|
* @param {Record<string, Handler>} eventHandler
|
||||||
|
* @returns {(event: TouchEvent) => void}
|
||||||
|
*/
|
||||||
|
function registerTouchendEvent(element, pstate, deso, eventHandler) {
|
||||||
|
if (platform.startsWith('Mac')) {
|
||||||
|
return event => macTouchend(element, pstate, deso, eventHandler, event);
|
||||||
|
} else {
|
||||||
|
return event => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
registerTouchstartEvent,
|
||||||
|
registerTouchmoveEvent,
|
||||||
|
registerTouchendEvent
|
||||||
|
};
|
136
src/hook/wave-view/wheel-event.js
Normal file
136
src/hook/wave-view/wheel-event.js
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
// 鼠标滚轮事件
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {WaveElements} element
|
||||||
|
* @param {Pstate} pstate
|
||||||
|
* @param {Deso} deso
|
||||||
|
* @param {Record<string, Handler>} eventHandler
|
||||||
|
* @param {WheelEvent} event
|
||||||
|
*/
|
||||||
|
function windowsWheel(element, pstate, deso, eventHandler, event) {
|
||||||
|
const { deltaX, deltaY } = event;
|
||||||
|
if (event.ctrlKey) {
|
||||||
|
const key = (deltaY < 0)
|
||||||
|
? 'scaleUp'
|
||||||
|
: ((deltaY > 0) ? 'scaleDown' : 'nop');
|
||||||
|
|
||||||
|
if (eventHandler[key].fn(pstate)) {
|
||||||
|
deso.render({ type: 'action' });
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
} else if (event.shiftKey) {
|
||||||
|
const key = (deltaY < 0) ? 'scrollLeft' : ((deltaY > 0) ? 'scrollRight' : 'nop');
|
||||||
|
if (eventHandler[key].fn(pstate)) {
|
||||||
|
deso.render({ type: 'action' });
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
} else if (deltaX !== 0 && deltaY === 0) {
|
||||||
|
const key = (deltaX < 0) ? 'scrollLeft' : 'scrollRight';
|
||||||
|
if (eventHandler[key].fn(pstate)) {
|
||||||
|
deso.render({ type: 'action' });
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
} else if (deltaX === 0 && deltaY !== 0) {
|
||||||
|
const key = (deltaY < 0) ? 'scrollUp' : 'scrollDown';
|
||||||
|
if (eventHandler[key].fn(pstate)) {
|
||||||
|
deso.render({ type: 'action' });
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {WaveElements} element
|
||||||
|
* @param {Pstate} pstate
|
||||||
|
* @param {Deso} deso
|
||||||
|
* @param {Record<string, Handler>} eventHandler
|
||||||
|
* @param {WheelEvent} event
|
||||||
|
*/
|
||||||
|
function macOsWheel(element, pstate, deso, eventHandler, event) {
|
||||||
|
let { deltaX, deltaY } = event;
|
||||||
|
if (event.ctrlKey) {
|
||||||
|
const key = (deltaY < 0)
|
||||||
|
? 'scaleUp'
|
||||||
|
: ((deltaY > 0) ? 'scaleDown' : 'nop');
|
||||||
|
if (eventHandler[key].fn(pstate)) {
|
||||||
|
deso.render({ type: 'action' });
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
} else if (event.shiftKey) {
|
||||||
|
const key = (deltaX < 0) ? 'scrollLeft' : ((deltaX > 0) ? 'scrollRight' : 'nop');
|
||||||
|
if (eventHandler[key].fn(pstate)) {
|
||||||
|
deso.render({ type: 'action' });
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
}else if (deltaX !== 0 && deltaY === 0) {
|
||||||
|
const key = (deltaX < 0) ? 'scrollLeft' : 'scrollRight';
|
||||||
|
if (eventHandler[key].fn(pstate)) {
|
||||||
|
deso.render({ type: 'action' });
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
} else if (deltaX === 0 && deltaY !== 0) {
|
||||||
|
const key = (deltaY < 0) ? 'scrollUp' : 'scrollDown';
|
||||||
|
if (eventHandler[key].fn(pstate)) {
|
||||||
|
deso.render({ type: 'action' });
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {WaveElements} element
|
||||||
|
* @param {Pstate} pstate
|
||||||
|
* @param {Deso} deso
|
||||||
|
* @param {Record<string, Handler>} eventHandler
|
||||||
|
* @param {WheelEvent} event
|
||||||
|
*/
|
||||||
|
function linuxWheel(element, pstate, deso, eventHandler, event) {
|
||||||
|
const { deltaX, deltaY } = event;
|
||||||
|
if (event.ctrlKey) {
|
||||||
|
const key = (deltaY < 0)
|
||||||
|
? 'scaleUp'
|
||||||
|
: ((deltaY > 0) ? 'scaleDown' : 'nop');
|
||||||
|
if (eventHandler[key].fn(pstate)) {
|
||||||
|
deso.render({ type: 'action' });
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
} else if (event.shiftKey) {
|
||||||
|
const key = (deltaY < 0) ? 'scrollLeft' : ((deltaY > 0) ? 'scrollRight' : 'nop');
|
||||||
|
if (eventHandler[key].fn(pstate)) {
|
||||||
|
deso.render({ type: 'action' });
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
} else if (deltaX !== 0 && deltaY === 0) {
|
||||||
|
const key = (deltaX < 0) ? 'scrollLeft' : 'scrollRight';
|
||||||
|
if (eventHandler[key].fn(pstate)) {
|
||||||
|
deso.render({ type: 'action' });
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
} else if (deltaX === 0 && deltaY !== 0) {
|
||||||
|
const key = (deltaY < 0) ? 'scrollUp' : 'scrollDown';
|
||||||
|
if (eventHandler[key].fn(pstate)) {
|
||||||
|
deso.render({ type: 'action' });
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerWheelEvent(element, pstate, deso, eventHandler) {
|
||||||
|
const platform = navigator.platform;
|
||||||
|
if (platform.startsWith('Win')) {
|
||||||
|
return event => windowsWheel(element, pstate, deso, eventHandler, event);
|
||||||
|
} else if (platform.startsWith('Linux')) {
|
||||||
|
return event => linuxWheel(element, pstate, deso, eventHandler, event);
|
||||||
|
} else if (platform.startsWith('Mac')) {
|
||||||
|
return event => macOsWheel(element, pstate, deso, eventHandler, event);
|
||||||
|
} else {
|
||||||
|
throw Error('不支持的操作系统!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default registerWheelEvent;
|
@ -6,7 +6,7 @@ const yOffsetUpdate = (pstate, nextOffsetYFn) => {
|
|||||||
|
|
||||||
const currentRenderHeight = globalLookup.currentWires.size * pstate.yStep;
|
const currentRenderHeight = globalLookup.currentWires.size * pstate.yStep;
|
||||||
const canvasHeight = pstate.height - pstate.topBarHeight - pstate.botBarHeight;
|
const canvasHeight = pstate.height - pstate.topBarHeight - pstate.botBarHeight;
|
||||||
console.log(currentRenderHeight, canvasHeight);
|
// console.log(currentRenderHeight, canvasHeight);
|
||||||
const maxOffsetX = Math.max(-40, currentRenderHeight - canvasHeight); // maximum offset
|
const maxOffsetX = Math.max(-40, currentRenderHeight - canvasHeight); // maximum offset
|
||||||
nextOffsetY = Math.min(nextOffsetY, maxOffsetX);
|
nextOffsetY = Math.min(nextOffsetY, maxOffsetX);
|
||||||
|
|
||||||
|
@ -46,7 +46,8 @@
|
|||||||
"usermanual": "User Manual",
|
"usermanual": "User Manual",
|
||||||
"usermanual.left-right-scroll.title": "<span class=\"iconfont icon-mouse\"/> + <span class=\"iconfont icon-up-down\"/>",
|
"usermanual.left-right-scroll.title": "<span class=\"iconfont icon-mouse\"/> + <span class=\"iconfont icon-up-down\"/>",
|
||||||
"usermanual.left-right-scroll.caption": "move up and down",
|
"usermanual.left-right-scroll.caption": "move up and down",
|
||||||
"usermanual.up-down-scroll.title": "<span class=\"iconfont icon-mouse\"/> + <span class=\"iconfont icon-left-right\"/> / <span class=\"iconfont icon-shift\"/> + <span class=\"iconfont icon-mouse\"/> + <span class=\"iconfont icon-up-down\"/>",
|
"usermanual.up-down-scroll.title.wheel": "<span class=\"iconfont icon-mouse\"/> + <span class=\"iconfont icon-left-right\"/> / <span class=\"iconfont icon-shift\"/> + <span class=\"iconfont icon-mouse\"/> + <span class=\"iconfont icon-up-down\"/>",
|
||||||
|
"usermanual.up-down-scroll.title.shift": "<span class=\"iconfont icon-mouse\"/> + <span class=\"iconfont icon-left-right\"/> / <span class=\"iconfont icon-shift\"/> + <span class=\"iconfont icon-mouse\"/> + <span class=\"iconfont icon-up-down\"/>",
|
||||||
"usermanual.up-down-scroll.caption": "move left and right",
|
"usermanual.up-down-scroll.caption": "move left and right",
|
||||||
"usermanual.xscale.title": "<span class=\"iconfont icon-ctrl\"/> + <span class=\"iconfont icon-mouse\"/> + <span class=\"iconfont icon-up-down\"/>",
|
"usermanual.xscale.title": "<span class=\"iconfont icon-ctrl\"/> + <span class=\"iconfont icon-mouse\"/> + <span class=\"iconfont icon-up-down\"/>",
|
||||||
"usermanual.xscale.caption": "scale along x axis",
|
"usermanual.xscale.caption": "scale along x axis",
|
||||||
|
@ -12,4 +12,9 @@ module.exports = {
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
devtool: 'none',
|
devtool: 'none',
|
||||||
}
|
module: {
|
||||||
|
loader: [
|
||||||
|
{ test: /\.vcd$/, loader: 'ignore-loader' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user