mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
update
This commit is contained in:
parent
845cecd553
commit
8ff1500b53
@ -18,7 +18,6 @@
|
||||
"mitt": "^2.1.0",
|
||||
"store2": "^2.12.0",
|
||||
"vue": "^3.0.0",
|
||||
"vue-router": "^4.0.0-0",
|
||||
"vuedraggable": "^4.0.1",
|
||||
"vuex": "^4.0.0-0"
|
||||
},
|
||||
@ -31,7 +30,6 @@
|
||||
"@typescript-eslint/parser": "^2.33.0",
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-plugin-router": "~4.5.0",
|
||||
"@vue/cli-plugin-typescript": "~4.5.0",
|
||||
"@vue/cli-plugin-unit-jest": "~4.5.0",
|
||||
"@vue/cli-plugin-vuex": "~4.5.0",
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<router-view/>
|
||||
<Editor />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@ -7,8 +7,13 @@ import { defineComponent, onMounted } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { MutationTypes, ActionTypes, State } from '@/store'
|
||||
|
||||
import Editor from './views/Editor/index.vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'app',
|
||||
components: {
|
||||
Editor,
|
||||
},
|
||||
setup() {
|
||||
const store = useStore<State>()
|
||||
|
||||
|
23
src/hooks/useScaleCanvas.ts
Normal file
23
src/hooks/useScaleCanvas.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { MutationTypes, State } from '@/store'
|
||||
|
||||
export default () => {
|
||||
const store = useStore<State>()
|
||||
const canvasPercentage = computed(() => store.state.canvasPercentage)
|
||||
|
||||
const scaleCanvas = (command: '+' | '-') => {
|
||||
let percentage = canvasPercentage.value
|
||||
const step = 5
|
||||
const max = 120
|
||||
const min = 60
|
||||
if(command === '+' && percentage <= max) percentage += step
|
||||
if(command === '-' && percentage >= min) percentage -= step
|
||||
|
||||
store.commit(MutationTypes.SET_CANVAS_PERCENTAGE, percentage)
|
||||
}
|
||||
|
||||
return {
|
||||
scaleCanvas,
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
|
||||
import '@/assets/styles/global.scss'
|
||||
@ -14,5 +13,4 @@ app.component('IconFont', IconFont)
|
||||
app.use(contextmenu)
|
||||
app.use(clickOutside)
|
||||
app.use(store)
|
||||
app.use(router)
|
||||
app.mount('#app')
|
||||
|
@ -1,28 +0,0 @@
|
||||
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
|
||||
import Editor from '@/views/Editor/index.vue'
|
||||
|
||||
const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Editor',
|
||||
component: Editor,
|
||||
},
|
||||
{
|
||||
path: '/player',
|
||||
name: 'Player',
|
||||
component: () => import(/* webpackChunkName: "Player" */ '@/views/Player/index.vue'),
|
||||
},
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(process.env.BASE_URL),
|
||||
routes,
|
||||
})
|
||||
|
||||
router.beforeEach((to, from) => {
|
||||
if(to.name === 'Player' && from.name !== 'Editor') {
|
||||
return router.push({ path: '/' })
|
||||
}
|
||||
})
|
||||
|
||||
export default router
|
@ -3,10 +3,12 @@ export enum MutationTypes {
|
||||
// editor
|
||||
SET_ACTIVE_ELEMENT_ID_LIST = 'setActiveElementIdList',
|
||||
SET_HANDLE_ELEMENT_ID = 'setHandleElementId',
|
||||
SET_EDITOR_AREA_SHOW_SCALE = 'setEditorAreaShowScale',
|
||||
SET_CANVAS_PERCENTAGE = 'setCanvasPercentage',
|
||||
SET_CANVAS_SCALE = 'setCanvasScale',
|
||||
SET_THUMBNAILS_FOCUS = 'setThumbnailsFocus',
|
||||
SET_EDITORAREA_FOCUS = 'setEditorAreaFocus',
|
||||
SET_DISABLE_HOTKEYS_STATE = 'setDisableHotkeysState',
|
||||
SET_GRID_LINES_STATE = 'setGridLinesState',
|
||||
SET_AVAILABLE_FONTS = 'setAvailableFonts',
|
||||
|
||||
// slides
|
||||
|
@ -13,10 +13,12 @@ export { MutationTypes, ActionTypes }
|
||||
export interface State {
|
||||
activeElementIdList: string[];
|
||||
handleElementId: string;
|
||||
editorAreaShowScale: number;
|
||||
canvasPercentage: number;
|
||||
canvasScale: number;
|
||||
thumbnailsFocus: boolean;
|
||||
editorAreaFocus: boolean;
|
||||
disableHotkeys: boolean;
|
||||
showGridLines: boolean;
|
||||
availableFonts: FontName[];
|
||||
slides: Slide[];
|
||||
slideIndex: number;
|
||||
@ -29,10 +31,12 @@ export interface State {
|
||||
const state: State = {
|
||||
activeElementIdList: [],
|
||||
handleElementId: '',
|
||||
editorAreaShowScale: 90,
|
||||
canvasPercentage: 90,
|
||||
canvasScale: 1,
|
||||
thumbnailsFocus: false,
|
||||
editorAreaFocus: false,
|
||||
disableHotkeys: false,
|
||||
showGridLines: false,
|
||||
availableFonts: [],
|
||||
slides: slides,
|
||||
slideIndex: 0,
|
||||
|
@ -5,11 +5,6 @@ import { Slide, PPTElement } from '@/types/slides'
|
||||
import { FONT_NAMES } from '@/configs/fontName'
|
||||
import { isSupportFontFamily } from '@/utils/fontFamily'
|
||||
|
||||
interface AddSlideData {
|
||||
index?: number;
|
||||
slide: Slide | Slide[];
|
||||
}
|
||||
|
||||
interface UpdateElementData {
|
||||
elId: string | string[];
|
||||
props: Partial<PPTElement>;
|
||||
@ -30,8 +25,12 @@ export const mutations: MutationTree<State> = {
|
||||
state.handleElementId = handleElementId
|
||||
},
|
||||
|
||||
[MutationTypes.SET_EDITOR_AREA_SHOW_SCALE](state, scale: number) {
|
||||
state.editorAreaShowScale = scale
|
||||
[MutationTypes.SET_CANVAS_PERCENTAGE](state, percentage: number) {
|
||||
state.canvasPercentage = percentage
|
||||
},
|
||||
|
||||
[MutationTypes.SET_CANVAS_SCALE](state, scale: number) {
|
||||
state.canvasScale = scale
|
||||
},
|
||||
|
||||
[MutationTypes.SET_THUMBNAILS_FOCUS](state, isFocus: boolean) {
|
||||
@ -46,6 +45,10 @@ export const mutations: MutationTree<State> = {
|
||||
state.disableHotkeys = disable
|
||||
},
|
||||
|
||||
[MutationTypes.SET_GRID_LINES_STATE](state, show: boolean) {
|
||||
state.showGridLines = show
|
||||
},
|
||||
|
||||
[MutationTypes.SET_AVAILABLE_FONTS](state) {
|
||||
state.availableFonts = FONT_NAMES.filter(font => isSupportFontFamily(font.en))
|
||||
},
|
||||
|
@ -39,10 +39,6 @@ export default defineComponent({
|
||||
BorderLine,
|
||||
},
|
||||
props: {
|
||||
canvasScale: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
elementList: {
|
||||
type: Array as PropType<PPTElement[]>,
|
||||
required: true,
|
||||
@ -55,6 +51,7 @@ export default defineComponent({
|
||||
setup(props) {
|
||||
const store = useStore<State>()
|
||||
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||
const canvasScale = computed(() => store.state.canvasScale)
|
||||
const localActiveElementList = computed(() => props.elementList.filter(el => activeElementIdList.value.includes(el.elId)))
|
||||
|
||||
const range = reactive({
|
||||
@ -64,8 +61,8 @@ export default defineComponent({
|
||||
maxY: 0,
|
||||
})
|
||||
|
||||
const width = computed(() => (range.maxX - range.minX) * props.canvasScale)
|
||||
const height = computed(() => (range.maxY - range.minY) * props.canvasScale)
|
||||
const width = computed(() => (range.maxX - range.minX) * canvasScale.value)
|
||||
const height = computed(() => (range.maxY - range.minY) * canvasScale.value)
|
||||
|
||||
const resizablePoints = computed(() => {
|
||||
return [
|
||||
|
@ -3,36 +3,34 @@
|
||||
class="slide-background"
|
||||
:style="backgroundStyle"
|
||||
>
|
||||
<template v-if="isShowGridLines">
|
||||
<template v-if="showGridLines">
|
||||
<GridLines />
|
||||
<GridLines :gridSize="100" gridColor="rgba(100, 100, 100, 0.3)" />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import GridLines from './GridLines'
|
||||
<script lang="ts">
|
||||
import { Ref, computed, defineComponent } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { State } from '@/store'
|
||||
import { Slide } from '@/types/slides'
|
||||
import GridLines from './GridLines.vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'slide-background',
|
||||
components: {
|
||||
GridLines,
|
||||
},
|
||||
props: {
|
||||
background: {
|
||||
type: Array,
|
||||
},
|
||||
isShowGridLines: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const backgroundStyle = computed(() => {
|
||||
if(!props.background) return { backgroundColor: '#fff' }
|
||||
setup() {
|
||||
const store = useStore<State>()
|
||||
const showGridLines = computed(() => store.state.showGridLines)
|
||||
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||
|
||||
const [type, value] = props.background
|
||||
const backgroundStyle = computed(() => {
|
||||
if(!currentSlide.value.background) return { backgroundColor: '#fff' }
|
||||
|
||||
const [type, value] = currentSlide.value.background
|
||||
if(type === 'solid') return { backgroundColor: value }
|
||||
else if(type === 'image') return { backgroundImage: `url(${value}` }
|
||||
|
||||
@ -40,6 +38,7 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
return {
|
||||
showGridLines,
|
||||
backgroundStyle,
|
||||
}
|
||||
},
|
||||
|
@ -9,11 +9,11 @@ import { getRectRotatedRange, AlignLine, uniqAlignLines } from '@/utils/element'
|
||||
export default (
|
||||
elementList: Ref<PPTElement[]>,
|
||||
activeGroupElementId: Ref<string>,
|
||||
canvasScale: Ref<number>,
|
||||
alignmentLines: Ref<AlignmentLineProps[]>,
|
||||
) => {
|
||||
const store = useStore<State>()
|
||||
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||
const canvasScale = computed(() => store.state.canvasScale)
|
||||
|
||||
const dragElement = (e: MouseEvent, element: PPTElement) => {
|
||||
if(!activeElementIdList.value.includes(element.elId)) return
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { Ref, reactive } from 'vue'
|
||||
import { Ref, reactive, computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { State, MutationTypes } from '@/store'
|
||||
import { PPTElement } from '@/types/slides'
|
||||
import { getElementRange } from '@/utils/element'
|
||||
|
||||
export default (elementList: Ref<PPTElement[]>, viewportRef: Ref<HTMLElement | null>, canvasScale: Ref<number>) => {
|
||||
export default (elementList: Ref<PPTElement[]>, viewportRef: Ref<HTMLElement | null>) => {
|
||||
const store = useStore<State>()
|
||||
const canvasScale = computed(() => store.state.canvasScale)
|
||||
|
||||
const mouseSelectionState = reactive({
|
||||
isShow: false,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Ref } from 'vue'
|
||||
import { Ref, computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { State, MutationTypes } from '@/store'
|
||||
import { PPTElement, PPTTextElement, PPTImageElement, PPTShapeElement } from '@/types/slides'
|
||||
@ -12,8 +12,9 @@ export const getAngleFromCoordinate = (x: number, y: number) => {
|
||||
return angle
|
||||
}
|
||||
|
||||
export default (elementList: Ref<PPTElement[]>, viewportRef: Ref<HTMLElement | null>, canvasScale: Ref<number>) => {
|
||||
export default (elementList: Ref<PPTElement[]>, viewportRef: Ref<HTMLElement | null>) => {
|
||||
const store = useStore<State>()
|
||||
const canvasScale = computed(() => store.state.canvasScale)
|
||||
|
||||
const rotateElement = (element: PPTTextElement | PPTImageElement | PPTShapeElement) => {
|
||||
let isMouseDown = true
|
||||
|
@ -83,13 +83,13 @@ export const getOppositePoint = (direction: number, points: ReturnType<typeof ge
|
||||
|
||||
export default (
|
||||
elementList: Ref<PPTElement[]>,
|
||||
canvasScale: Ref<number>,
|
||||
activeGroupElementId: Ref<string>,
|
||||
alignmentLines: Ref<AlignmentLineProps[]>,
|
||||
) => {
|
||||
const store = useStore<State>()
|
||||
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||
const ctrlOrShiftKeyActive: Ref<boolean> = computed(() => store.getters.ctrlOrShiftKeyActive)
|
||||
const canvasScale = computed(() => store.state.canvasScale)
|
||||
|
||||
const scaleElement = (e: MouseEvent, element: Exclude<PPTElement, PPTLineElement>, command: ElementScaleHandler) => {
|
||||
let isMouseDown = true
|
||||
|
@ -1,15 +1,14 @@
|
||||
import { ref, computed, onMounted, onUnmounted, Ref } from 'vue'
|
||||
import { ref, computed, onMounted, onUnmounted, Ref, watch } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { State } from '@/store'
|
||||
import { State, MutationTypes } from '@/store'
|
||||
import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas'
|
||||
|
||||
export default (canvasRef: Ref<HTMLElement | null>) => {
|
||||
const canvasScale = ref(1)
|
||||
const viewportLeft = ref(0)
|
||||
const viewportTop = ref(0)
|
||||
|
||||
const store = useStore<State>()
|
||||
const editorAreaShowScale = computed(() => store.state.editorAreaShowScale)
|
||||
const canvasPercentage = computed(() => store.state.canvasPercentage)
|
||||
|
||||
const setViewportSize = () => {
|
||||
if(!canvasRef.value) return
|
||||
@ -17,19 +16,21 @@ export default (canvasRef: Ref<HTMLElement | null>) => {
|
||||
const canvasHeight = canvasRef.value.clientHeight
|
||||
|
||||
if(canvasHeight / canvasWidth > VIEWPORT_ASPECT_RATIO) {
|
||||
const viewportActualWidth = canvasWidth * (editorAreaShowScale.value / 100)
|
||||
canvasScale.value = viewportActualWidth / VIEWPORT_SIZE
|
||||
const viewportActualWidth = canvasWidth * (canvasPercentage.value / 100)
|
||||
store.commit(MutationTypes.SET_CANVAS_SCALE, viewportActualWidth / VIEWPORT_SIZE)
|
||||
viewportLeft.value = (canvasWidth - viewportActualWidth) / 2
|
||||
viewportTop.value = (canvasHeight - viewportActualWidth * VIEWPORT_ASPECT_RATIO) / 2
|
||||
}
|
||||
else {
|
||||
const viewportActualHeight = canvasHeight * (editorAreaShowScale.value / 100)
|
||||
canvasScale.value = viewportActualHeight / (VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO)
|
||||
const viewportActualHeight = canvasHeight * (canvasPercentage.value / 100)
|
||||
store.commit(MutationTypes.SET_CANVAS_SCALE, viewportActualHeight / (VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO))
|
||||
viewportLeft.value = (canvasWidth - viewportActualHeight / VIEWPORT_ASPECT_RATIO) / 2
|
||||
viewportTop.value = (canvasHeight - viewportActualHeight) / 2
|
||||
}
|
||||
}
|
||||
|
||||
watch(canvasPercentage, setViewportSize)
|
||||
|
||||
const viewportStyles = computed(() => ({
|
||||
width: VIEWPORT_SIZE,
|
||||
height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO,
|
||||
@ -47,7 +48,6 @@ export default (canvasRef: Ref<HTMLElement | null>) => {
|
||||
})
|
||||
|
||||
return {
|
||||
canvasScale,
|
||||
viewportStyles,
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
<div
|
||||
class="canvas"
|
||||
ref="canvasRef"
|
||||
@mousewheel="$event => mousewheelScaleCanvas($event)"
|
||||
@mousedown="$event => handleClickBlankArea($event)"
|
||||
v-contextmenu="contextmenus"
|
||||
v-click-outside="removeEditorAreaFocus"
|
||||
@ -26,11 +27,6 @@
|
||||
:quadrant="mouseSelectionState.quadrant"
|
||||
/>
|
||||
|
||||
<SlideBackground
|
||||
:background="currentSlide?.background"
|
||||
:isShowGridLines="isShowGridLines"
|
||||
/>
|
||||
|
||||
<AlignmentLine
|
||||
v-for="(line, index) in alignmentLines" :key="index"
|
||||
:type="line.type" :axis="line.axis" :length="line.length"
|
||||
@ -40,13 +36,13 @@
|
||||
v-if="activeElementIdList.length > 1"
|
||||
:elementList="elementList"
|
||||
:scaleMultiElement="scaleMultiElement"
|
||||
:canvasScale="canvasScale"
|
||||
/>
|
||||
|
||||
<SlideBackground />
|
||||
|
||||
<EditableElement
|
||||
v-for="(element, index) in elementList"
|
||||
:key="element.elId"
|
||||
:canvasScale="canvasScale"
|
||||
:elementInfo="element"
|
||||
:elementIndex="index + 1"
|
||||
:isActive="activeElementIdList.includes(element.elId)"
|
||||
@ -64,6 +60,7 @@
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, Ref, ref, watch, watchEffect } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import throttle from 'lodash/throttle'
|
||||
import { State, MutationTypes } from '@/store'
|
||||
import { ContextmenuItem } from '@/components/Contextmenu/types'
|
||||
import { PPTElement, Slide } from '@/types/slides'
|
||||
@ -80,6 +77,7 @@ import useDragElement from './hooks/useDragElement'
|
||||
import useDeleteElement from '@/hooks/useDeleteElement'
|
||||
import useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'
|
||||
import useSelectAllElement from '@/hooks/useSelectAllElement'
|
||||
import useScaleCanvas from '@/hooks/useScaleCanvas'
|
||||
|
||||
import EditableElement from '@/views/_common/_element/EditableElement.vue'
|
||||
import MouseSelection from './MouseSelection.vue'
|
||||
@ -102,6 +100,7 @@ export default defineComponent({
|
||||
const activeElementIdList = computed(() => store.state.activeElementIdList)
|
||||
const handleElementId = computed(() => store.state.handleElementId)
|
||||
const editorAreaFocus = computed(() => store.state.editorAreaFocus)
|
||||
const ctrlKeyState = computed(() => store.state.ctrlKeyState)
|
||||
const ctrlOrShiftKeyActive: Ref<boolean> = computed(() => store.getters.ctrlOrShiftKeyActive)
|
||||
|
||||
const viewportRef = ref<HTMLElement | null>(null)
|
||||
@ -121,14 +120,15 @@ export default defineComponent({
|
||||
useDropImageElement(viewportRef)
|
||||
|
||||
const canvasRef = ref<HTMLElement | null>(null)
|
||||
const { canvasScale, viewportStyles } = useViewportSize(canvasRef)
|
||||
const canvasScale = computed(() => store.state.canvasScale)
|
||||
const { viewportStyles } = useViewportSize(canvasRef)
|
||||
|
||||
const { mouseSelectionState, updateMouseSelection } = useMouseSelection(elementList, viewportRef, canvasScale)
|
||||
const { mouseSelectionState, updateMouseSelection } = useMouseSelection(elementList, viewportRef)
|
||||
|
||||
const { dragElement } = useDragElement(elementList, activeGroupElementId, canvasScale, alignmentLines)
|
||||
const { dragElement } = useDragElement(elementList, activeGroupElementId, alignmentLines)
|
||||
const { selectElement } = useSelectElement(elementList, activeGroupElementId, dragElement)
|
||||
const { scaleElement, scaleMultiElement } = useScaleElement(elementList, canvasScale, activeGroupElementId, alignmentLines)
|
||||
const { rotateElement } = useRotateElement(elementList, viewportRef, canvasScale)
|
||||
const { scaleElement, scaleMultiElement } = useScaleElement(elementList, activeGroupElementId, alignmentLines)
|
||||
const { rotateElement } = useRotateElement(elementList, viewportRef)
|
||||
|
||||
const { selectAllElement } = useSelectAllElement()
|
||||
const { deleteAllElements } = useDeleteElement()
|
||||
@ -144,6 +144,17 @@ export default defineComponent({
|
||||
if(editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, false)
|
||||
}
|
||||
|
||||
const { scaleCanvas } = useScaleCanvas()
|
||||
const throttleScaleCanvas = throttle(scaleCanvas, 100, { leading: true, trailing: false })
|
||||
|
||||
const mousewheelScaleCanvas = (e: WheelEvent) => {
|
||||
if(!ctrlKeyState.value) return
|
||||
|
||||
e.preventDefault()
|
||||
if(e.deltaY > 0) throttleScaleCanvas('-')
|
||||
else if(e.deltaY < 0) throttleScaleCanvas('+')
|
||||
}
|
||||
|
||||
const contextmenus = (): ContextmenuItem[] => {
|
||||
return [
|
||||
{
|
||||
@ -182,6 +193,7 @@ export default defineComponent({
|
||||
rotateElement,
|
||||
scaleElement,
|
||||
scaleMultiElement,
|
||||
mousewheelScaleCanvas,
|
||||
contextmenus,
|
||||
}
|
||||
},
|
||||
|
@ -15,19 +15,41 @@
|
||||
</div>
|
||||
|
||||
<div class="right-handler">
|
||||
<IconFont class="handler-item viewport-size" type="icon-minus" />
|
||||
<span class="text">100%</span>
|
||||
<IconFont class="handler-item viewport-size" type="icon-plus" />
|
||||
<IconFont class="handler-item viewport-size" type="icon-number" />
|
||||
<IconFont class="handler-item viewport-size" type="icon-minus" @click="scaleCanvas('-')" />
|
||||
<span class="text">{{canvasScalePercentage}}</span>
|
||||
<IconFont class="handler-item viewport-size" type="icon-plus" @click="scaleCanvas('+')" />
|
||||
<IconFont class="handler-item viewport-size" type="icon-number" @click="toggleGridLines()" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import { defineComponent, computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { MutationTypes, State } from '@/store'
|
||||
import useScaleCanvas from '@/hooks/useScaleCanvas'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'canvas-tool',
|
||||
setup() {
|
||||
const store = useStore<State>()
|
||||
const canvasScale = computed(() => store.state.canvasScale)
|
||||
const showGridLines = computed(() => store.state.showGridLines)
|
||||
|
||||
const canvasScalePercentage = computed(() => parseInt(canvasScale.value * 100 + '') + '%')
|
||||
|
||||
const { scaleCanvas } = useScaleCanvas()
|
||||
|
||||
const toggleGridLines = () => {
|
||||
store.commit(MutationTypes.SET_GRID_LINES_STATE, !showGridLines.value)
|
||||
}
|
||||
|
||||
return {
|
||||
scaleCanvas,
|
||||
canvasScalePercentage,
|
||||
toggleGridLines,
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -40,6 +62,7 @@ export default defineComponent({
|
||||
justify-content: space-between;
|
||||
padding: 0 10px;
|
||||
font-size: 13px;
|
||||
user-select: none;
|
||||
}
|
||||
.left-handler {
|
||||
display: flex;
|
||||
@ -59,6 +82,11 @@ export default defineComponent({
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.text {
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.viewport-size {
|
||||
font-size: 12px;
|
||||
margin-top: -1px;
|
||||
|
@ -5,7 +5,7 @@
|
||||
v-click-outside="() => setThumbnailsFocus(false)"
|
||||
>
|
||||
<div class="add-slide">
|
||||
<span>+ 添加幻灯片</span>
|
||||
<span @click="createSlide()">+ 添加幻灯片</span>
|
||||
</div>
|
||||
<draggable
|
||||
class="thumbnail-list"
|
||||
@ -130,6 +130,7 @@ export default defineComponent({
|
||||
setThumbnailsFocus,
|
||||
slides,
|
||||
slideIndex,
|
||||
createSlide,
|
||||
changSlideIndex,
|
||||
contextmenus,
|
||||
fillDigit,
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, PropType } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { State } from '@/store'
|
||||
import { PPTElement, PPTTextElement, PPTImageElement, PPTShapeElement, PPTLineElement } from '@/types/slides'
|
||||
import { ContextmenuItem } from '@/components/Contextmenu/types'
|
||||
|
||||
@ -42,10 +44,6 @@ import TextElement from './TextElement/index.vue'
|
||||
export default defineComponent({
|
||||
name: 'editable-element',
|
||||
props: {
|
||||
canvasScale: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
elementInfo: {
|
||||
type: Object as PropType<PPTElement>,
|
||||
required: true,
|
||||
@ -88,6 +86,9 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const store = useStore<State>()
|
||||
const canvasScale = computed(() => store.state.canvasScale)
|
||||
|
||||
const currentElementComponent = computed(() => {
|
||||
const elementTypeMap = {
|
||||
'image': ImageElement,
|
||||
@ -180,6 +181,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
return {
|
||||
canvasScale,
|
||||
currentElementComponent,
|
||||
contextmenus,
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user