diff --git a/public/iconfont.css b/public/iconfont.css index 1552658..159bf3b 100644 --- a/public/iconfont.css +++ b/public/iconfont.css @@ -1,6 +1,6 @@ @font-face { font-family: "iconfont"; /* Project id 4440655 */ - src: url('iconfont.woff2?t=1725033317914') format('woff2'); + src: url('iconfont.woff2?t=1725251353876') format('woff2'); } .iconfont { @@ -11,6 +11,10 @@ -moz-osx-font-smoothing: grayscale; } +.icon-clear:before { + content: "\e619"; +} + .icon-axis:before { content: "\ed1f"; } diff --git a/public/iconfont.woff2 b/public/iconfont.woff2 index 1e1f7fe..3ff238e 100644 Binary files a/public/iconfont.woff2 and b/public/iconfont.woff2 differ diff --git a/src/components/about/index.vue b/src/components/about/index.vue index c357714..3003ab2 100644 --- a/src/components/about/index.vue +++ b/src/components/about/index.vue @@ -49,7 +49,7 @@
- {{ t('current-version') }}   0.3.3 + {{ t('current-version') }}   0.4.0

diff --git a/src/components/pivot/axis-item.vue b/src/components/pivot/axis-item.vue new file mode 100644 index 0000000..bddf0c2 --- /dev/null +++ b/src/components/pivot/axis-item.vue @@ -0,0 +1,38 @@ + + + + + \ No newline at end of file diff --git a/src/components/pivot/cursor.js b/src/components/pivot/cursor.js index 37d4dec..6fdd593 100644 --- a/src/components/pivot/cursor.js +++ b/src/components/pivot/cursor.js @@ -32,7 +32,7 @@ export const SystemPivot = reactive({ this.label = formatTime(this.currentTime, timescale); }, updateLeft() { - this.left = calcCursorLeft(this.currentTime); + this.left = time2cursorX(this.currentTime); } }); @@ -46,20 +46,37 @@ export function changeCursorLocation() { SystemPivot.show = true; const pstate = globalLookup.pstate; if (pstate) { - const { xCursor, xOffset, xScale, tgcd, timescale } = pstate; - const currentTime = Math.round((xCursor - xOffset) / xScale) * tgcd; + const { xCursor, timescale } = pstate; + const currentTime = cursorX2time(xCursor); SystemPivot.currentTime = currentTime; SystemPivot.updateLabel(timescale); SystemPivot.updateLeft(); } } + +/** + * @description 给出当前左侧偏移亮,计算出它实际上代表的时间 + * @param {number} cursorX + * @returns {number} + */ +export function cursorX2time(cursorX) { + const pstate = globalLookup.pstate; + if (pstate) { + const { xOffset, xScale, tgcd } = pstate; + const currentTime = Math.round((cursorX - xOffset) / xScale) * tgcd; + return currentTime; + } + + return 0; +} + /** * @description 给出当前的时间,比如 23ns,计算当前这个点应该相对于左侧偏移多少 * @param {number} currentTime * @returns {number} */ -export function calcCursorLeft(currentTime) { +export function time2cursorX(currentTime) { const pstate = globalLookup.pstate; if (pstate) { const { xOffset, xScale, tgcd, timescale } = pstate; diff --git a/src/components/pivot/index.vue b/src/components/pivot/index.vue index 727d669..fda4593 100644 --- a/src/components/pivot/index.vue +++ b/src/components/pivot/index.vue @@ -24,6 +24,8 @@ /> + +
@@ -38,6 +40,7 @@ import Pivot from '@/components/pivot/system-pivot.vue'; import { globalLookup } from '@/hook/global'; import MovingPivotVue from './moving-pivot.vue'; import { UserPivotCtxShows } from './pivot-view'; +import RelativeAxis from './relative-axis.vue'; defineComponent({ name: 'main-render' }); @@ -45,10 +48,12 @@ defineComponent({ name: 'main-render' }); /** * @description 渲染区域被鼠标点击时 */ -function onMousedown() { +function onMousedown() { updateWireCurrentValue(); changeCursorLocation(); + console.log('enter'); + // 关闭所有 for (const id of UserPivotCtxShows.keys()) { UserPivotCtxShows.set(id, false); diff --git a/src/components/pivot/moving-pivot.vue b/src/components/pivot/moving-pivot.vue index 9d8d5b2..a3a5864 100644 --- a/src/components/pivot/moving-pivot.vue +++ b/src/components/pivot/moving-pivot.vue @@ -21,7 +21,7 @@ import { emitter, globalLookup } from '@/hook/global'; import { eventHandler, registerWheelEvent } from '@/hook/wave-view'; import { computed, defineComponent, ref, onMounted } from 'vue'; -import { calcCursorLeft, MovingPivot } from './cursor'; +import { time2cursorX, MovingPivot, cursorX2time } from './cursor'; import formatTime from '@/hook/wave-view/format-time'; import { getNearestUserPivot, UserPivots } from './pivot-view'; @@ -54,12 +54,12 @@ function onMousemove(event) { const pstate = globalLookup.pstate; const x = event.clientX || event.x; pstate.xCursor = x; - const { xScale, xOffset, tgcd, timescale, xCursor } = pstate; - const currentT = Math.round((xCursor - xOffset) / xScale) * tgcd; + const { timescale, xCursor } = pstate; + const currentT = cursorX2time(xCursor); globalLookup.currentTime = currentT; MovingPivot.currentTime = currentT; MovingPivot.label = formatTime(currentT, timescale); - MovingPivot.left = calcCursorLeft(currentT); + MovingPivot.left = time2cursorX(currentT); const pivot = UserPivots.get(currentT); if (pivot !== undefined) { diff --git a/src/components/pivot/pivot-view.js b/src/components/pivot/pivot-view.js index 2909835..f192bac 100644 --- a/src/components/pivot/pivot-view.js +++ b/src/components/pivot/pivot-view.js @@ -1,5 +1,5 @@ import { reactive, ref } from "vue"; -import { calcCursorLeft, SystemPivot } from "./cursor"; +import { time2cursorX, SystemPivot } from "./cursor"; import { globalLookup } from "@/hook/global"; import formatTime from "@/hook/wave-view/format-time"; @@ -16,9 +16,21 @@ import formatTime from "@/hook/wave-view/format-time"; /** * @description 该数据结构描述了所有通过 makePivot 创建的 用户信标 - * @type {Map} + * @type {Map} number 为时间 */ export const UserPivots = reactive(new Map()); + +/** + * @type {Map} number 为 id + */ +export const Id2Pivot = reactive(new Map()); + +/** + * @description 应该被渲染到当前屏幕中的 + * @type {Set} + */ +export const VisibleUserPivotIds = reactive(new Set()); + export const orderedTimes = []; export const UserPivotColor = ref('#1e90ff'); @@ -33,12 +45,15 @@ export function createPivot(time) { } const id = Date.now(); - const x = calcCursorLeft(time); + const x = time2cursorX(time); const timescale = globalLookup.timescale; const label = formatTime(time, timescale); const show = true; - UserPivots.set(time, { time, x, id, label, show }); + const pivot = { time, x, id, label, show }; + UserPivots.set(time, pivot); + Id2Pivot.set(id, pivot); + orderedTimes.push(time); orderedTimes.sort((a, b) => a < b); } @@ -57,21 +72,39 @@ export function deletePivot(time) { return; } - UserPivots.delete(time); const i = searchOrderedTimeIndex(time); if (i !== undefined) { orderedTimes.splice(i, 1); } + + if (UserPivots.has(time)) { + const pivot = UserPivots.get(time); + UserPivots.delete(time); + Id2Pivot.delete(pivot.id); + UserPivotCtxShows.delete(pivot.id); + } + + currentPivotId.value = 0; } +export const boxShift = 25; + export function updateAllPivots() { // 更新系统信标 SystemPivot.updateLeft(); + + // 维护可见 Pivots + VisibleUserPivotIds.clear(); // 更新所有用户信标 for (const time of UserPivots.keys()) { const pivot = UserPivots.get(time); - pivot.x = calcCursorLeft(time); + const x = time2cursorX(time); + const cx = x - boxShift; // 25 是 boxShift,也就是展示数字圆形的一半宽度 + if (cx > 0 && cx < (globalLookup.pstate.width || window.innerWidth)) { + VisibleUserPivotIds.add(pivot.id); + } + pivot.x = x; } } @@ -141,3 +174,5 @@ export function getNearestUserPivot(time) { * @type {Map} */ export const UserPivotCtxShows = reactive(new Map()); + +export const currentPivotId = ref(0); \ No newline at end of file diff --git a/src/components/pivot/relative-axis.js b/src/components/pivot/relative-axis.js new file mode 100644 index 0000000..38429ed --- /dev/null +++ b/src/components/pivot/relative-axis.js @@ -0,0 +1,6 @@ +import { reactive } from "vue"; + +export const RelativeAxis = reactive({ + show: false +}); + diff --git a/src/components/pivot/relative-axis.vue b/src/components/pivot/relative-axis.vue new file mode 100644 index 0000000..d27f36d --- /dev/null +++ b/src/components/pivot/relative-axis.vue @@ -0,0 +1,48 @@ + + + + + \ No newline at end of file diff --git a/src/components/pivot/user-pivot.vue b/src/components/pivot/user-pivot.vue index c991d10..c9c47ed 100644 --- a/src/components/pivot/user-pivot.vue +++ b/src/components/pivot/user-pivot.vue @@ -1,6 +1,6 @@ diff --git a/src/components/toolbar/index.vue b/src/components/toolbar/index.vue index 0146340..9e448ee 100644 --- a/src/components/toolbar/index.vue +++ b/src/components/toolbar/index.vue @@ -32,17 +32,7 @@ import { MovingPivot } from '../pivot/cursor'; defineComponent({ name: 'toolbar' }); function onEnter() { - console.log('enter'); MovingPivot.show = false; - console.log(MovingPivot.show); - nextTick(() => { - MovingPivot.show = false; - }); - setTimeout(() => { - console.log(MovingPivot.show); - MovingPivot.show = false; - }, 20); - } diff --git a/src/hook/color.js b/src/hook/color.js new file mode 100644 index 0000000..392c3f8 --- /dev/null +++ b/src/hook/color.js @@ -0,0 +1,68 @@ +/** + * @typedef {Object} RgbColor + * @property {number} r + * @property {number} g + * @property {number} b + */ + +/** + * @description 解析 rgb 字符串 + * @param {string} colorString 形如 #1e90ff 或者 rgba(0, 206, 209, 1) 这样的字符串 + * @returns {RgbColor | undefined} + */ +export function parseColor(colorString) { + // 检查是否是十六进制颜色 + if (colorString.startsWith('#')) { + let hex = colorString.slice(1); + if (hex.length === 3) { + hex = hex.split('').map(c => c + c).join(''); + } + const r = parseInt(hex.slice(0, 2), 16); + const g = parseInt(hex.slice(2, 4), 16); + const b = parseInt(hex.slice(4, 6), 16); + return { r, g, b }; + } + // 检查是否是 RGBA 颜色 + else if (colorString.startsWith('rgba')) { + const matches = colorString.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*(\d+(\.\d+)?)\)/); + if (matches) { + const r = parseInt(matches[1], 10); + const g = parseInt(matches[2], 10); + const b = parseInt(matches[3], 10); + return { r, g, b }; + } + } + // 检查是否是 RGB 颜色 + else if (colorString.startsWith('rgb')) { + const matches = colorString.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/); + if (matches) { + const r = parseInt(matches[1], 10); + const g = parseInt(matches[2], 10); + const b = parseInt(matches[3], 10); + return { r, g, b }; + } + } + + return undefined; +} + +/** + * @description 提升颜色的亮度 + * @param {RgbColor} rgb + * @param {number} percent 0 - 100 的数字,代表增强的亮度比例 + * @returns {RgbColor} + */ +export function increaseBrightness(rgb, percent) { + // 确保 percent 在 0 到 100 之间 + percent = Math.max(0, Math.min(100, percent)); + + // 计算每个颜色分量的增量 + const increment = (percent / 100) * 255; + + // 提升每个颜色分量的亮度 + const r = Math.min(255, Math.round(rgb.r + increment)); + const g = Math.min(255, Math.round(rgb.g + increment)); + const b = Math.min(255, Math.round(rgb.b + increment)); + + return { r, g, b }; +} \ No newline at end of file diff --git a/src/i18n/en.json b/src/i18n/en.json index 542fbd0..2ad154f 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -92,6 +92,8 @@ "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", + "toolbar.location.clear-location": "Clear All Pivots", + "toolbar.location.clear-location-dialog": "Are you sure to clear all the pivots ?", "context-menu.cannot-join-repeat-group": "current signal is already contained in this group", @@ -102,6 +104,7 @@ "pivot.context.delete": "delete pivot", "pivot.context.display-axis": "create relative axis", + "pivot.context.cancel-axis": "cancel relative axis", "setting.appearance.pivot-color": "pivot color", "setting.appearance.moving-pivot": "moving pivot", diff --git a/src/i18n/zh.json b/src/i18n/zh.json index 00ee4dc..95636f9 100644 --- a/src/i18n/zh.json +++ b/src/i18n/zh.json @@ -90,6 +90,8 @@ "toolbar.location.to-next-change": "前往下一个变化的边沿", "toolbar.location.to-prev-change": "前往上一个变化的边沿", "toolbar.location.make-location": "创建新的信标", + "toolbar.location.clear-location": "清除所有信标", + "toolbar.location.clear-location-dialog": "您确定要清除所有的信标吗?", "context-menu.cannot-join-repeat-group": "当前信号已在此分组中", @@ -100,6 +102,7 @@ "pivot.context.delete": "删除信标", "pivot.context.display-axis": "创建相对坐标轴", + "pivot.context.cancel-axis": "取消相对坐标轴", "setting.appearance.pivot-color": "信标颜色", "setting.appearance.moving-pivot": "移动信标",