feat(数据大屏): 数据大屏增加刻度尺指示功能

This commit is contained in:
wangjiahao 2024-06-23 23:26:17 +08:00
parent d1466f511c
commit 486d1f03a4
5 changed files with 239 additions and 9 deletions

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1719155593625" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="32183" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M658.52 0v658.52H0V1024h1024V0H658.52z m23.1 991.3V835.18h-32.7V991.3H465.31V790.06h-32.7V991.3H249.02V835.18h-32.7V991.3H32.7V691.22h658.52V32.7H991.3v183.61H835.18v32.7H991.3v183.61H790.06v32.7H991.3v183.59H835.18v32.7H991.3v309.68H681.62z" p-id="32184"></path></svg>

After

Width:  |  Height:  |  Size: 604 B

View File

@ -157,6 +157,7 @@ onUnmounted(() => {
background-color: @side-area-background;
border-top: 1px solid @side-outline-border-color;
color: #fff;
z-index: 2;
transition: 0.5s;
.scale-area {
display: flex;

View File

@ -8,6 +8,14 @@ const props = defineProps({
tickLabelFormatter: {
type: Function,
default: value => value.toString() //
},
size: {
type: Number,
default: 300 //
},
direction: {
type: String,
default: 'horizontal' //
}
})
@ -15,10 +23,14 @@ const labelInterval = 5
const { canvasStyleData } = storeToRefs(dvMainStore)
const rulerSize = computed(() =>
props.direction === 'horizontal' ? canvasStyleData.value.width : canvasStyleData.value.height
)
const ticks = computed(() => {
const result = []
let currentValue = 0
while (currentValue <= canvasStyleData.value.width) {
while (currentValue <= rulerSize.value) {
const isLong = currentValue % (labelInterval * tickSize.value) === 0
const label = isLong ? props.tickLabelFormatter(currentValue) : ''
result.push({ position: (currentValue * canvasStyleData.value.scale) / 100, label, isLong })
@ -29,28 +41,47 @@ const ticks = computed(() => {
const wStyle = computed(() => {
return {
width: canvasStyleData.value.width * 1.5 + 'px'
width: rulerSize.value * 1.5 + 'px'
}
})
const radio = computed(() => rulerSize.value / canvasStyleData.value.width)
const tickSize = computed(
() =>
10 *
Math.max(Math.floor(200000 / (canvasStyleData.value.width * canvasStyleData.value.scale)), 1)
Math.max(
Math.floor((200000 * radio.value) / (rulerSize.value * canvasStyleData.value.scale)),
1
)
)
const scaleWidth = computed(() => (canvasStyleData.value.width * canvasStyleData.value.scale) / 100)
const scaleWidth = computed(() => (rulerSize.value * canvasStyleData.value.scale) / 100)
const rulerScroll = e => {
wRuleRef.value.scrollTo(e.scrollLeft, 0)
const left = props.direction === 'vertical' ? e.scrollTop : e.scrollLeft
wRuleRef.value.scrollTo(left, 0)
}
const outerStyle = computed(() => {
return {
width: props.direction === 'vertical' ? props.size - 30 + 'px' : '100%'
}
})
defineExpose({
rulerScroll
})
</script>
<template>
<div class="ruler-outer" ref="wRuleRef">
<div
class="ruler-outer"
:style="outerStyle"
:class="{ 'ruler-vertical': direction === 'vertical' }"
ref="wRuleRef"
>
<!--覆盖着尺子上方防止鼠标移到尺子位置滑动-->
<div class="ruler-shadow" :style="outerStyle"></div>
<div :style="wStyle" class="ruler-outer-scroll">
<div class="ruler" :style="{ width: `${scaleWidth}px` }">
<div class="ruler-line" :style="{ width: `${scaleWidth}px` }"></div>
@ -73,8 +104,36 @@ defineExpose({
width: 0px !important;
height: 0px !important;
}
.ruler-vertical {
position: absolute;
left: 30px;
top: 30px;
transform-origin: top left;
transform: rotate(90deg);
overflow-y: auto;
overflow-x: hidden;
z-index: 1;
.ruler {
.ruler-line {
top: 0;
}
.ruler-tick {
top: 0;
.tick-label {
transform: rotate(180deg);
}
}
}
}
.ruler-shadow {
position: absolute;
height: 30px;
z-index: 10;
overflow: hidden;
}
.ruler-outer {
width: 100%;
overflow-x: auto;
background-color: #2c2c2c;
}

View File

@ -0,0 +1,144 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia'
const dvMainStore = dvMainStoreWithOut()
const wRuleRef = ref(null)
const props = defineProps({
tickLabelFormatter: {
type: Function,
default: value => value.toString() //
},
direction: {
type: String,
default: 'horizontal' //
}
})
const labelInterval = 5
const { canvasStyleData } = storeToRefs(dvMainStore)
const ticks = computed(() => {
const result = []
let currentValue = 0
while (currentValue <= canvasStyleData.value.height) {
const isLong = currentValue % (labelInterval * tickSize.value) === 0
const label = isLong ? props.tickLabelFormatter(currentValue) : ''
result.push({ position: (currentValue * canvasStyleData.value.scale) / 100, label, isLong })
currentValue += tickSize.value
}
return result
})
const hStyle = computed(() => {
return {
height: canvasStyleData.value.height * 1.5 + 'px'
}
})
const tickSize = computed(
() =>
10 *
Math.max(Math.floor(200000 / (canvasStyleData.value.height * canvasStyleData.value.scale)), 1)
)
const scaleHeight = computed(
() => (canvasStyleData.value.height * canvasStyleData.value.scale) / 100
)
const rulerScroll = e => {
wRuleRef.value.scrollTo(0, e.scrollHeight)
}
defineExpose({
rulerScroll
})
</script>
<template>
<div class="ruler-outer-vertical" ref="wRuleRef">
testtest
<!--覆盖着尺子上方防止鼠标移到尺子位置滑动-->
<div class="ruler-shadow-vertical"></div>
<div :style="hStyle" class="ruler-outer-vertical-scroll">
<div class="ruler" :style="{ height: `${scaleHeight}px` }">
<div class="ruler-line" :style="{ height: `${scaleHeight}px` }"></div>
<div
v-for="(tick, index) in ticks"
:key="index"
class="ruler-tick"
:class="{ 'long-tick': tick.isLong }"
:style="{ left: `${tick.position}px` }"
>
<span v-if="tick.isLong" class="tick-label">{{ tick.label }}</span>
</div>
</div>
</div>
</div>
</template>
<style scoped lang="less">
::-webkit-scrollbar {
width: 0px !important;
height: 0px !important;
}
.ruler-shadow-vertical {
position: absolute;
width: 30px;
height: 100%;
z-index: 10;
overflow: hidden;
}
.ruler-outer-vertical {
position: absolute;
width: 30px;
height: 100%;
overflow-y: auto;
background-color: #2c2c2c;
}
.ruler-outer-vertical-scroll {
display: flex;
align-items: center;
justify-content: center;
}
.ruler {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
height: 100%;
border-left: 1px solid #974e4e;
background-color: #2c2c2c;
}
.ruler-line {
position: absolute;
bottom: 0;
height: 1px;
background-color: #ac2a2a;
}
.ruler-tick {
position: absolute;
bottom: 1px;
height: 3px;
width: 1px;
background-color: #e38a8a;
}
.long-tick {
width: 1px;
height: 15px;
}
.tick-label {
position: absolute;
bottom: 2px;
font-size: 8px;
left: 50%;
transform: translateX(2%);
white-space: nowrap;
}
</style>

View File

@ -65,6 +65,7 @@ const contextmenuStore = contextmenuStoreWithOut()
const composeStore = composeStoreWithOut()
const canvasCacheOutRef = ref(null)
const deWRulerRef = ref(null)
const deHRulerRef = ref(null)
const {
fullscreenFlag,
@ -82,6 +83,7 @@ const canvasInner = ref(null)
const leftSidebarRef = ref(null)
const dvLayout = ref(null)
const canvasCenterRef = ref(null)
const mainHeight = ref(300)
const state = reactive({
datasetTree: [],
scaleHistory: null,
@ -179,9 +181,9 @@ const initScroll = () => {
nextTick(() => {
const { width, height } = canvasStyleData.value
const mainWidth = canvasCenterRef.value.clientWidth
const mainHeight = canvasCenterRef.value.clientHeight
mainHeight.value = canvasCenterRef.value.clientHeight
const scrollX = (1.5 * width - mainWidth) / 2
const scrollY = (1.5 * height - mainHeight) / 2 + 20
const scrollY = (1.5 * height - mainHeight.value) / 2 + 20
//
canvasOut.value.scrollTo(scrollX, scrollY)
})
@ -361,7 +363,9 @@ const viewsPropertiesShow = computed(
const scrollCanvas = e => {
deWRulerRef.value.rulerScroll(e)
deHRulerRef.value.rulerScroll(e)
}
eventBus.on('handleNew', handleNew)
</script>
@ -393,7 +397,13 @@ eventBus.on('handleNew', handleNew)
</dv-sidebar>
<!-- 中间画布 -->
<main id="dv-main-center" class="center" ref="canvasCenterRef">
<div class="de-ruler-icon-outer">
<el-icon class="de-ruler-icon">
<Icon name="dv-ruler" />
</el-icon>
</div>
<de-ruler ref="deWRulerRef"></de-ruler>
<de-ruler direction="vertical" :size="mainHeight" ref="deHRulerRef"></de-ruler>
<el-scrollbar
ref="canvasOut"
@scroll="scrollCanvas"
@ -554,4 +564,19 @@ eventBus.on('handleNew', handleNew)
justify-content: center;
align-items: center;
}
.de-ruler-icon-outer {
background: #2c2c2c;
position: absolute;
width: 30px;
height: 30px;
z-index: 3;
color: #ebebeb;
.de-ruler-icon {
margin-left: 6px;
margin-top: 6px;
font-size: 24px;
color: #ebebeb;
}
}
</style>