This commit is contained in:
pipipi-pikachu 2020-12-13 18:03:50 +08:00
parent f37c7d7a62
commit 5b333c4dab
9 changed files with 195 additions and 44 deletions

View File

@ -2,6 +2,22 @@
<router-view/>
</template>
<script>
import { defineComponent, onMounted } from 'vue'
import { useStore } from 'vuex'
import { MutationTypes } from '@/store/constants'
export default defineComponent({
name: 'app',
setup() {
const store = useStore()
onMounted(() => {
store.commit(MutationTypes.SET_AVAILABLE_FONTS)
})
},
})
</script>
<style lang="scss">
#app {
height: 100%;

View File

@ -19,24 +19,24 @@ export const ELEMENT_TYPE_TABS = {
table: { key: 'element-table', label: '表格属性' },
}
export const ELEMENTS = {
text: '文本',
image: '图片',
shape: '形状',
icon: '图标',
line: '线条',
chart: '图表',
iframe: 'Iframe',
table: '表格',
export enum ELEMENTS {
text = '文本',
image = '图片',
shape = '形状',
icon = '图标',
line = '线条',
chart = '图表',
iframe = 'Iframe',
table = '表格',
}
export const OPERATE_KEYS = {
LEFT_TOP: 1,
TOP: 2,
RIGHT_TOP: 3,
LEFT: 4,
RIGHT: 5,
LEFT_BOTTOM: 6,
BOTTOM: 7,
RIGHT_BOTTOM: 8,
export enum OPERATE_KEYS {
LEFT_TOP = 1,
TOP = 2,
RIGHT_TOP = 3,
LEFT = 4,
RIGHT = 5,
LEFT_BOTTOM = 6,
BOTTOM = 7,
RIGHT_BOTTOM = 8,
}

View File

@ -1,4 +1,10 @@
export const FONT_FAMILYS = [
export interface FontName {
source: string;
zh: string;
en: string;
}
export const FONT_NAMES = [
{ source: 'windows', zh: '微软雅黑', en: 'Microsoft Yahei' },
{ source: 'windows', zh: '宋体', en: 'SimSun' },
{ source: 'windows', zh: '黑体', en: 'SimHei' },

View File

@ -1,18 +1,18 @@
export const KEYCODE = {
S: 83,
C: 67,
X: 88,
Z: 90,
Y: 89,
A: 65,
G: 71,
L: 76,
DELETE: 46,
UP: 38,
DOWN: 40,
LEFT: 37,
RIGHT: 39,
ENTER: 13,
SPACE: 32,
TAB: 9,
export enum KEYCODE {
S = 83,
C = 67,
X = 88,
Z = 90,
Y = 89,
A = 65,
G = 71,
L = 76,
DELETE = 46,
UP = 38,
DOWN = 40,
LEFT = 37,
RIGHT = 39,
ENTER = 13,
SPACE = 32,
TAB = 9,
}

View File

@ -1,6 +1,8 @@
import { MutationTypes } from './constants'
import { State, SaveState } from './state'
import { Slide, PPTElement } from '@/types/slides'
import { FONT_NAMES } from '@/configs/fontName'
import { isSupportFontFamily } from '@/utils/index'
interface AddSlidesData {
index?: number;
@ -33,7 +35,7 @@ export type Mutations = {
[MutationTypes.TOGGLE_SHOW_GRID_LINES](state: State): void;
[MutationTypes.SET_THUMBNAILS_FOCUS](state: State, isFocus: boolean): void;
[MutationTypes.SET_EDITORAREA_FOCUS](state: State, isFocus: boolean): void;
[MutationTypes.SET_AVAILABLE_FONTS](state: State, fonts: string[]): void;
[MutationTypes.SET_AVAILABLE_FONTS](state: State): void;
[MutationTypes.SET_SAVE_STATE](state: State, saveState: SaveState ): void;
[MutationTypes.SET_SLIDES](state: State, slides: Slide[]): void;
[MutationTypes.ADD_SLIDES](state: State, data: AddSlidesData): void;
@ -44,6 +46,10 @@ export type Mutations = {
[MutationTypes.UPDATE_SLIDE_INDEX](state: State, index: number): void;
[MutationTypes.ADD_ELEMENTS](state: State, elements: PPTElement[]): void;
[MutationTypes.UPDATE_ELEMENT](state: State, data: UpdateElementData): void;
[MutationTypes.SET_CURSOR](state: State, cursor: number): void;
[MutationTypes.UNDO](state: State): void;
[MutationTypes.REDO](state: State): void;
[MutationTypes.SET_HISTORY_RECORD_LENGTH](state: State, length: number): void;
}
export const mutations: Mutations = {
@ -81,8 +87,8 @@ export const mutations: Mutations = {
state.editorAreaFocus = isFocus
},
[MutationTypes.SET_AVAILABLE_FONTS](state, fonts) {
state.availableFonts = fonts
[MutationTypes.SET_AVAILABLE_FONTS](state) {
state.availableFonts = FONT_NAMES.filter(font => isSupportFontFamily(font.en))
},
[MutationTypes.SET_SAVE_STATE](state, saveState) {
@ -146,4 +152,22 @@ export const mutations: Mutations = {
})
state.slides[slideIndex].elements = (elements as PPTElement[])
},
// history
[MutationTypes.SET_CURSOR](state, cursor) {
state.cursor = cursor
},
[MutationTypes.UNDO](state) {
state.cursor -= 1
},
[MutationTypes.REDO](state) {
state.cursor += 1
},
[MutationTypes.SET_HISTORY_RECORD_LENGTH](state, length) {
state.historyRecordLength = length
},
}

View File

@ -1,5 +1,6 @@
import { Slide } from '@/types/slides'
import { slides } from '@/mocks/index'
import { FontName } from '@/configs/fontName'
export type SaveState = 'complete' | 'pending'
@ -11,7 +12,7 @@ export type State = {
canvasScale: number;
thumbnailsFocus: boolean;
editorAreaFocus: boolean;
availableFonts: string[];
availableFonts: FontName[];
saveState: SaveState;
slides: Slide[];
slideIndex: number;

View File

@ -10,7 +10,7 @@ export const createRandomNumber = (min: number, max: number) => {
}
// 生成随机码
export const createRandomCode = (len: number = 6) => {
export const createRandomCode = (len = 6) => {
const charset = `_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`
const maxLen = charset.length
let ret = ''
@ -30,7 +30,7 @@ export const createUUID = () => {
}
// 获取当前日期字符串
export const getDateTime = (format: string = 'yyyy-MM-dd hh:mm:ss') => {
export const getDateTime = (format = 'yyyy-MM-dd hh:mm:ss') => {
const date = new Date()
const formatMap = {

View File

@ -4,6 +4,7 @@
ref="canvasRef"
@mousedown="$event => handleClickBlankArea($event)"
v-contextmenu="contextmenus"
v-click-outside="removeEditorAreaFocus"
>
<div
class="viewport"
@ -32,6 +33,7 @@
import { computed, defineComponent, onMounted, onUnmounted, reactive, ref } from 'vue'
import { useStore } from 'vuex'
import { State } from '@/store/state'
import { MutationTypes } from '@/store/constants'
import { ContextmenuItem } from '@/components/Contextmenu/types'
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
@ -149,8 +151,16 @@ export default defineComponent({
mouseSelectionState.isShow = false
}
}
const editorAreaFocus = computed(() => store.state.editorAreaFocus)
const handleClickBlankArea = (e: MouseEvent) => {
updateMouseSelection(e)
if(!editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true)
}
const removeEditorAreaFocus = () => {
if(editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, false)
}
const contextmenus = (): ContextmenuItem[] => {
@ -191,6 +201,7 @@ export default defineComponent({
viewportStyles,
mouseSelectionState,
handleClickBlankArea,
removeEditorAreaFocus,
contextmenus,
}
},

View File

@ -13,7 +13,12 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { computed, defineComponent, onMounted, onUnmounted, ref } from 'vue'
import { useStore } from 'vuex'
import { State } from '@/store/state'
import { KEYCODE } from '@/configs/keyCode'
import { message } from 'ant-design-vue'
import EditorHeader from './EditorHeader/index.vue'
import Canvas from './Canvas/index.vue'
@ -30,6 +35,94 @@ export default defineComponent({
Thumbnails,
Toolbar,
},
setup() {
const ctrlKeyDown = ref(false)
const shiftKeyDown = ref(false)
const store = useStore<State>()
const editorAreaFocus = computed(() => store.state.editorAreaFocus)
const thumbnailsFocus = computed(() => store.state.thumbnailsFocus)
const save = () => {
message.success('save')
}
const copy = () => {
message.success('copy')
}
const cut = () => {
message.success('cut')
}
const undo = () => {
message.success('undo')
}
const redo = () => {
message.success('redo')
}
const selectAll = () => {
message.success('selectAll')
}
const lock = () => {
message.success('lock')
}
const combine = () => {
message.success('combine')
}
const uncombine = () => {
message.success('uncombine')
}
const remove = () => {
message.success('remove')
}
const move = (key: number) => {
message.success(`move: ${key}`)
}
const create = () => {
message.success('create')
}
const keydownListener = (e: KeyboardEvent) => {
const { keyCode, ctrlKey, shiftKey } = e
if(ctrlKey && !ctrlKeyDown.value) ctrlKeyDown.value = true
if(shiftKey && !shiftKeyDown.value) shiftKeyDown.value = true
if(!editorAreaFocus.value && !thumbnailsFocus.value) return
e.preventDefault()
if(ctrlKey && keyCode === KEYCODE.S) save()
if(ctrlKey && keyCode === KEYCODE.C) copy()
if(ctrlKey && keyCode === KEYCODE.X) cut()
if(ctrlKey && keyCode === KEYCODE.Z) undo()
if(ctrlKey && keyCode === KEYCODE.Y) redo()
if(ctrlKey && keyCode === KEYCODE.A) selectAll()
if(ctrlKey && keyCode === KEYCODE.L) lock()
if(!shiftKey && ctrlKey && keyCode === KEYCODE.G) combine()
if(shiftKey && ctrlKey && keyCode === KEYCODE.G) uncombine()
if(keyCode === KEYCODE.DELETE) remove()
if(keyCode === KEYCODE.UP) move(KEYCODE.UP)
if(keyCode === KEYCODE.DOWN) move(KEYCODE.DOWN)
if(keyCode === KEYCODE.LEFT) move(KEYCODE.LEFT)
if(keyCode === KEYCODE.RIGHT) move(KEYCODE.RIGHT)
if(keyCode === KEYCODE.ENTER) create()
}
const keyupListener = () => {
if(ctrlKeyDown.value) ctrlKeyDown.value = false
if(shiftKeyDown.value) shiftKeyDown.value = false
}
onMounted(() => {
document.addEventListener('keydown', keydownListener)
document.addEventListener('keyup', keyupListener)
window.addEventListener('blur', keyupListener)
})
onUnmounted(() => {
document.removeEventListener('keydown', keydownListener)
document.removeEventListener('keyup', keyupListener)
window.removeEventListener('blur', keyupListener)
})
},
})
</script>