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
395df00bd2
commit
045f361e14
@ -17,6 +17,9 @@
|
|||||||
.ant-radio-group {
|
.ant-radio-group {
|
||||||
font-size: 13px !important;
|
font-size: 13px !important;
|
||||||
}
|
}
|
||||||
|
.ant-select-selection-item {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
.ant-select-item-option-content {
|
.ant-select-item-option-content {
|
||||||
font-size: 13px !important;
|
font-size: 13px !important;
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,12 @@ export default (background: Ref<SlideBackground | undefined>) => {
|
|||||||
return {
|
return {
|
||||||
backgroundImage: `url(${value}`,
|
backgroundImage: `url(${value}`,
|
||||||
backgroundRepeat: 'repeat',
|
backgroundRepeat: 'repeat',
|
||||||
|
backgroundSize: 'initial',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
backgroundImage: `url(${value}`,
|
backgroundImage: `url(${value}`,
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
backgroundSize: size,
|
backgroundSize: size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ export interface PPTAnimation {
|
|||||||
export interface SlideBackground {
|
export interface SlideBackground {
|
||||||
type: 'solid' | 'image';
|
type: 'solid' | 'image';
|
||||||
value: string;
|
value: string;
|
||||||
size?: 'cover' | 'contain' | 'repeat';
|
size?: 'cover' | 'contain' | 'repeat' | 'initial';
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Slide {
|
export interface Slide {
|
||||||
|
@ -43,7 +43,6 @@ export default defineComponent({
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-size: cover;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,29 +1,45 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="canvas-tool">
|
<div class="canvas-tool">
|
||||||
<div class="left-handler">
|
<div class="left-handler">
|
||||||
<IconFont type="icon-undo" class="handler-item" :class="{ 'disable': !canUndo }" @click="undo()" />
|
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="撤销">
|
||||||
<IconFont type="icon-redo" class="handler-item" :class="{ 'disable': !canRedo }" @click="redo()" />
|
<IconFont type="icon-undo" class="handler-item" :class="{ 'disable': !canUndo }" @click="undo()" />
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="重做">
|
||||||
|
<IconFont type="icon-redo" class="handler-item" :class="{ 'disable': !canRedo }" @click="redo()" />
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="add-element-handler">
|
<div class="add-element-handler">
|
||||||
<IconFont type="icon-font-size" class="handler-item" @click="drawText()" />
|
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="插入文字">
|
||||||
|
<IconFont type="icon-font-size" class="handler-item" @click="drawText()" />
|
||||||
|
</Tooltip>
|
||||||
<FileInput @change="files => insertImageElement(files)">
|
<FileInput @change="files => insertImageElement(files)">
|
||||||
<IconFont type="icon-image" class="handler-item" />
|
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="插入图片">
|
||||||
|
<IconFont type="icon-image" class="handler-item" />
|
||||||
|
</Tooltip>
|
||||||
</FileInput>
|
</FileInput>
|
||||||
<Popover trigger="click" v-model:visible="isOpenShapePool">
|
<Popover trigger="click" v-model:visible="isOpenShapePool">
|
||||||
<template #content>
|
<template #content>
|
||||||
<ShapePool @select="shape => drawShape(shape)" />
|
<ShapePool @select="shape => drawShape(shape)" />
|
||||||
</template>
|
</template>
|
||||||
<IconFont type="icon-star" class="handler-item" />
|
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="插入形状">
|
||||||
|
<IconFont type="icon-star" class="handler-item" />
|
||||||
|
</Tooltip>
|
||||||
</Popover>
|
</Popover>
|
||||||
<Popover trigger="click" v-model:visible="isOpenLinePool">
|
<Popover trigger="click" v-model:visible="isOpenLinePool">
|
||||||
<template #content>
|
<template #content>
|
||||||
<LinePool @select="line => drawLine(line)" />
|
<LinePool @select="line => drawLine(line)" />
|
||||||
</template>
|
</template>
|
||||||
<IconFont type="icon-line" class="handler-item" />
|
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="插入线条">
|
||||||
|
<IconFont type="icon-line" class="handler-item" />
|
||||||
|
</Tooltip>
|
||||||
</Popover>
|
</Popover>
|
||||||
<IconFont type="icon-table" class="handler-item" />
|
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="插入表格">
|
||||||
<IconFont type="icon-piechart" class="handler-item" />
|
<IconFont type="icon-table" class="handler-item" />
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="插入图表">
|
||||||
|
<IconFont type="icon-piechart" class="handler-item" />
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="right-handler">
|
<div class="right-handler">
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
<div class="menu-item">文件</div>
|
<div class="menu-item">文件</div>
|
||||||
<div class="menu-item">编辑</div>
|
<div class="menu-item">编辑</div>
|
||||||
<div class="menu-item">设置</div>
|
<div class="menu-item">设置</div>
|
||||||
<div class="menu-item">素材</div>
|
|
||||||
<div class="menu-item">演示</div>
|
<div class="menu-item">演示</div>
|
||||||
<div class="menu-item">帮助</div>
|
<div class="menu-item">帮助</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,8 +26,8 @@
|
|||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<ButtonGroup class="row">
|
<ButtonGroup class="row">
|
||||||
<Button :disabled="!canCombine" @click="combineElements()" style="flex: 1;">组合</Button>
|
<Button :disabled="!canCombine" @click="combineElements()" style="flex: 1;"><IconFont type="icon-group" />组合</Button>
|
||||||
<Button :disabled="canCombine" @click="uncombineElements()" style="flex: 1;">取消组合</Button>
|
<Button :disabled="canCombine" @click="uncombineElements()" style="flex: 1;"><IconFont type="icon-ungroup" />取消组合</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,13 +1,178 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="slide-style-panel">
|
<div class="slide-style-panel">
|
||||||
<div>背景填充</div>
|
<div class="title">背景填充</div>
|
||||||
|
<div class="row">
|
||||||
|
<Select
|
||||||
|
style="flex: 10;"
|
||||||
|
:value="background.type"
|
||||||
|
@change="value => updateBackgroundType(value)"
|
||||||
|
>
|
||||||
|
<SelectOption value="solid">纯色填充</SelectOption>
|
||||||
|
<SelectOption value="image">图片填充</SelectOption>
|
||||||
|
</Select>
|
||||||
|
<div style="flex: 1;"></div>
|
||||||
|
<Popover trigger="click" v-if="background.type === 'solid'">
|
||||||
|
<template #content>
|
||||||
|
<ColorPicker
|
||||||
|
:modelValue="background.value"
|
||||||
|
@update:modelValue="value => updateBackground({ value })"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<ColorButton :color="background.value" style="flex: 10;" />
|
||||||
|
</Popover>
|
||||||
|
<Select
|
||||||
|
style="flex: 10;"
|
||||||
|
:value="background.size || 'cover'"
|
||||||
|
@change="value => updateBackground({ size: value })"
|
||||||
|
v-else
|
||||||
|
>
|
||||||
|
<SelectOption value="initial">原始大小</SelectOption>
|
||||||
|
<SelectOption value="contain">缩放</SelectOption>
|
||||||
|
<SelectOption value="repeat">拼贴</SelectOption>
|
||||||
|
<SelectOption value="cover">缩放铺满</SelectOption>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div class="background-image-wrapper" v-if="background.type === 'image'">
|
||||||
|
<FileInput @change="files => uploadBackgroundImage(files)">
|
||||||
|
<div class="background-image">
|
||||||
|
<div
|
||||||
|
class="content"
|
||||||
|
:style="backgroundStyle"
|
||||||
|
>
|
||||||
|
<IconFont type="icon-plus" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</FileInput>
|
||||||
|
</div>
|
||||||
|
<div class="row"><Button style="flex: 1;" @click="applyAllSlide()">应用到全部</Button></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue'
|
import { computed, defineComponent, Ref } from 'vue'
|
||||||
|
import { useStore } from 'vuex'
|
||||||
|
import { MutationTypes, State } from '@/store'
|
||||||
|
import { Slide, SlideBackground } from '@/types/slides'
|
||||||
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
|
import ColorButton from './common/ColorButton.vue'
|
||||||
|
import { getImageDataURL } from '@/utils/image'
|
||||||
|
import useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'slide-style-panel',
|
name: 'slide-style-panel',
|
||||||
|
components: {
|
||||||
|
ColorButton,
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const store = useStore<State>()
|
||||||
|
const slides = computed(() => store.state.slides)
|
||||||
|
const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
|
||||||
|
|
||||||
|
const background = computed(() => {
|
||||||
|
if(!currentSlide.value.background) {
|
||||||
|
return {
|
||||||
|
type: 'solid',
|
||||||
|
value: '#fff',
|
||||||
|
} as SlideBackground
|
||||||
|
}
|
||||||
|
return currentSlide.value.background
|
||||||
|
})
|
||||||
|
|
||||||
|
const { backgroundStyle } = useSlideBackgroundStyle(background)
|
||||||
|
|
||||||
|
const { addHistorySnapshot } = useHistorySnapshot()
|
||||||
|
|
||||||
|
const updateBackgroundType = (type: 'solid' | 'image') => {
|
||||||
|
if(type === 'solid') {
|
||||||
|
const background: SlideBackground = {
|
||||||
|
type: 'solid',
|
||||||
|
value: '#fff',
|
||||||
|
}
|
||||||
|
store.commit(MutationTypes.UPDATE_SLIDE, { background })
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const background: SlideBackground = {
|
||||||
|
type: 'image',
|
||||||
|
value: '',
|
||||||
|
size: 'cover',
|
||||||
|
}
|
||||||
|
store.commit(MutationTypes.UPDATE_SLIDE, { background })
|
||||||
|
}
|
||||||
|
addHistorySnapshot()
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateBackground = (props: Partial<SlideBackground>) => {
|
||||||
|
store.commit(MutationTypes.UPDATE_SLIDE, { background: { ...background.value, ...props } })
|
||||||
|
addHistorySnapshot()
|
||||||
|
}
|
||||||
|
|
||||||
|
const uploadBackgroundImage = (files: File[]) => {
|
||||||
|
const imageFile = files[0]
|
||||||
|
if(!imageFile) return
|
||||||
|
getImageDataURL(imageFile).then(dataURL => updateBackground({ value: dataURL }))
|
||||||
|
}
|
||||||
|
|
||||||
|
const applyAllSlide = () => {
|
||||||
|
const newSlides = slides.value.map(slide => {
|
||||||
|
return {
|
||||||
|
...slide,
|
||||||
|
background: currentSlide.value.background,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
store.commit(MutationTypes.SET_SLIDES, newSlides)
|
||||||
|
addHistorySnapshot()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
background,
|
||||||
|
backgroundStyle,
|
||||||
|
updateBackgroundType,
|
||||||
|
updateBackground,
|
||||||
|
uploadBackgroundImage,
|
||||||
|
applyAllSlide,
|
||||||
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.row {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.background-image-wrapper {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.background-image {
|
||||||
|
height: 0;
|
||||||
|
padding-bottom: 56.25%;
|
||||||
|
border: 1px dashed $borderColor;
|
||||||
|
border-radius: $borderRadius;
|
||||||
|
position: relative;
|
||||||
|
transition: all .2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: $themeColor;
|
||||||
|
color: $themeColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background-position: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
38
src/views/Editor/Toolbar/common/ColorButton.vue
Normal file
38
src/views/Editor/Toolbar/common/ColorButton.vue
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<template>
|
||||||
|
<Button class="color-btn">
|
||||||
|
<div class="color-block" :style="{ backgroundColor: color }"></div>
|
||||||
|
<IconFont type="icon-down" class="color-btn-icon" />
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'color-button',
|
||||||
|
props: {
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.color-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
.color-block {
|
||||||
|
height: 20px;
|
||||||
|
margin-left: 8px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.color-btn-icon {
|
||||||
|
width: 30px;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 2px;
|
||||||
|
color: #bfbfbf;
|
||||||
|
}
|
||||||
|
</style>
|
@ -30,10 +30,7 @@
|
|||||||
@update:modelValue="value => updateOutline({ color: value })"
|
@update:modelValue="value => updateOutline({ color: value })"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<Button class="color-btn" style="flex: 3;">
|
<ColorButton :color="outline.color" style="flex: 3;" />
|
||||||
<div class="color-block" :style="{ backgroundColor: outline.color }"></div>
|
|
||||||
<IconFont type="icon-down" class="color-btn-icon" />
|
|
||||||
</Button>
|
|
||||||
</Popover>
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -55,8 +52,13 @@ import { MutationTypes, State } from '@/store'
|
|||||||
import { PPTElement, PPTElementOutline } from '@/types/slides'
|
import { PPTElement, PPTElementOutline } from '@/types/slides'
|
||||||
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
|
import ColorButton from './ColorButton.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'element-outline',
|
name: 'element-outline',
|
||||||
|
components: {
|
||||||
|
ColorButton,
|
||||||
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const handleElement: Ref<PPTElement> = computed(() => store.getters.handleElement)
|
const handleElement: Ref<PPTElement> = computed(() => store.getters.handleElement)
|
||||||
@ -104,22 +106,6 @@ export default defineComponent({
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
.color-btn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.color-block {
|
|
||||||
width: 100px;
|
|
||||||
height: 20px;
|
|
||||||
background-color: #777;
|
|
||||||
margin: 0 8px;
|
|
||||||
}
|
|
||||||
.color-btn-icon {
|
|
||||||
font-size: 12px;
|
|
||||||
margin-top: 2px;
|
|
||||||
color: #bfbfbf;
|
|
||||||
}
|
|
||||||
.switch-wrapper {
|
.switch-wrapper {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
@ -49,10 +49,7 @@
|
|||||||
@update:modelValue="value => updateShadow({ color: value })"
|
@update:modelValue="value => updateShadow({ color: value })"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<Button class="color-btn" style="flex: 3;">
|
<ColorButton :color="shadow.color" style="flex: 3;" />
|
||||||
<div class="color-block"></div>
|
|
||||||
<IconFont type="icon-down" class="color-btn-icon" />
|
|
||||||
</Button>
|
|
||||||
</Popover>
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -66,8 +63,13 @@ import { MutationTypes, State } from '@/store'
|
|||||||
import { PPTElement, PPTElementShadow } from '@/types/slides'
|
import { PPTElement, PPTElementShadow } from '@/types/slides'
|
||||||
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
|
|
||||||
|
import ColorButton from './ColorButton.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'element-shadow',
|
name: 'element-shadow',
|
||||||
|
components: {
|
||||||
|
ColorButton,
|
||||||
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const handleElement: Ref<PPTElement> = computed(() => store.getters.handleElement)
|
const handleElement: Ref<PPTElement> = computed(() => store.getters.handleElement)
|
||||||
@ -115,22 +117,6 @@ export default defineComponent({
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
.color-btn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.color-block {
|
|
||||||
width: 100px;
|
|
||||||
height: 20px;
|
|
||||||
background-color: #777;
|
|
||||||
margin: 0 8px;
|
|
||||||
}
|
|
||||||
.color-btn-icon {
|
|
||||||
font-size: 12px;
|
|
||||||
margin-top: 2px;
|
|
||||||
color: #bfbfbf;
|
|
||||||
}
|
|
||||||
.switch-wrapper {
|
.switch-wrapper {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
@ -67,8 +67,9 @@ export default defineComponent({
|
|||||||
transform-origin: 0 0;
|
transform-origin: 0 0;
|
||||||
}
|
}
|
||||||
.background {
|
.background {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-size: cover;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -69,8 +69,9 @@ export default defineComponent({
|
|||||||
transform-origin: 0 0;
|
transform-origin: 0 0;
|
||||||
}
|
}
|
||||||
.background {
|
.background {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-size: cover;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
Loading…
x
Reference in New Issue
Block a user