完成搜索
This commit is contained in:
parent
948370b644
commit
9f50214cbb
@ -6,7 +6,7 @@
|
|||||||
--main-light-color: var(--main-color);
|
--main-light-color: var(--main-color);
|
||||||
--sidebar-width: 330px;
|
--sidebar-width: 330px;
|
||||||
--right-nav-width: 60px;
|
--right-nav-width: 60px;
|
||||||
--time-scale-height: 50px;
|
--time-scale-height: 30px;
|
||||||
--sidebar-padding: 10px;
|
--sidebar-padding: 10px;
|
||||||
--sidebar-item-margin: 5px;
|
--sidebar-item-margin: 5px;
|
||||||
--toolbar-height: 50px;
|
--toolbar-height: 50px;
|
||||||
|
@ -71,7 +71,7 @@ onMounted(async () => {
|
|||||||
// document.body.style.setProperty('--el-color-white', 'var(--background)');
|
// document.body.style.setProperty('--el-color-white', 'var(--background)');
|
||||||
|
|
||||||
// 设置全局宏
|
// 设置全局宏
|
||||||
document.body.style.setProperty('--time-scale-height', '50px');
|
document.body.style.setProperty('--time-scale-height', '30px');
|
||||||
document.body.style.setProperty('--vcd-render-padding', '30px');
|
document.body.style.setProperty('--vcd-render-padding', '30px');
|
||||||
document.body.style.setProperty('--sidebar-width', '330px');
|
document.body.style.setProperty('--sidebar-width', '330px');
|
||||||
document.body.style.setProperty('--toolbar-height', '60px');
|
document.body.style.setProperty('--toolbar-height', '60px');
|
||||||
|
47
src/components/render/cursor.js
Normal file
47
src/components/render/cursor.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { globalLookup } from '@/hook/global';
|
||||||
|
import formatTime from '@/hook/wave-view/format-time';
|
||||||
|
import { reactive } from 'vue';
|
||||||
|
|
||||||
|
export const StaticCursor = reactive({
|
||||||
|
label: '',
|
||||||
|
show: false,
|
||||||
|
currentTime: 0,
|
||||||
|
left: 0,
|
||||||
|
updateLabel(timescale) {
|
||||||
|
this.label = formatTime(this.currentTime, timescale);
|
||||||
|
},
|
||||||
|
updateLeft() {
|
||||||
|
this.left = calcCursorLeft(this.currentTime);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export function changeCursorLocation() {
|
||||||
|
StaticCursor.show = true;
|
||||||
|
const pstate = globalLookup.pstate;
|
||||||
|
if (pstate) {
|
||||||
|
const { xCursor, xOffset, xScale, tgcd, timescale } = pstate;
|
||||||
|
const currentTime = Math.round((xCursor - xOffset) / xScale) * tgcd;
|
||||||
|
StaticCursor.currentTime = currentTime;
|
||||||
|
StaticCursor.updateLabel(timescale);
|
||||||
|
StaticCursor.updateLeft();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 给出当前的时间,比如 23ns,计算当前这个点应该相对于左侧偏移多少
|
||||||
|
* @param {number} currentTime
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
export function calcCursorLeft(currentTime) {
|
||||||
|
const pstate = globalLookup.pstate;
|
||||||
|
if (pstate) {
|
||||||
|
const { xOffset, xScale, tgcd, timescale } = pstate;
|
||||||
|
const xCursor = (currentTime / tgcd) * xScale + xOffset;
|
||||||
|
return xCursor;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MovingCursor = reactive({
|
||||||
|
|
||||||
|
});
|
@ -1,94 +1,62 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div v-show="StaticCursor.show">
|
||||||
<div class="vertical-cursor-wrapper"
|
<div class="vertical-cursor-wrapper"
|
||||||
@click="makeCursor"
|
:style="cursorStyle"
|
||||||
:style="`left: ${currentX}px`">
|
>
|
||||||
<div class="current-display-cursor-up">
|
<div class="current-display-cursor-up">
|
||||||
<div class="current-time-value">{{ currentX }} px</div>
|
<div class="current-time-value" :style="colorStyle">{{ StaticCursor.label }}</div>
|
||||||
<div class="cursor-down-arrow"></div>
|
<div class="cursor-down-arrow" :style="borderStyle"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="vertical-line"></div>
|
<div class="vertical-line" :style="colorStyle"></div>
|
||||||
<div class="current-display-cursor-down">
|
<div class="current-display-cursor-down">
|
||||||
<div class="current-time-value">{{ currentX }} px</div>
|
<div class="current-time-value" :style="colorStyle">{{ StaticCursor.label }}</div>
|
||||||
<div class="cursor-up-arrow"></div>
|
<div class="cursor-up-arrow" :style="borderStyle"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-show="showFixedOne"
|
|
||||||
class="vertical-cursor-wrapper"
|
|
||||||
@click="makeCursor"
|
|
||||||
:style="`left: ${fixedLeft}px`">
|
|
||||||
<div class="fix-current-display-cursor-up">
|
|
||||||
{{ globalLookup.view.currentX }} px
|
|
||||||
</div>
|
|
||||||
<div class="fix-vertical-line"></div>
|
|
||||||
<div class="fix-current-display-cursor-down">
|
|
||||||
{{ globalLookup.view.currentX }} px
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
import { reactive, ref } from 'vue';
|
import { computed, defineComponent } from 'vue';
|
||||||
import { globalLookup } from '../../hook/global';
|
import { StaticCursor } from './cursor';
|
||||||
|
|
||||||
export default {
|
defineComponent({ name: 'vertical-cursor' });
|
||||||
name: 'vertical-cursor',
|
|
||||||
setup() {
|
|
||||||
// see --sidebar-width
|
|
||||||
const left = 280 + 20;
|
|
||||||
|
|
||||||
// see --right-nav-width
|
const props = defineProps({
|
||||||
const right = document.body.clientWidth - 60;
|
color: {
|
||||||
|
type: String,
|
||||||
const showFixedOne = ref(false);
|
default: 'var(--main-color)'
|
||||||
const fixedLeft = ref(0);
|
|
||||||
const currentX = ref(left);
|
|
||||||
const boxShift = 25;
|
|
||||||
|
|
||||||
document.onmousemove = event => {
|
|
||||||
const x = event.x;
|
|
||||||
if (x < left || x > right) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
currentX.value = x - boxShift;
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
const colorStyle = {
|
||||||
* @param { PointerEvent } event
|
backgroundColor: props.color
|
||||||
*/
|
};
|
||||||
function makeCursor(event) {
|
|
||||||
// console.log(event.x);
|
|
||||||
showFixedOne.value = true;
|
|
||||||
fixedLeft.value = event.x - boxShift;
|
|
||||||
globalLookup.view.currentX = event.x - boxShift;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
const borderStyle = {
|
||||||
makeCursor,
|
borderLeft: '5px solid ' + props.color,
|
||||||
fixedLeft,
|
borderTop: '5px solid ' + props.color
|
||||||
showFixedOne,
|
};
|
||||||
boxShift,
|
|
||||||
globalLookup,
|
const boxShift = 25;
|
||||||
currentX
|
const cursorStyle = computed(() => ({
|
||||||
}
|
left: StaticCursor.left - boxShift + 'px'
|
||||||
}
|
}));
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style scoped>
|
||||||
.vertical-cursor-wrapper {
|
.vertical-cursor-wrapper {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 100vh;
|
|
||||||
padding: 0;
|
|
||||||
top: 0;
|
top: 0;
|
||||||
|
padding: 0;
|
||||||
cursor: crosshair;
|
cursor: crosshair;
|
||||||
z-index: 55;
|
z-index: 55;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center; /* 沿着横轴(水平方向)对齐 */
|
align-items: center; /* 沿着横轴(水平方向)对齐 */
|
||||||
justify-content: center; /* 沿着纵轴(垂直方向)对齐 */
|
justify-content: center; /* 沿着纵轴(垂直方向)对齐 */
|
||||||
|
transform: translateY(var(--toolbar-height));
|
||||||
}
|
}
|
||||||
|
|
||||||
.current-display-cursor-up {
|
.current-display-cursor-up {
|
||||||
@ -115,7 +83,6 @@ export default {
|
|||||||
|
|
||||||
.current-time-value {
|
.current-time-value {
|
||||||
border-radius: .4em;
|
border-radius: .4em;
|
||||||
background-color: var(--color-deepPurple);
|
|
||||||
color: var(--sidebar-item-text);
|
color: var(--sidebar-item-text);
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
@ -123,8 +90,6 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.cursor-down-arrow {
|
.cursor-down-arrow {
|
||||||
border-left: 5px solid var(--color-deepPurple);
|
|
||||||
border-top: 5px solid var(--color-deepPurple);
|
|
||||||
transform: rotate(225deg);
|
transform: rotate(225deg);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 10px;
|
width: 10px;
|
||||||
@ -134,9 +99,12 @@ export default {
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vertical-line {
|
||||||
|
width: 2px;
|
||||||
|
height: calc(100vh - 2 * var(--time-scale-height) - 60px);
|
||||||
|
}
|
||||||
|
|
||||||
.cursor-up-arrow {
|
.cursor-up-arrow {
|
||||||
border-left: 5px solid var(--color-deepPurple);
|
|
||||||
border-top: 5px solid var(--color-deepPurple);
|
|
||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 10px;
|
width: 10px;
|
||||||
@ -144,40 +112,4 @@ export default {
|
|||||||
left: 17.93px;
|
left: 17.93px;
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vertical-line {
|
|
||||||
width: 1px;
|
|
||||||
height: calc(100vh - 2 * var(--time-scale-height));
|
|
||||||
}
|
|
||||||
|
|
||||||
.fix-vertical-line {
|
|
||||||
width: 1px;
|
|
||||||
height: calc(100vh - 2 * var(--time-scale-height));
|
|
||||||
background-color: var(--color-deepPurple);
|
|
||||||
}
|
|
||||||
|
|
||||||
.fix-current-display-cursor-up {
|
|
||||||
height: var(--time-scale-height);
|
|
||||||
width: 50px;
|
|
||||||
background-color: var(--color-deepPurple);
|
|
||||||
border-radius: .5em .5em .5em .5em;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-around;
|
|
||||||
color: var(--sidebar-item-text);
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fix-current-display-cursor-down {
|
|
||||||
height: var(--time-scale-height);
|
|
||||||
width: 50px;
|
|
||||||
background-color: var(--color-deepPurple);
|
|
||||||
border-radius: .5em .5em .5em .5em;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-around;
|
|
||||||
color: var(--sidebar-item-text);
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
@ -1,35 +1,27 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- <VerticalCursor></VerticalCursor> -->
|
<!-- <VerticalCursor></VerticalCursor> -->
|
||||||
<!-- <TimeScale></TimeScale> -->
|
<!-- <TimeScale></TimeScale> -->
|
||||||
<div class="vcd-render-wrapper" @click="updateWireCurrentValue()">
|
<div class="vcd-render-wrapper" @click="onRenderClick()">
|
||||||
|
<VerticalCursor></VerticalCursor>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
import { reactive, ref } from 'vue';
|
import { defineComponent, reactive, ref } from 'vue';
|
||||||
import { emitter, globalLookup, globalSetting } from '@/hook/global';
|
import { emitter, globalLookup, globalSetting } from '@/hook/global';
|
||||||
import { updateWireCurrentValue } from '@/hook/utils';
|
import { updateWireCurrentValue } from '@/hook/utils';
|
||||||
|
|
||||||
import VerticalCursor from '@/components/render/cursor.vue';
|
import VerticalCursor from '@/components/render/cursor.vue';
|
||||||
import TimeScale from '@/components/render/time-scale.vue';
|
import { changeCursorLocation } from './cursor';
|
||||||
|
|
||||||
export default {
|
defineComponent({ name: 'main-render' });
|
||||||
name: 'main-render',
|
|
||||||
components: {
|
|
||||||
// VerticalCursor,
|
|
||||||
// TimeScale
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 渲染区域被鼠标点击时
|
||||||
return {
|
*/
|
||||||
globalLookup,
|
function onRenderClick() {
|
||||||
updateWireCurrentValue
|
updateWireCurrentValue();
|
||||||
}
|
changeCursorLocation();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@ -89,6 +81,7 @@ export default {
|
|||||||
.vcd-cursor {
|
.vcd-cursor {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
z-index: 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vcd-values text {
|
.vcd-values text {
|
||||||
|
@ -150,7 +150,7 @@ function handleSidebarGlobalClick() {
|
|||||||
border-radius: 0 .8em .8em 0;
|
border-radius: 0 .8em .8em 0;
|
||||||
border: solid 1px var(--sidebar-border);
|
border: solid 1px var(--sidebar-border);
|
||||||
width: var(--sidebar-width);
|
width: var(--sidebar-width);
|
||||||
height: calc(100vh - var(--toolbar-height));
|
height: calc(100vh - var(--toolbar-height) - 50px);
|
||||||
box-shadow: 0 0 15px 1px rgb(16, 16, 16);
|
box-shadow: 0 0 15px 1px rgb(16, 16, 16);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
@ -165,6 +165,14 @@ function handleSidebarGlobalClick() {
|
|||||||
transition: var(--animation-5s);
|
transition: var(--animation-5s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.group-children .display-signal-item {
|
||||||
|
width: calc(200px - 8px - 10px) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-children .signal-color-vendor > span {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.display-signal-item-container {
|
.display-signal-item-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
<span>{{ signalInfo.name }}</span>
|
<span>{{ signalInfo.name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="signal-info-width" v-show="showWidth">
|
<div class="signal-info-width" v-show="showWidth">
|
||||||
<div :class="signalInfo.size > 1 ? 'signal-info-caption' : ''">
|
<div
|
||||||
|
:class="{ 'signal-info-caption': signalInfo.size > 1 }"
|
||||||
|
>
|
||||||
{{ makeSignalCaption(signalInfo) }}
|
{{ makeSignalCaption(signalInfo) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -70,7 +72,7 @@ const signalInfo = computed(() => {
|
|||||||
/**
|
/**
|
||||||
* @param {WireItemBaseInfo} signal
|
* @param {WireItemBaseInfo} signal
|
||||||
*/
|
*/
|
||||||
function makeSignalIconClass(signal) {
|
function makeSignalIconClass(signal) {
|
||||||
const realSignal = globalLookup.link2CurrentWires.get(signal.link);
|
const realSignal = globalLookup.link2CurrentWires.get(signal.link);
|
||||||
return 'iconfont ' + makeIconClass(realSignal);
|
return 'iconfont ' + makeIconClass(realSignal);
|
||||||
}
|
}
|
||||||
|
160
src/components/toolbar/cursor-location.js
Normal file
160
src/components/toolbar/cursor-location.js
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import { globalLookup } from "@/hook/global";
|
||||||
|
import { calcCursorLeft, StaticCursor } from "../render/cursor";
|
||||||
|
import { sidebarSelectedWires } from "@/hook/sidebar-select-wire";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 将 某时间点 移动到指定位置
|
||||||
|
* @param {number} time 需要移动到的时间点
|
||||||
|
* @param {number} leftMargin 移动后的该时间点距离左侧多少px
|
||||||
|
* @param {Pstate} pstate
|
||||||
|
*/
|
||||||
|
function moveto(time, leftMargin, pstate) {
|
||||||
|
StaticCursor.show = true;
|
||||||
|
StaticCursor.currentTime = time;
|
||||||
|
pstate.oldXOffset = pstate.xOffset;
|
||||||
|
const { width, xOffset, xScale, tgcd, timescale } = pstate;
|
||||||
|
pstate.xOffset = leftMargin - (time / tgcd) * xScale;
|
||||||
|
|
||||||
|
StaticCursor.updateLeft();
|
||||||
|
StaticCursor.updateLabel(pstate.timescale);
|
||||||
|
globalLookup.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toBegin() {
|
||||||
|
const pstate = globalLookup.pstate;
|
||||||
|
if (pstate) {
|
||||||
|
moveto(0, pstate.sidebarWidth - 20, pstate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toEnd() {
|
||||||
|
const pstate = globalLookup.pstate;
|
||||||
|
if (pstate) {
|
||||||
|
moveto(globalLookup.time, pstate.width - pstate.sidebarWidth, pstate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clip(v, min, max) {
|
||||||
|
if (v < min) {
|
||||||
|
v = min;
|
||||||
|
}
|
||||||
|
if (v > max) {
|
||||||
|
v = max;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toPrevChange() {
|
||||||
|
const link = sidebarSelectedWires.lastLink;
|
||||||
|
const pstate = globalLookup.pstate;
|
||||||
|
|
||||||
|
if (link === undefined || pstate === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chango = globalLookup.chango[link];
|
||||||
|
if (chango && chango.wave && chango.wave.length > 0) {
|
||||||
|
const wave = chango.wave;
|
||||||
|
|
||||||
|
// 如果长度为 1,直接到前面或者后面即可
|
||||||
|
if (wave.length === 1) {
|
||||||
|
toBegin();
|
||||||
|
} else {
|
||||||
|
const currentT = StaticCursor.currentTime;
|
||||||
|
let pivot = bisearch(wave, currentT);
|
||||||
|
|
||||||
|
const pwave = wave[pivot];
|
||||||
|
if (pwave[0] === currentT) {
|
||||||
|
pivot = clip(pivot - 1, 0, wave.length - 1);
|
||||||
|
} else {
|
||||||
|
pivot = clip(pivot, 0, wave.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetT = wave[pivot][0];
|
||||||
|
moveto(targetT, (pstate.width + pstate.sidebarWidth) / 2, pstate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function toNextChange() {
|
||||||
|
const link = sidebarSelectedWires.lastLink;
|
||||||
|
const pstate = globalLookup.pstate;
|
||||||
|
|
||||||
|
if (link === undefined || pstate === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chango = globalLookup.chango[link];
|
||||||
|
if (chango && chango.wave && chango.wave.length > 0) {
|
||||||
|
const wave = chango.wave;
|
||||||
|
|
||||||
|
// 如果长度为 1,直接到前面或者后面即可
|
||||||
|
if (wave.length === 1) {
|
||||||
|
toEnd();
|
||||||
|
} else {
|
||||||
|
const currentT = StaticCursor.currentTime;
|
||||||
|
let pivot = bisearch(wave, currentT);
|
||||||
|
let targetT;
|
||||||
|
if (pivot === wave.length - 1) {
|
||||||
|
pivot = clip(pivot + 1, 0, wave.length - 1);
|
||||||
|
targetT = globalLookup.time;
|
||||||
|
} else {
|
||||||
|
pivot = clip(pivot + 1, 0, wave.length - 1);
|
||||||
|
targetT = wave[pivot][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
moveto(targetT, (pstate.width + pstate.sidebarWidth) / 2, pstate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const locationManager = {
|
||||||
|
/**
|
||||||
|
* @description 记录所有的信标
|
||||||
|
* @type {Map<number, HTMLElement>} 时间点到元素的映射
|
||||||
|
*/
|
||||||
|
pivots: new Map(),
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export function makeLocation() {
|
||||||
|
const currentT = StaticCursor.currentTime;
|
||||||
|
// 在 currentT 创建新的信标
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 二分查找找到最近的索引下标
|
||||||
|
* @param {number[][]} wave
|
||||||
|
* @param {number} time
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
function bisearch(wave, time) {
|
||||||
|
const times = wave.map(p => p[0]);
|
||||||
|
|
||||||
|
// 二分查找,并将结果存入 i
|
||||||
|
let i = 0, j = wave.length - 1;
|
||||||
|
while (i < j) {
|
||||||
|
if (times[i] === time) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (times[j] <= time) {
|
||||||
|
i = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j - i === 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const mid = (i + j) >> 1;
|
||||||
|
if (times[mid] > time) {
|
||||||
|
j = mid;
|
||||||
|
} else {
|
||||||
|
i = mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
@ -1,35 +1,86 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="location">
|
<div class="location">
|
||||||
|
<el-tooltip
|
||||||
|
effect="dark"
|
||||||
|
:content="t('toolbar.location.to-begin')"
|
||||||
|
placement="bottom"
|
||||||
|
raw-content
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="item iconfont icon-beginning"
|
class="item iconfont icon-beginning"
|
||||||
|
@click="toBegin()"
|
||||||
/>
|
/>
|
||||||
|
</el-tooltip>
|
||||||
|
|
||||||
|
|
||||||
|
<el-tooltip
|
||||||
|
effect="dark"
|
||||||
|
:content="t('toolbar.location.to-end')"
|
||||||
|
placement="bottom"
|
||||||
|
raw-content
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="item iconfont icon-ending"
|
class="item iconfont icon-ending"
|
||||||
|
@click="toEnd()"
|
||||||
/>
|
/>
|
||||||
|
</el-tooltip>
|
||||||
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
<el-divider direction="vertical"></el-divider>
|
||||||
|
|
||||||
|
<el-tooltip
|
||||||
|
effect="dark"
|
||||||
|
:content="t('toolbar.location.to-prev-change')"
|
||||||
|
placement="bottom"
|
||||||
|
raw-content
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="item iconfont icon-arrow-to-previous"
|
class="item iconfont icon-arrow-to-previous"
|
||||||
|
:class="{ 'disable' : globalLookup.sidebarSelectedWireLinks.size === 0 }"
|
||||||
|
@click="toPrevChange()"
|
||||||
/>
|
/>
|
||||||
|
</el-tooltip>
|
||||||
|
|
||||||
|
|
||||||
|
<el-tooltip
|
||||||
|
effect="dark"
|
||||||
|
:content="t('toolbar.location.to-next-change')"
|
||||||
|
placement="bottom"
|
||||||
|
raw-content
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="item iconfont icon-arrow-to-next"
|
class="item iconfont icon-arrow-to-next"
|
||||||
|
:class="{ 'disable' : globalLookup.sidebarSelectedWireLinks.size === 0 }"
|
||||||
|
@click="toNextChange()"
|
||||||
/>
|
/>
|
||||||
|
</el-tooltip>
|
||||||
|
|
||||||
<el-divider direction="vertical"></el-divider>
|
<el-divider direction="vertical"></el-divider>
|
||||||
|
|
||||||
|
<el-tooltip
|
||||||
|
effect="dark"
|
||||||
|
:content="t('toolbar.location.make-location')"
|
||||||
|
placement="bottom"
|
||||||
|
raw-content
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="item iconfont icon-add-line"
|
class="item iconfont icon-add-line"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
</el-tooltip>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { toBegin, toEnd, toNextChange, toPrevChange } from './cursor-location';
|
||||||
|
import { globalLookup } from '@/hook/global';
|
||||||
|
|
||||||
defineComponent({ name: 'cursor-location' });
|
defineComponent({ name: 'cursor-location' });
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -62,4 +113,15 @@ defineComponent({ name: 'cursor-location' });
|
|||||||
color: var(--sidebar);
|
color: var(--sidebar);
|
||||||
transition: var(--animation-3s);
|
transition: var(--animation-3s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.disable {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.location .item.disable:hover {
|
||||||
|
background-color: unset !important;
|
||||||
|
color: unset !important;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
@ -37,6 +37,7 @@ defineComponent({ name: 'toolbar' });
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: var(--toolbar-height);
|
height: var(--toolbar-height);
|
||||||
background-color: var(--background);
|
background-color: var(--background);
|
||||||
|
z-index: 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar-body {
|
.toolbar-body {
|
||||||
|
1
src/components/toolbar/pivot-view.js
Normal file
1
src/components/toolbar/pivot-view.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
@ -54,15 +54,16 @@ const signalModal = ref(0);
|
|||||||
const disabled = ref(true);
|
const disabled = ref(true);
|
||||||
|
|
||||||
function onSignalModalUpdate() {
|
function onSignalModalUpdate() {
|
||||||
console.log('enter change');
|
|
||||||
const links = globalLookup.sidebarSelectedWireLinks;
|
const links = globalLookup.sidebarSelectedWireLinks;
|
||||||
if (links.size > 0) {
|
if (links.size > 0) {
|
||||||
const modal = signalModal.value;
|
const modal = signalModal.value;
|
||||||
// 更新渲染选项
|
// 更新渲染选项
|
||||||
for (const link of links) {
|
for (const link of links) {
|
||||||
globalLookup.setRenderOption(link, 'renderModal', modal);
|
const realChange = globalLookup.setRenderOption(link, 'renderModal', modal);
|
||||||
|
if (realChange) {
|
||||||
globalLookup.waveRender.resetVertice(link);
|
globalLookup.waveRender.resetVertice(link);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 重新渲染
|
// 重新渲染
|
||||||
globalLookup.render();
|
globalLookup.render();
|
||||||
|
@ -37,9 +37,6 @@ const { t } = useI18n();
|
|||||||
const currentOption = ref(2);
|
const currentOption = ref(2);
|
||||||
const disabled = ref(true);
|
const disabled = ref(true);
|
||||||
|
|
||||||
function onChange() {
|
|
||||||
console.log(currentOption.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
formatOptions.push({
|
formatOptions.push({
|
||||||
@ -95,6 +92,23 @@ onMounted(() => {
|
|||||||
|
|
||||||
const formatOptions = reactive([]);
|
const formatOptions = reactive([]);
|
||||||
|
|
||||||
|
function onChange() {
|
||||||
|
const links = globalLookup.sidebarSelectedWireLinks;
|
||||||
|
if (links.size > 0) {
|
||||||
|
const valueFormat = currentOption.value;
|
||||||
|
// 更新渲染选项
|
||||||
|
for (const link of links) {
|
||||||
|
const realChange = globalLookup.setRenderOption(link, 'valueFormat', valueFormat);
|
||||||
|
if (realChange) {
|
||||||
|
globalLookup.waveRender.resetVertice(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新渲染,不过只需要渲染数值即可
|
||||||
|
globalLookup.render({ type: 'value' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sidebarSelectedWires.addToPipe(lastLink => {
|
sidebarSelectedWires.addToPipe(lastLink => {
|
||||||
if (lastLink) {
|
if (lastLink) {
|
||||||
const option = globalLookup.currentSignalRenderOptions.get(lastLink);
|
const option = globalLookup.currentSignalRenderOptions.get(lastLink);
|
||||||
|
@ -14,20 +14,132 @@
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</div>
|
</div>
|
||||||
<div class="value-input-wrapper">
|
<div class="value-input-wrapper">
|
||||||
<el-input></el-input>
|
<el-input
|
||||||
|
v-model="searchManage.content"
|
||||||
|
@input="safeSearch"
|
||||||
|
@focus="searchManage.displayResult = true"
|
||||||
|
@blur="searchManage.displayResult = false"
|
||||||
|
></el-input>
|
||||||
|
|
||||||
|
<transition name="collapse-from-top">
|
||||||
|
<div
|
||||||
|
v-show="searchManage.displayResult || searchManage.mouseOnResult"
|
||||||
|
class="toolbar-search-container"
|
||||||
|
>
|
||||||
|
<el-scrollbar
|
||||||
|
height="300px"
|
||||||
|
width="100%"
|
||||||
|
@mouseenter="searchManage.mouseOnResult = true"
|
||||||
|
@mouseleave="searchManage.mouseOnResult = false"
|
||||||
|
class="search-result"
|
||||||
|
>
|
||||||
|
<div v-if="searchManage.searchResult.length > 0">
|
||||||
|
<div v-for="(signal, index) in searchManage.searchResult"
|
||||||
|
:key="index"
|
||||||
|
@click="clickSearchItem(signal)"
|
||||||
|
class="toolbar-search"
|
||||||
|
>
|
||||||
|
<span :class="makeSignalIconClass(signal)"></span>
|
||||||
|
<span class="signal-name">{{ signal.name }}</span>
|
||||||
|
<span
|
||||||
|
class="signal-width"
|
||||||
|
>
|
||||||
|
<span :class="{ 'vec': signal.width > 1 }">{{ makeSignalCaption(signal) }}</span>
|
||||||
|
</span>
|
||||||
|
<span class="signal-value">{{ signal.value }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else class="toolbar-search-nothing">
|
||||||
|
<span class="iconfont icon-empty"></span>
|
||||||
|
<span>{{ t('search-nothing') }}</span>
|
||||||
|
</div>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineComponent, ref } from 'vue';
|
import { globalLookup } from '@/hook/global';
|
||||||
|
import { debounceWrapper, makeIconClass } from '@/hook/utils';
|
||||||
|
import { defineComponent, reactive, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
defineComponent({ name: 'value-search' })
|
defineComponent({ name: 'value-search' })
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const searchMode = ref(1);
|
||||||
|
|
||||||
const searchMode = ref(0);
|
const searchManage = reactive({
|
||||||
|
content: '',
|
||||||
|
displayResult: false,
|
||||||
|
mouseOnResult: false,
|
||||||
|
searchResult: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
function addWire(wireItem) {
|
||||||
|
searchManage.searchResult.push({
|
||||||
|
name: wireItem.name,
|
||||||
|
width: wireItem.size,
|
||||||
|
type: wireItem.type,
|
||||||
|
value: globalLookup.currentSignalValues[wireItem.link]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchByValue() {
|
||||||
|
const value = searchManage.content.trim();
|
||||||
|
for (const wireItem of globalLookup.currentWires) {
|
||||||
|
const currentVal = globalLookup.currentSignalValues[wireItem.link];
|
||||||
|
if (currentVal.toString().includes(value)) {
|
||||||
|
addWire(wireItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchByName() {
|
||||||
|
const name = searchManage.content.trim();
|
||||||
|
for (const wireItem of globalLookup.currentWires) {
|
||||||
|
if (wireItem.name.includes(name)) {
|
||||||
|
addWire(wireItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function search() {
|
||||||
|
if (globalLookup.currentWires.size === 0 || searchManage.content.trim().length === 0) {
|
||||||
|
searchManage.searchResult.length = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (searchMode.value) {
|
||||||
|
case 0:
|
||||||
|
searchByValue();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
searchByName();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const safeSearch = debounceWrapper(search, 200);
|
||||||
|
|
||||||
|
function clickSearchItem() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeSignalCaption(signal) {
|
||||||
|
if (signal === undefined) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return signal.width === 1 ? '' : `${signal.width - 1}:0`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeSignalIconClass(signal) {
|
||||||
|
return 'iconfont ' + makeIconClass(signal);
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -41,8 +153,106 @@ const searchMode = ref(0);
|
|||||||
}
|
}
|
||||||
|
|
||||||
.value-input-wrapper {
|
.value-input-wrapper {
|
||||||
|
position: relative;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
width: 120px;
|
width: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.toolbar-search-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 50px;
|
||||||
|
left: -10px;
|
||||||
|
transition: var(--animation-3s);
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px;
|
||||||
|
background-color: var(--sidebar);
|
||||||
|
border: 1.5px solid var(--main-color);
|
||||||
|
color: var(--sidebar-item-text);
|
||||||
|
border-radius: .5em;
|
||||||
|
width: 420px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-search-nothing {
|
||||||
|
height: 260px;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-search-nothing .iconfont {
|
||||||
|
font-size: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-search .signal-name {
|
||||||
|
width: 100px;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-search .iconfont {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--sidebar);
|
||||||
|
background-color: #7ca532;
|
||||||
|
border-radius: 99em;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-search {
|
||||||
|
display: flex;
|
||||||
|
margin: 3px;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: var(--animation-3s);
|
||||||
|
border-radius: .5em;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-search:hover {
|
||||||
|
transition: var(--animation-3s);
|
||||||
|
background-color: var(--sidebar-item-selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-search .signal-width {
|
||||||
|
width: 80px;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-search .vec {
|
||||||
|
color: var(--sidebar);
|
||||||
|
background-color: #7ca532;
|
||||||
|
padding: 2px 3px;
|
||||||
|
border-radius: .5em;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-search .signal-value {
|
||||||
|
width: 150px;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
@ -13,7 +13,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<transition name="collapse-from-top">
|
<transition name="collapse-from-top">
|
||||||
<div
|
<div
|
||||||
v-show="searchManage.displayResult | searchManage.mouseOnResult"
|
v-show="searchManage.displayResult || searchManage.mouseOnResult"
|
||||||
:style="searchResultWrapper"
|
:style="searchResultWrapper"
|
||||||
class="search-result-wrapper"
|
class="search-result-wrapper"
|
||||||
id="search-result-wrapper"
|
id="search-result-wrapper"
|
||||||
@ -110,7 +110,7 @@ emitter.on('signal-search', searchResultItem => {
|
|||||||
searchManage.searchResult.push(searchResultItem);
|
searchManage.searchResult.push(searchResultItem);
|
||||||
});
|
});
|
||||||
|
|
||||||
const safeSearch = debounceWrapper(search, 500);
|
const safeSearch = debounceWrapper(search, 200);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -86,10 +86,11 @@ export const globalLookup = reactive({
|
|||||||
*/
|
*/
|
||||||
chango: {},
|
chango: {},
|
||||||
|
|
||||||
// 初始化时会被定义
|
/**
|
||||||
render: () => {},
|
* @description 【核心】接入渲染管线,重新渲染,该函数必须在 domContainer 初始化完成后再去调用
|
||||||
|
* @param {RenderConfig} renderConfig 渲染的类型,默认为重新渲染所有可视项
|
||||||
|
*/
|
||||||
|
render: (renderConfig) => {},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 非常核心的用于操控 webgl 进行渲染和动画的核心类
|
* @description 非常核心的用于操控 webgl 进行渲染和动画的核心类
|
||||||
@ -98,6 +99,10 @@ export const globalLookup = reactive({
|
|||||||
waveRender: undefined,
|
waveRender: undefined,
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 描述描述当前渲染区的一些基本几何状态
|
||||||
|
* @type {Pstate | undefined}
|
||||||
|
*/
|
||||||
pstate: undefined,
|
pstate: undefined,
|
||||||
|
|
||||||
xScale: 1,
|
xScale: 1,
|
||||||
@ -126,13 +131,18 @@ export const globalLookup = reactive({
|
|||||||
* @param {string} link
|
* @param {string} link
|
||||||
* @param {'height' | 'color' | 'valueFormat' | 'renderModal'} option
|
* @param {'height' | 'color' | 'valueFormat' | 'renderModal'} option
|
||||||
* @param {any} value
|
* @param {any} value
|
||||||
|
* @returns {boolean} true 代表改变了值,否则则没有,可以用来判断是否需要重复塑造 Vertices
|
||||||
*/
|
*/
|
||||||
setRenderOption(link, option, value) {
|
setRenderOption(link, option, value) {
|
||||||
if (!this.currentSignalRenderOptions.has(link)) {
|
if (!this.currentSignalRenderOptions.has(link)) {
|
||||||
this.currentSignalRenderOptions.set(link, {});
|
this.currentSignalRenderOptions.set(link, {});
|
||||||
}
|
}
|
||||||
const renderOption = this.currentSignalRenderOptions.get(link);
|
const renderOption = this.currentSignalRenderOptions.get(link);
|
||||||
|
if (renderOption[option] === value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
renderOption[option] = value;
|
renderOption[option] = value;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -65,8 +65,6 @@ function makeWaveView(parentElement) {
|
|||||||
console.log('updater');
|
console.log('updater');
|
||||||
};
|
};
|
||||||
|
|
||||||
globalLookup
|
|
||||||
|
|
||||||
// 注册基本的响应事件
|
// 注册基本的响应事件
|
||||||
container.elo.container.addEventListener('wheel',
|
container.elo.container.addEventListener('wheel',
|
||||||
registerWheelEvent(parentElement, container.pstate, globalLookup, eventHandler)
|
registerWheelEvent(parentElement, container.pstate, globalLookup, eventHandler)
|
||||||
|
@ -21,14 +21,20 @@ const mouseMoveHandler = (cursor, content, pstate /* , render */) => {
|
|||||||
// 这是上面展示当前 time 的圆角矩形内的字体大小
|
// 这是上面展示当前 time 的圆角矩形内的字体大小
|
||||||
const fontHeight = 20;
|
const fontHeight = 20;
|
||||||
const fontWidth = fontHeight / 2;
|
const fontWidth = fontHeight / 2;
|
||||||
|
const sidebarWidth = pstate.sidebarWidth;
|
||||||
|
|
||||||
const handler = event => {
|
const handler = event => {
|
||||||
const x = pstate.xCursor = event.clientX;
|
const x = pstate.xCursor = event.clientX;
|
||||||
|
const left = x - xmargin;
|
||||||
|
// 不能进入左侧,也不能进入右侧
|
||||||
|
if (left > sidebarWidth - 195) {
|
||||||
cursor.style.left = (x - xmargin) + 'px';
|
cursor.style.left = (x - xmargin) + 'px';
|
||||||
cursor.innerHTML = renderCursor({ xmargin, fontWidth, fontHeight }, pstate);
|
cursor.innerHTML = renderCursor({ xmargin, fontWidth, fontHeight }, pstate);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// 添加初始鼠标位置
|
// 添加初始鼠标位置
|
||||||
handler({ clientX: pstate.width / 2 });
|
handler({ clientX: pstate.width / 2 });
|
||||||
content.addEventListener('mousemove', handler);
|
document.addEventListener('mousemove', handler);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -171,7 +177,6 @@ const domContainer = (obj) => {
|
|||||||
setTime(pstate, deso.timeOpt.value);
|
setTime(pstate, deso.timeOpt.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const waveRender = new WebGL2WaveRender(elo, deso, pstate, obj.renderPlugins);
|
const waveRender = new WebGL2WaveRender(elo, deso, pstate, obj.renderPlugins);
|
||||||
deso.render = waveRender.render.bind(waveRender);
|
deso.render = waveRender.render.bind(waveRender);
|
||||||
deso.waveRender = waveRender;
|
deso.waveRender = waveRender;
|
||||||
|
@ -81,7 +81,7 @@ function addVecRenderItem(link) {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {GlobalLookup} desc
|
* @param {GlobalLookup} desc
|
||||||
* @param {*} pstate
|
* @param {Pstate} pstate
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function* renderValues(desc, pstate) {
|
function* renderValues(desc, pstate) {
|
||||||
@ -89,9 +89,9 @@ function* renderValues(desc, pstate) {
|
|||||||
|
|
||||||
// 根据 currentWiresRenderView 视图渲染
|
// 根据 currentWiresRenderView 视图渲染
|
||||||
// 此处应该和 render-wave 的相同注释的地方保持逻辑上的一致(render-wave.js 约 646 行)
|
// 此处应该和 render-wave 的相同注释的地方保持逻辑上的一致(render-wave.js 约 646 行)
|
||||||
|
|
||||||
const currentWires = desc.currentWires;
|
const currentWires = desc.currentWires;
|
||||||
const renderSignals = [];
|
const renderSignals = [];
|
||||||
|
|
||||||
for (const view of globalLookup.currentWiresRenderView) {
|
for (const view of globalLookup.currentWiresRenderView) {
|
||||||
if (view.renderType === 0) {
|
if (view.renderType === 0) {
|
||||||
const realSignal = addVecRenderItem(view.signalInfo.link);
|
const realSignal = addVecRenderItem(view.signalInfo.link);
|
||||||
@ -115,48 +115,57 @@ function* renderValues(desc, pstate) {
|
|||||||
|
|
||||||
|
|
||||||
const lineHeightExtra = (globalSetting.displaySignalHeight - 30) / 2;
|
const lineHeightExtra = (globalSetting.displaySignalHeight - 30) / 2;
|
||||||
const ilen = height / yStep;
|
const canvaseHeight = height - topBarHeight - botBarHeight;
|
||||||
const iskip = (yOffset - lineHeightExtra) / yStep;
|
|
||||||
|
|
||||||
const ml = genSVG(width, height - topBarHeight - botBarHeight);
|
// 当前一页最多渲染这么多项目
|
||||||
|
const validRenderNum = Math.ceil(canvaseHeight / yStep);
|
||||||
|
|
||||||
|
const ml = genSVG(width, canvaseHeight);
|
||||||
|
|
||||||
|
// 需要跳过前面几项
|
||||||
|
const renderStartNo = (yOffset - lineHeightExtra) / yStep;
|
||||||
let ifirst = 0;
|
let ifirst = 0;
|
||||||
for (let i = 0; i < ilen; ++ i) {
|
for (let i = 0; i < validRenderNum; ++ i) {
|
||||||
const lane = renderSignals[i];
|
const lane = renderSignals[i];
|
||||||
if (lane && (lane.name || lane.kind)) {
|
if (lane && (lane.name || lane.kind)) {
|
||||||
if (i > iskip) {
|
if (i > renderStartNo) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ifirst = i;
|
ifirst = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ml.push(defs);
|
ml.push(defs);
|
||||||
yield;
|
yield;
|
||||||
|
|
||||||
const markers = ['g'];
|
const markers = ['g'];
|
||||||
ml.push(markers);
|
ml.push(markers);
|
||||||
|
|
||||||
for (let i = 0; i < (iskip + ilen); i++) {
|
for (let i = 0; i < (renderStartNo + validRenderNum); i++) {
|
||||||
const lane = renderSignals[i + (ifirst | 0)];
|
const lane = renderSignals[i + (ifirst | 0)];
|
||||||
const link = (lane || {}).ref;
|
const link = (lane || {}).ref;
|
||||||
|
|
||||||
|
if (link === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (lane && lane.kind === 'DIZ') {
|
if (lane && lane.kind === 'DIZ') {
|
||||||
markers.push(['g', tt(0, Math.round((i - (iskip - ifirst) + 1.18) * yStep))].concat(water(lane, desc, pstate)));
|
markers.push(['g', tt(0, Math.round((i - (renderStartNo - ifirst) + 1.18) * yStep))].concat(water(lane, desc, pstate)));
|
||||||
} else if (lane && lane.kind === 'brace') {
|
} else if (lane && lane.kind === 'brace') {
|
||||||
markers.push(['g', tt(0, Math.round((i - (iskip - ifirst) + 1.18) * yStep))].concat(bracer(lane, desc, pstate)));
|
markers.push(['g', tt(0, Math.round((i - (renderStartNo - ifirst) + 1.18) * yStep))].concat(bracer(lane, desc, pstate)));
|
||||||
} else if (lane && link) {
|
} else if (lane && link) {
|
||||||
const chango = desc.chango[link];
|
const chango = desc.chango[link];
|
||||||
if (chango && chango.kind === 'vec') {
|
if (chango && chango.kind === 'vec') {
|
||||||
// tt: 计算出当前这一行的所有 值 svg 在 Y 方向的偏移
|
// tt: 计算出当前这一行的所有 值 svg 在 Y 方向的偏移
|
||||||
const mLane = ['g', tt(0, Math.round((i - (iskip - ifirst) + 0.15) * yStep))];
|
const mLane = ['g', tt(0, Math.round((i - (renderStartNo - ifirst) + 0.15) * yStep))];
|
||||||
const { wave } = chango;
|
const { wave } = chango;
|
||||||
const jlen = wave.length;
|
|
||||||
|
|
||||||
perLane: {
|
perLane: {
|
||||||
let [tPre, vPre, mPre] = wave[0];
|
let [tPre, vPre, mPre] = wave[0];
|
||||||
|
|
||||||
let xPre = getX(pstate, tPre);
|
let xPre = getX(pstate, tPre);
|
||||||
const labeler = getLabel(lane);
|
const labeler = getLabel(lane);
|
||||||
for (let j = 1; j <= jlen; j++) {
|
for (let j = 1; j <= wave.length; j++) {
|
||||||
const mark = wave[j];
|
const mark = wave[j];
|
||||||
|
|
||||||
const [tCur, vCur, mCur] = (mark || [desc.time, 0, 0]);
|
const [tCur, vCur, mCur] = (mark || [desc.time, 0, 0]);
|
||||||
@ -191,7 +200,6 @@ function* renderValues(desc, pstate) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// console.log(view);
|
|
||||||
for (let i = 0; i < renderSignals.length; i++) {
|
for (let i = 0; i < renderSignals.length; i++) {
|
||||||
const lane = renderSignals[i];
|
const lane = renderSignals[i];
|
||||||
if (lane && lane.vlines) {
|
if (lane && lane.vlines) {
|
||||||
|
@ -3,6 +3,7 @@ import { globalSetting, globalStyle } from '../global';
|
|||||||
import { gl_Colors, gl_Shifts, gl_Shifts_for_bar, gl_WidthShifts, barShift, getRatio, screenHeightPixel, maskColorIndexOffset, posYFactor, glslInputLength, prettyPrint, ladderAnalog_GL_WidthShifts, lineAnlog_GL_WidthShifts } from './render-utils.js';
|
import { gl_Colors, gl_Shifts, gl_Shifts_for_bar, gl_WidthShifts, barShift, getRatio, screenHeightPixel, maskColorIndexOffset, posYFactor, glslInputLength, prettyPrint, ladderAnalog_GL_WidthShifts, lineAnlog_GL_WidthShifts } from './render-utils.js';
|
||||||
import { vertexShader, fragmentShader } from './render-shader.js';
|
import { vertexShader, fragmentShader } from './render-shader.js';
|
||||||
import { renderAsBit, renderAsCommonDigital, renderAsLadderAnalog, renderAsLineAnalog } from './toolbar/renderModal';
|
import { renderAsBit, renderAsCommonDigital, renderAsLadderAnalog, renderAsLineAnalog } from './toolbar/renderModal';
|
||||||
|
import { StaticCursor } from '@/components/render/cursor';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
@ -392,6 +393,17 @@ class WebGL2WaveRender {
|
|||||||
|
|
||||||
const _this = this;
|
const _this = this;
|
||||||
|
|
||||||
|
if (renderConfig.type === 'value') {
|
||||||
|
const renderValue = plugins.filter(plugin => plugin.name === 'pluginRenderValues')[0];
|
||||||
|
if (renderValue) {
|
||||||
|
renderValue(globalLookup, pstate, elements);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新静态 cursor
|
||||||
|
StaticCursor.updateLeft();
|
||||||
|
|
||||||
function linearAnimation(delta, oldVal, newVal) {
|
function linearAnimation(delta, oldVal, newVal) {
|
||||||
return (1 - delta) * oldVal + delta * newVal;
|
return (1 - delta) * oldVal + delta * newVal;
|
||||||
}
|
}
|
||||||
@ -537,10 +549,8 @@ class WebGL2WaveRender {
|
|||||||
pstate.oldYStep = pstate.yStep;
|
pstate.oldYStep = pstate.yStep;
|
||||||
pstate.oldYDuty = pstate.yDuty;
|
pstate.oldYDuty = pstate.yDuty;
|
||||||
|
|
||||||
if (needHiddenAnimation) {
|
|
||||||
_this.elements.grid.classList.remove('vcd-hidden');
|
_this.elements.grid.classList.remove('vcd-hidden');
|
||||||
_this.elements.values.classList.remove('vcd-hidden');
|
_this.elements.values.classList.remove('vcd-hidden');
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ export class FormatValueRender {
|
|||||||
if (valueString.length <= pos) {
|
if (valueString.length <= pos) {
|
||||||
return valueString;
|
return valueString;
|
||||||
}
|
}
|
||||||
const valSign = (value < 0) ? '-' : '+';
|
const valSign = (value < 0) ? '-' : '';
|
||||||
if (pos === 1) {
|
if (pos === 1) {
|
||||||
return valSign;
|
return valSign;
|
||||||
}
|
}
|
||||||
@ -155,6 +155,8 @@ export class FormatValueRender {
|
|||||||
* @param {number} pos 位置
|
* @param {number} pos 位置
|
||||||
*/
|
*/
|
||||||
floatTransform(fWidth, value, pos) {
|
floatTransform(fWidth, value, pos) {
|
||||||
|
const replacer = this.replacer;
|
||||||
|
|
||||||
if (fWidth === 16) {
|
if (fWidth === 16) {
|
||||||
value = this.calcIEEEFloat(value, 5, 10);
|
value = this.calcIEEEFloat(value, 5, 10);
|
||||||
} else if (fWidth === 32) {
|
} else if (fWidth === 32) {
|
||||||
@ -167,7 +169,7 @@ export class FormatValueRender {
|
|||||||
if (valueString.length <= pos) {
|
if (valueString.length <= pos) {
|
||||||
return valueString;
|
return valueString;
|
||||||
}
|
}
|
||||||
const valSign = (value < 0) ? '-' : '+';
|
const valSign = (value < 0) ? '-' : '';
|
||||||
if (pos === 1) {
|
if (pos === 1) {
|
||||||
return valSign;
|
return valSign;
|
||||||
}
|
}
|
||||||
@ -221,3 +223,141 @@ export class FormatValueRender {
|
|||||||
return sign * efficentPow2(e - offset) * (1 + m / mFrac);
|
return sign * efficentPow2(e - offset) * (1 + m / mFrac);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class JSValueRender {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} link 信号的ID
|
||||||
|
* @param {number} width 信号的位置宽度
|
||||||
|
* @param {string} replacer 位置不足的地方会用 replacer 补足,比如 ...
|
||||||
|
*/
|
||||||
|
constructor(link, width) {
|
||||||
|
this.formatCode = getValueFormatCode(link);
|
||||||
|
this.width = BigInt(width);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据当前的设置进行数值的渲染
|
||||||
|
* @param {number} value 波形当前的数值
|
||||||
|
* @returns {string} 转换后需要渲染的字符串
|
||||||
|
*/
|
||||||
|
explainAsNumber(value) {
|
||||||
|
const formatCode = this.formatCode;
|
||||||
|
switch (formatCode) {
|
||||||
|
// 二进制
|
||||||
|
case 0: return this.radixTransform(2, value);
|
||||||
|
// 八进制
|
||||||
|
case 1: return this.radixTransform(8, value);
|
||||||
|
// 十六进制
|
||||||
|
case 2: return this.radixTransform(16, value);
|
||||||
|
// 有符号整型
|
||||||
|
case 3: return this.radixTransform(10, value, true);
|
||||||
|
// 无符号整型
|
||||||
|
case 4: return this.radixTransform(10, value);
|
||||||
|
// 半精度浮点数
|
||||||
|
case 5: return this.floatTransform(16, value);
|
||||||
|
// 单精度浮点数
|
||||||
|
case 6: return this.floatTransform(32, value);
|
||||||
|
// 双精度浮点数
|
||||||
|
case 7: return this.floatTransform(64, value);
|
||||||
|
// 未知
|
||||||
|
default: return '?';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 整数的进制转换
|
||||||
|
* @param {number} radix 进制
|
||||||
|
* @param {number} value 值
|
||||||
|
* @param {number} pos 位置宽度
|
||||||
|
* @param {boolean} sign 是否是有符号数,默认为 false
|
||||||
|
*/
|
||||||
|
radixTransform(radix, value, sign = false) {
|
||||||
|
const width = this.width;
|
||||||
|
const replacer = this.replacer;
|
||||||
|
|
||||||
|
if (value === 'x') {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
value = BigInt(value);
|
||||||
|
|
||||||
|
// 如果是有符号数
|
||||||
|
if (sign) {
|
||||||
|
if ((value >> (width - 1n)) & 1n) {
|
||||||
|
value = value - (2n ** width);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseInt(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无符号的各类进制数字
|
||||||
|
return parseInt(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description IEEE 浮点数的转换
|
||||||
|
* 为什么没有 sign 参数?因为 IEEE 定义下的 float 第一个位置就是符号
|
||||||
|
* @param {number} fWidth 16, 32 或者 64
|
||||||
|
* @param {number} value 值
|
||||||
|
* @param {number} pos 位置
|
||||||
|
*/
|
||||||
|
floatTransform(fWidth, value) {
|
||||||
|
const replacer = this.replacer;
|
||||||
|
|
||||||
|
if (fWidth === 16) {
|
||||||
|
value = this.calcIEEEFloat(value, 5, 10);
|
||||||
|
} else if (fWidth === 32) {
|
||||||
|
value = this.calcIEEEFloat(value, 8, 23);
|
||||||
|
} else if (fWidth === 64) {
|
||||||
|
value = this.calcIEEEFloat(value, 11, 52);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据 e 和 m 得到计算 IEEE 浮点数的函数,默认第一个位置代表符号
|
||||||
|
* @param {number} value 值
|
||||||
|
* @param {number} eWidth 代表指数部分的位数
|
||||||
|
* @param {number} mWidth 代表有效尾数的位数
|
||||||
|
* @returns {(value: number) => number}
|
||||||
|
*/
|
||||||
|
calcIEEEFloat(value, eWidth, mWidth) {
|
||||||
|
const offset = (1 << (eWidth - 1)) - 1;
|
||||||
|
const mFrac = 1 << mWidth;
|
||||||
|
|
||||||
|
// 计算参考博客:https://blog.csdn.net/leo0308/article/details/117398166
|
||||||
|
let bits = value.toString(2);
|
||||||
|
const width = 1 + eWidth + mWidth;
|
||||||
|
// 应对 bits 长度和 预定长度不一致的情况
|
||||||
|
// 不足的地方补上 0,否则进行截断
|
||||||
|
if (bits.length < width) {
|
||||||
|
bits = '0'.repeat(width - bits.length) + bits;
|
||||||
|
}
|
||||||
|
if (bits.length > width) {
|
||||||
|
bits = bits.substring(bits.length - width);
|
||||||
|
}
|
||||||
|
|
||||||
|
const s = parseInt(bits[0], 2);
|
||||||
|
const e = parseInt(bits.substring(1, 1 + eWidth), 2);
|
||||||
|
const m = parseInt(bits.substring(2 + eWidth), 2);
|
||||||
|
|
||||||
|
const sign = (s === 1) ? -1 : 1;
|
||||||
|
// 全 0
|
||||||
|
if (e === 0) {
|
||||||
|
return sign * efficentPow2(-offset + 1 - mWidth) * m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全 1
|
||||||
|
if (e === ((1 << eWidth) - 1)) {
|
||||||
|
if (m === 0) {
|
||||||
|
return sign * Infinity;
|
||||||
|
}
|
||||||
|
return NaN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sign * efficentPow2(e - offset) * (1 + m / mFrac);
|
||||||
|
}
|
||||||
|
}
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
import { globalLookup } from "@/hook/global";
|
import { globalLookup } from "@/hook/global";
|
||||||
import { lineAnalog_WidthShift, lineAnlog_GL_WidthShifts, maskColorIndexOffset, posYFactor, prettyPrint } from "../render-utils";
|
import { lineAnalog_WidthShift, lineAnlog_GL_WidthShifts, maskColorIndexOffset, posYFactor, prettyPrint } from "../render-utils";
|
||||||
import { hexToSignedInt } from "./renderFormat";
|
import { FormatValueRender, hexToSignedInt, JSValueRender } from "./renderFormat";
|
||||||
|
|
||||||
function makeQuadVertices(p1, p2, p3, p4) {
|
function makeQuadVertices(p1, p2, p3, p4) {
|
||||||
return [
|
return [
|
||||||
@ -413,11 +413,13 @@ function getMaxMinByFormat(link, wave, time, formatCode, width) {
|
|||||||
let minVal = undefined;
|
let minVal = undefined;
|
||||||
const length = wave.length;
|
const length = wave.length;
|
||||||
|
|
||||||
|
const valueRender = new JSValueRender(link, width);
|
||||||
|
|
||||||
// TODO : 优化这段代码
|
// TODO : 优化这段代码
|
||||||
for (let i = 0; i < length; ++ i) {
|
for (let i = 0; i < length; ++ i) {
|
||||||
const [t1, val, mask] = wave[i];
|
const [t1, val, mask] = wave[i];
|
||||||
const t2 = (i === (length - 1)) ? time : wave[i + 1][0];
|
const t2 = (i === (length - 1)) ? time : wave[i + 1][0];
|
||||||
const numVal = explainAsJSNumber(formatCode, val, width);
|
const numVal = valueRender.explainAsNumber(val);
|
||||||
|
|
||||||
if (maxVal === undefined) {
|
if (maxVal === undefined) {
|
||||||
maxVal = numVal;
|
maxVal = numVal;
|
||||||
@ -479,6 +481,7 @@ export function renderAsLadderAnalog(lookup, link, wave, time) {
|
|||||||
|
|
||||||
const { maxVal, minVal } = getMaxMinByFormat(link, wave, time, formatCode, width);
|
const { maxVal, minVal } = getMaxMinByFormat(link, wave, time, formatCode, width);
|
||||||
const coordinateTransform = getMappingFunc(formatCode, maxVal, minVal);
|
const coordinateTransform = getMappingFunc(formatCode, maxVal, minVal);
|
||||||
|
const valueRender = new JSValueRender(link, width);
|
||||||
|
|
||||||
function makeLadderAnalogRenderParam(link, wave, time) {
|
function makeLadderAnalogRenderParam(link, wave, time) {
|
||||||
const [t1, val, mask] = wave;
|
const [t1, val, mask] = wave;
|
||||||
@ -489,7 +492,7 @@ export function renderAsLadderAnalog(lookup, link, wave, time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 根据当前格式进行转换
|
// 根据当前格式进行转换
|
||||||
const numVal = explainAsJSNumber(formatCode, val, width);
|
const numVal = valueRender.explainAsNumber(val);
|
||||||
// 此时的 y 是一个 -1 到 1 的浮点数,因为 VAO 我设置了 Int
|
// 此时的 y 是一个 -1 到 1 的浮点数,因为 VAO 我设置了 Int
|
||||||
const y = coordinateTransform(numVal);
|
const y = coordinateTransform(numVal);
|
||||||
const colorParam = { y, color: 5 };
|
const colorParam = { y, color: 5 };
|
||||||
@ -648,6 +651,7 @@ export function renderAsLineAnalog(lookup, link, wave, time) {
|
|||||||
const length = wave.length;
|
const length = wave.length;
|
||||||
const lineVertices = [];
|
const lineVertices = [];
|
||||||
const maskVertices = [];
|
const maskVertices = [];
|
||||||
|
const valueRender = new JSValueRender(link, width);
|
||||||
|
|
||||||
function makeLineAnalogRenderParam(link, wave, time) {
|
function makeLineAnalogRenderParam(link, wave, time) {
|
||||||
const [t1, val, mask] = wave;
|
const [t1, val, mask] = wave;
|
||||||
@ -658,7 +662,7 @@ export function renderAsLineAnalog(lookup, link, wave, time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 根据当前格式进行转换
|
// 根据当前格式进行转换
|
||||||
const numVal = explainAsJSNumber(formatCode, val, width);
|
const numVal = valueRender.explainAsNumber(val);
|
||||||
// 此时的 y 是一个 -1 到 1 的浮点数,因为 VAO 我设置了 Int
|
// 此时的 y 是一个 -1 到 1 的浮点数,因为 VAO 我设置了 Int
|
||||||
const y = coordinateTransform(numVal);
|
const y = coordinateTransform(numVal);
|
||||||
const colorParam = { y, color: 5 };
|
const colorParam = { y, color: 5 };
|
||||||
|
@ -21,6 +21,7 @@ const xOffsetUpdate = (pstate, nextOffsetXFn) => {
|
|||||||
|
|
||||||
pstate.oldXOffset = pstate.xOffset;
|
pstate.oldXOffset = pstate.xOffset;
|
||||||
pstate.xOffset = nextOffsetX;
|
pstate.xOffset = nextOffsetX;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,19 +6,25 @@ const yOffsetUpdate = (pstate, nextOffsetYFn) => {
|
|||||||
|
|
||||||
nextOffsetY = nextOffsetY;
|
nextOffsetY = nextOffsetY;
|
||||||
|
|
||||||
|
// 当前所有信号的高度之和
|
||||||
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);
|
|
||||||
const maxOffsetY = Math.max(-20,
|
if (currentRenderHeight < canvasHeight) {
|
||||||
currentRenderHeight - canvasHeight); // maximum offset
|
// 如果当前的信号高度小于画布的高度,则取消本次渲染
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxOffsetY = Math.max(-20, currentRenderHeight - canvasHeight);
|
||||||
nextOffsetY = Math.min(nextOffsetY, maxOffsetY);
|
nextOffsetY = Math.min(nextOffsetY, maxOffsetY);
|
||||||
|
|
||||||
const minOffsetY = -20; // minimum offset
|
const minOffsetY = -20;
|
||||||
nextOffsetY = Math.max(nextOffsetY, minOffsetY);
|
nextOffsetY = Math.max(nextOffsetY, minOffsetY);
|
||||||
|
|
||||||
// if (nextOffsetY === xOffset) {
|
console.log(nextOffsetY);
|
||||||
// return false; // exit without scroll
|
|
||||||
// }
|
|
||||||
|
|
||||||
pstate.oldYOffset = pstate.yOffset;
|
pstate.oldYOffset = pstate.yOffset;
|
||||||
pstate.yOffset = nextOffsetY;
|
pstate.yOffset = nextOffsetY;
|
||||||
|
@ -87,6 +87,12 @@
|
|||||||
"toolbar.format.float": "Float (32bit)",
|
"toolbar.format.float": "Float (32bit)",
|
||||||
"toolbar.format.double": "Double (64bit)",
|
"toolbar.format.double": "Double (64bit)",
|
||||||
|
|
||||||
|
"toolbar.location.to-begin": "Move to Beginning",
|
||||||
|
"toolbar.location.to-end": "Move to End",
|
||||||
|
"toolbar.location.to-next-change": "Go to Next Change Edge",
|
||||||
|
"toolbar.location.to-prev-change": "Go to Previous Change Edge",
|
||||||
|
"toolbar.location.make-location": "Create New Pivot",
|
||||||
|
|
||||||
"current-version": "current version",
|
"current-version": "current version",
|
||||||
"copyright": "The copyright of this software belongs to <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> project team. Welcome to <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>."
|
"copyright": "The copyright of this software belongs to <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> project team. Welcome to <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>."
|
||||||
}
|
}
|
@ -85,7 +85,11 @@
|
|||||||
"toolbar.format.float": "单精度(32bit)",
|
"toolbar.format.float": "单精度(32bit)",
|
||||||
"toolbar.format.double": "双精度(64bit)",
|
"toolbar.format.double": "双精度(64bit)",
|
||||||
|
|
||||||
|
"toolbar.location.to-begin": "移动至开头",
|
||||||
|
"toolbar.location.to-end": "移动至结尾",
|
||||||
|
"toolbar.location.to-next-change": "前往下一个变化的边沿",
|
||||||
|
"toolbar.location.to-prev-change": "前往上一个变化的边沿",
|
||||||
|
"toolbar.location.make-location": "创建新的信标",
|
||||||
|
|
||||||
"current-version": "当前版本",
|
"current-version": "当前版本",
|
||||||
"copyright": "本软件版权归 <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> 项目组所有,欢迎 <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>。"
|
"copyright": "本软件版权归 <a href=\"https://github.com/Digital-EDA\" target=\"_blank\">Digital-IDE</a> 项目组所有,欢迎 <a href=\"https://github.com/Digital-EDA/Digital-IDE\">Star</a>。"
|
||||||
|
@ -96,13 +96,18 @@
|
|||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
* @typedef {Object} Pstate
|
* @typedef {Object} Pstate
|
||||||
|
* @property {number} tgcd
|
||||||
* @property {number} width
|
* @property {number} width
|
||||||
* @property {number} height
|
* @property {number} height
|
||||||
* @property {number} xScale
|
* @property {number} xScale
|
||||||
|
* @property {number} xCursor
|
||||||
* @property {number} xOffset
|
* @property {number} xOffset
|
||||||
* @property {number} yOffset
|
* @property {number} yOffset
|
||||||
* @property {number} yStep
|
* @property {number} yStep
|
||||||
* @property {number} yDuty
|
* @property {number} yDuty
|
||||||
|
* @property {number} sidebarWidth
|
||||||
|
* @property {number} topBarHeight
|
||||||
|
* @property {number} botBarHeight
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,7 +129,7 @@
|
|||||||
/**
|
/**
|
||||||
* @description
|
* @description
|
||||||
* @typedef {Object} RenderConfig
|
* @typedef {Object} RenderConfig
|
||||||
* @property {'common' | 'action' | undefined} type
|
* @property {'common' | 'action' | 'value' | undefined} type
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user