feat: 添加画布标尺

This commit is contained in:
pipipi-pikachu 2022-05-01 14:15:44 +08:00
parent e450a944a9
commit 297aa6cca2
4 changed files with 171 additions and 1 deletions

View File

@ -18,6 +18,7 @@ export interface MainState {
editorAreaFocus: boolean;
disableHotkeys: boolean;
showGridLines: boolean;
showRuler: boolean;
creatingElement: CreatingElement | null;
availableFonts: typeof SYS_FONTS;
toolbarState: ToolbarStates;
@ -41,6 +42,7 @@ export const useMainStore = defineStore('main', {
editorAreaFocus: false, // 编辑区域聚焦
disableHotkeys: false, // 禁用快捷键
showGridLines: false, // 显示网格线
showRuler: false, // 显示标尺
creatingElement: null, // 正在插入的元素信息,需要通过绘制插入的元素(文字、形状、线条)
availableFonts: SYS_FONTS, // 当前环境可用字体
toolbarState: ToolbarStates.SLIDE_DESIGN, // 右侧工具栏状态
@ -112,6 +114,10 @@ export const useMainStore = defineStore('main', {
this.showGridLines = show
},
setRulerState(show: boolean) {
this.showRuler = show
},
setCreatingElement(element: CreatingElement | null) {
this.creatingElement = element
},

View File

@ -0,0 +1,142 @@
<template>
<div class="ruler">
<div
class="h"
:style="{
width: viewportStyles.width * canvasScale + 'px',
left: viewportStyles.left + 'px',
}"
>
<div class="ruler-mark-100" v-for="mark in 10" :key="`mark-100-${mark}`">{{mark * 100}}</div>
</div>
<div
class="v"
:style="{
height: viewportStyles.height * canvasScale + 'px',
top: viewportStyles.top + 'px',
}"
>
<div
class="ruler-mark-100"
v-for="mark in 10"
:key="mark"
:style="{ height: markSize + 'px' }"
>{{mark * 100}}</div>
</div>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
interface ViewportStyles {
top: number;
left: number;
width: number;
height: number;
}
export default defineComponent({
props: {
viewportStyles: {
type: Object as PropType<ViewportStyles>,
required: true,
},
},
setup(props) {
const { canvasScale } = storeToRefs(useMainStore())
const markSize = computed(() => {
return props.viewportStyles.width * canvasScale.value / 10
})
return {
canvasScale,
markSize,
}
},
})
</script>
<style lang="scss" scoped>
.ruler {
font-size: 12px;
}
.h {
position: absolute;
background-color: #fff;
border: 1px solid $borderColor;
height: 20px;
top: 5px;
display: flex;
justify-content: space-between;
align-items: center;
.ruler-mark-100 {
height: 100%;
line-height: 20px;
text-align: right;
flex: 1;
padding-right: 5px;
position: relative;
&:not(:last-child)::after {
content: '';
width: .1px;
height: 12px;
position: absolute;
right: 0;
bottom: 0;
background-color: #999;
}
&::before {
content: '';
width: .1px;
height: 8px;
position: absolute;
right: 50%;
bottom: 0;
background-color: #999;
}
}
}
.v {
position: absolute;
background-color: #fff;
border: 1px solid $borderColor;
width: 20px;
left: 5px;
overflow: hidden;
.ruler-mark-100 {
width: 100%;
line-height: 20px;
text-align: right;
padding-bottom: 5px;
position: relative;
writing-mode: vertical-rl;
&:not(:last-child)::after {
content: '';
height: .1px;
width: 12px;
position: absolute;
bottom: 0;
right: 0;
background-color: #999;
}
&::before {
content: '';
height: .1px;
width: 8px;
position: absolute;
bottom: 50%;
right: 0;
background-color: #999;
}
}
}
</style>

View File

@ -76,6 +76,8 @@
<div class="drag-mask" v-if="spaceKeyState"></div>
<Ruler :viewportStyles="viewportStyles" v-if="showRuler" />
<Modal
v-model:visible="linkDialogVisible"
:footer="null"
@ -121,6 +123,7 @@ import EditableElement from './EditableElement.vue'
import MouseSelection from './MouseSelection.vue'
import ViewportBackground from './ViewportBackground.vue'
import AlignmentLine from './AlignmentLine.vue'
import Ruler from './Ruler.vue'
import ElementCreateSelection from './ElementCreateSelection.vue'
import MultiSelectOperate from './Operate/MultiSelectOperate.vue'
import Operate from './Operate/index.vue'
@ -133,6 +136,7 @@ export default defineComponent({
MouseSelection,
ViewportBackground,
AlignmentLine,
Ruler,
ElementCreateSelection,
MultiSelectOperate,
Operate,
@ -146,6 +150,7 @@ export default defineComponent({
handleElementId,
editorAreaFocus,
showGridLines,
showRuler,
creatingElement,
canvasScale,
} = storeToRefs(mainStore)
@ -228,6 +233,11 @@ export default defineComponent({
mainStore.setGridLinesState(!showGridLines.value)
}
//
const toggleRuler = () => {
mainStore.setRulerState(!showRuler.value)
}
//
const { insertElementFromCreateSelection } = useInsertFromCreateSelection(viewportRef)
@ -248,6 +258,11 @@ export default defineComponent({
subText: showGridLines.value ? '√' : '',
handler: toggleGridLines,
},
{
text: '标尺',
subText: showRuler.value ? '√' : '',
handler: toggleRuler,
},
{
text: '重置当前页',
handler: deleteAllElements,
@ -279,6 +294,7 @@ export default defineComponent({
alignmentLines,
linkDialogVisible,
spaceKeyState,
showRuler,
openLinkDialog,
handleClickBlankArea,
removeEditorAreaFocus,

View File

@ -20,6 +20,7 @@
<MenuItem @click="createSlide()">添加页面</MenuItem>
<MenuItem @click="deleteSlide()">删除页面</MenuItem>
<MenuItem @click="toggleGridLines()">{{ showGridLines ? '关闭网格线' : '打开网格线' }}</MenuItem>
<MenuItem @click="toggleRuler()">{{ toggleRuler ? '关闭标尺' : '打开标尺' }}</MenuItem>
<MenuItem @click="resetSlides()">重置幻灯片</MenuItem>
</Menu>
</template>
@ -99,7 +100,7 @@ export default defineComponent({
},
setup() {
const mainStore = useMainStore()
const { showGridLines } = storeToRefs(mainStore)
const { showGridLines, showRuler } = storeToRefs(mainStore)
const { enterScreening, enterScreeningFromStart } = useScreening()
const { createSlide, deleteSlide, resetSlides } = useSlideHandler()
@ -110,6 +111,10 @@ export default defineComponent({
mainStore.setGridLinesState(!showGridLines.value)
}
const toggleRuler = () => {
mainStore.setRulerState(!showRuler.value)
}
const hotkeyDrawerVisible = ref(false)
const exportImgDialogVisible = ref(false)
@ -129,6 +134,7 @@ export default defineComponent({
createSlide,
deleteSlide,
toggleGridLines,
toggleRuler,
resetSlides,
exportJSON,
exportPPTX,