pct tool draft

This commit is contained in:
Tako 2023-12-01 23:40:30 +00:00
parent 722a279578
commit 635d70fe56
4 changed files with 148 additions and 0 deletions

10
src/auto-imports.d.ts vendored
View File

@ -8,6 +8,7 @@ declare global {
const ColorPreferences: typeof import('./stores/colors')['ColorPreferences']
const DashboardLayout: typeof import('./stores/layout')['DashboardLayout']
const EffectScope: typeof import('vue')['EffectScope']
const KeyCode: typeof import('./composables/inputListener')['KeyCode']
const OpenTradeVizOptions: typeof import('./stores/settings')['OpenTradeVizOptions']
const TradeLayout: typeof import('./stores/layout')['TradeLayout']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
@ -186,6 +187,7 @@ declare global {
const useIdle: typeof import('@vueuse/core')['useIdle']
const useImage: typeof import('@vueuse/core')['useImage']
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
const useInputListener: typeof import('./composables/inputListener')['useInputListener']
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
const useInterval: typeof import('@vueuse/core')['useInterval']
const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn']
@ -215,6 +217,7 @@ declare global {
const usePairlistConfigStore: typeof import('./stores/pairlistConfig')['usePairlistConfigStore']
const useParallax: typeof import('@vueuse/core')['useParallax']
const useParentElement: typeof import('@vueuse/core')['useParentElement']
const usePercentageTool: typeof import('./composables/percentageTool')['usePercentageTool']
const usePerformanceObserver: typeof import('@vueuse/core')['usePerformanceObserver']
const usePermission: typeof import('@vueuse/core')['usePermission']
const usePlotConfigStore: typeof import('./stores/plotConfig')['usePlotConfigStore']
@ -302,6 +305,7 @@ declare global {
declare global {
// @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
import('vue')
}
// for vue template auto import
import { UnwrapRef } from 'vue'
@ -310,6 +314,7 @@ declare module 'vue' {
readonly ColorPreferences: UnwrapRef<typeof import('./stores/colors')['ColorPreferences']>
readonly DashboardLayout: UnwrapRef<typeof import('./stores/layout')['DashboardLayout']>
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly KeyCode: UnwrapRef<typeof import('./composables/inputListener')['KeyCode']>
readonly OpenTradeVizOptions: UnwrapRef<typeof import('./stores/settings')['OpenTradeVizOptions']>
readonly TradeLayout: UnwrapRef<typeof import('./stores/layout')['TradeLayout']>
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
@ -488,6 +493,7 @@ declare module 'vue' {
readonly useIdle: UnwrapRef<typeof import('@vueuse/core')['useIdle']>
readonly useImage: UnwrapRef<typeof import('@vueuse/core')['useImage']>
readonly useInfiniteScroll: UnwrapRef<typeof import('@vueuse/core')['useInfiniteScroll']>
readonly useInputListener: UnwrapRef<typeof import('./composables/inputListener')['useInputListener']>
readonly useIntersectionObserver: UnwrapRef<typeof import('@vueuse/core')['useIntersectionObserver']>
readonly useInterval: UnwrapRef<typeof import('@vueuse/core')['useInterval']>
readonly useIntervalFn: UnwrapRef<typeof import('@vueuse/core')['useIntervalFn']>
@ -517,6 +523,7 @@ declare module 'vue' {
readonly usePairlistConfigStore: UnwrapRef<typeof import('./stores/pairlistConfig')['usePairlistConfigStore']>
readonly useParallax: UnwrapRef<typeof import('@vueuse/core')['useParallax']>
readonly useParentElement: UnwrapRef<typeof import('@vueuse/core')['useParentElement']>
readonly usePercentageTool: UnwrapRef<typeof import('./composables/percentageTool')['usePercentageTool']>
readonly usePerformanceObserver: UnwrapRef<typeof import('@vueuse/core')['usePerformanceObserver']>
readonly usePermission: UnwrapRef<typeof import('@vueuse/core')['usePermission']>
readonly usePlotConfigStore: UnwrapRef<typeof import('./stores/plotConfig')['usePlotConfigStore']>
@ -606,6 +613,7 @@ declare module '@vue/runtime-core' {
readonly ColorPreferences: UnwrapRef<typeof import('./stores/colors')['ColorPreferences']>
readonly DashboardLayout: UnwrapRef<typeof import('./stores/layout')['DashboardLayout']>
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly KeyCode: UnwrapRef<typeof import('./composables/inputListener')['KeyCode']>
readonly OpenTradeVizOptions: UnwrapRef<typeof import('./stores/settings')['OpenTradeVizOptions']>
readonly TradeLayout: UnwrapRef<typeof import('./stores/layout')['TradeLayout']>
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
@ -784,6 +792,7 @@ declare module '@vue/runtime-core' {
readonly useIdle: UnwrapRef<typeof import('@vueuse/core')['useIdle']>
readonly useImage: UnwrapRef<typeof import('@vueuse/core')['useImage']>
readonly useInfiniteScroll: UnwrapRef<typeof import('@vueuse/core')['useInfiniteScroll']>
readonly useInputListener: UnwrapRef<typeof import('./composables/inputListener')['useInputListener']>
readonly useIntersectionObserver: UnwrapRef<typeof import('@vueuse/core')['useIntersectionObserver']>
readonly useInterval: UnwrapRef<typeof import('@vueuse/core')['useInterval']>
readonly useIntervalFn: UnwrapRef<typeof import('@vueuse/core')['useIntervalFn']>
@ -813,6 +822,7 @@ declare module '@vue/runtime-core' {
readonly usePairlistConfigStore: UnwrapRef<typeof import('./stores/pairlistConfig')['usePairlistConfigStore']>
readonly useParallax: UnwrapRef<typeof import('@vueuse/core')['useParallax']>
readonly useParentElement: UnwrapRef<typeof import('@vueuse/core')['useParentElement']>
readonly usePercentageTool: UnwrapRef<typeof import('./composables/percentageTool')['usePercentageTool']>
readonly usePerformanceObserver: UnwrapRef<typeof import('@vueuse/core')['usePerformanceObserver']>
readonly usePermission: UnwrapRef<typeof import('@vueuse/core')['usePermission']>
readonly usePlotConfigStore: UnwrapRef<typeof import('./stores/plotConfig')['usePlotConfigStore']>

View File

@ -133,6 +133,8 @@ const diffCols = computed(() => {
return getDiffColumnsFromPlotConfig(props.plotConfig);
});
usePercentageTool(candleChart);
function updateChart(initial = false) {
if (!hasData.value) {
return;

View File

@ -0,0 +1,30 @@
// codes we care about
export enum KeyCode {
SHIFT_LEFT = 'ShiftLeft',
CTRL_LEFT = 'ControlLeft',
}
export function useInputListener() {
const allCodes = Object.values(KeyCode) as string[];
const pressed = ref<string[]>([]);
function onKeyDown(e: KeyboardEvent) {
if (!allCodes.includes(e.code) || pressed.value.includes(e.code)) return;
pressed.value.push(e.code);
}
function onKeyUp(e: KeyboardEvent) {
const i = pressed.value.indexOf(e.code);
if (i > -1) {
pressed.value.splice(i, 1);
}
}
useEventListener(document, 'keydown', onKeyDown);
useEventListener(document, 'keyup', onKeyUp);
return {
isKeyPressed: (key: KeyCode) => pressed.value.includes(key),
isAnyPressed: computed(() => pressed.value.length > 0),
};
}

View File

@ -0,0 +1,106 @@
import { use } from 'echarts/core';
import { ElementEvent } from 'echarts';
import { useInputListener } from './inputListener';
import { GraphicComponent } from 'echarts/components';
use([GraphicComponent]);
export function usePercentageTool(chartRef: Ref) {
const inputListener = useInputListener();
const mousePos = ref({ x: 0, y: 0 });
const startPos = ref({ x: 0, y: 0 });
const drawLimitPerSecond = 144;
const canDraw = ref(true);
const active = ref(false);
function mouseMove(e: ElementEvent) {
mousePos.value.x = e.offsetX;
mousePos.value.y = e.offsetY;
if (!active.value || !canDraw.value) return;
draw(e.offsetX, e.offsetY);
}
function drawStart() {
active.value = true;
startPos.value = { ...mousePos.value };
chartRef.value?.setOption({
dataZoom: [{ disabled: true }],
graphic: [
{
type: 'line',
shape: {
x1: mousePos.value.x,
x2: mousePos.value.x,
y1: mousePos.value.y,
y2: mousePos.value.y,
},
style: {
stroke: 'white',
},
},
{ type: 'text', z: 5 },
],
});
}
function drawEnd() {
active.value = false;
chartRef.value?.setOption({
dataZoom: [{ disabled: false }],
graphic: [{ $action: 'remove' }, { $action: 'remove' }],
});
}
function draw(x: number, y: number) {
const startPrice = Number(
chartRef.value?.convertFromPixel({ seriesIndex: 0 }, [startPos.value.x, startPos.value.y])[1],
);
const endPrice = Number(chartRef.value?.convertFromPixel({ seriesIndex: 0 }, [x, y])[1]);
const pct = Math.abs(((startPrice - endPrice) / startPrice) * 100).toFixed(2);
chartRef.value?.setOption({
graphic: [
{
shape: {
x2: x,
y2: y,
},
},
{
style: {
x: x,
y: y - 20,
text: (startPrice < endPrice ? pct : '-' + pct) + '%',
font: '16px sans-serif',
fill: 'white',
},
},
],
});
canDraw.value = false;
setTimeout(() => {
canDraw.value = true;
}, 1000 / drawLimitPerSecond);
}
watch(
() => inputListener.isAnyPressed.value,
() => {
if (inputListener.isKeyPressed(KeyCode.SHIFT_LEFT)) {
drawStart();
} else if (active.value) {
drawEnd();
}
},
);
onMounted(() => {
chartRef.value?.chart.getZr().on('mousemove', mouseMove);
});
onUnmounted(() => {
chartRef.value?.chart.getZr().off('mousemove', mouseMove);
});
}