添加幻灯片放映时的全部页面总览

This commit is contained in:
pipipi-pikachu 2021-01-12 22:29:37 +08:00
parent 3266d853c4
commit 3230e76de8
4 changed files with 128 additions and 10 deletions

View File

@ -3,5 +3,5 @@
import { createFromIconfontCN } from '@ant-design/icons-vue' import { createFromIconfontCN } from '@ant-design/icons-vue'
export default createFromIconfontCN({ export default createFromIconfontCN({
scriptUrl: '//at.alicdn.com/t/font_2317509_83tu8tohuv.js', scriptUrl: '//at.alicdn.com/t/font_2317509_nn4bn0af7a.js',
}) as any }) as any

View File

@ -29,6 +29,7 @@ import {
Switch, Switch,
Radio, Radio,
Input, Input,
Modal,
} from 'ant-design-vue' } from 'ant-design-vue'
const app = createApp(App) const app = createApp(App)
@ -48,6 +49,7 @@ app.component('RadioGroup', Radio.Group)
app.component('RadioButton', Radio.Button) app.component('RadioButton', Radio.Button)
app.component('Input', Input) app.component('Input', Input)
app.component('InputGroup', Input.Group) app.component('InputGroup', Input.Group)
app.component('Modal', Modal)
app.use(contextmenu) app.use(contextmenu)
app.use(clickOutside) app.use(clickOutside)

View File

@ -321,7 +321,7 @@ export default defineComponent({
store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, {
id: handleElement.value.id, id: handleElement.value.id,
propName: ['clip', 'outline', 'flip', 'shadow', 'filter'], propName: ['clip', 'outline', 'flip', 'shadow', 'filters'],
}) })
addHistorySnapshot() addHistorySnapshot()
} }

View File

@ -8,12 +8,13 @@
<div <div
:class="[ :class="[
'slide-item', 'slide-item',
`turning-mode-${slide.turningMode || 'slideY'}`,
{ {
'show': index === slideIndex, 'show': index === slideIndex,
'prev': index < slideIndex, 'prev': index < slideIndex,
'next': index > slideIndex, 'next': index > slideIndex,
} }
]" ]"
v-for="(slide, index) in slides" v-for="(slide, index) in slides"
:key="slide.id" :key="slide.id"
> >
@ -32,6 +33,33 @@
</div> </div>
</div> </div>
</div> </div>
<Modal
v-model:visible="slideListModelVisible"
:footer="null"
centered
:width="1020"
:bodyStyle="{ padding: '50px 20px 20px 20px' }"
>
<div class="slide-list-model">
<div
class="thumbnail"
:class="{ 'active': index === slideIndex }"
v-for="(slide, index) in slides"
:key="slide.id"
@click="turnSlideToIndex(index)"
>
<ThumbnailSlide :slide="slide" :size="150" />
</div>
</div>
</Modal>
<div class="tools">
<IconFont class="tool-btn" type="icon-left-circle" @click="execPrev()" />
<IconFont class="tool-btn" type="icon-right-circle" @click="execNext()" />
<IconFont class="tool-btn" type="icon-appstore" @click="slideListModelVisible = true" />
<IconFont class="tool-btn" type="icon-edit" />
</div>
</div> </div>
</template> </template>
@ -40,18 +68,20 @@ import { computed, defineComponent, onMounted, onUnmounted, Ref, ref } from 'vue
import { useStore } from 'vuex' import { useStore } from 'vuex'
import throttle from 'lodash/throttle' import throttle from 'lodash/throttle'
import { MutationTypes, State } from '@/store' import { MutationTypes, State } from '@/store'
import { Slide } from '@/types/slides'
import { exitFullscreen, isFullscreen } from '@/utils/fullscreen' import { exitFullscreen, isFullscreen } from '@/utils/fullscreen'
import { VIEWPORT_ASPECT_RATIO, VIEWPORT_SIZE } from '@/configs/canvas' import { VIEWPORT_ASPECT_RATIO, VIEWPORT_SIZE } from '@/configs/canvas'
import { KEYS } from '@/configs/hotkey' import { KEYS } from '@/configs/hotkey'
import { ContextmenuItem } from '@/components/Contextmenu/types' import { ContextmenuItem } from '@/components/Contextmenu/types'
import ScreenSlide from './ScreenSlide.vue' import ScreenSlide from './ScreenSlide.vue'
import { Slide } from '@/types/slides' import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'
export default defineComponent({ export default defineComponent({
name: 'screen', name: 'screen',
components: { components: {
ScreenSlide, ScreenSlide,
ThumbnailSlide,
}, },
setup() { setup() {
const store = useStore<State>() const store = useStore<State>()
@ -63,6 +93,8 @@ export default defineComponent({
const slideHeight = ref(0) const slideHeight = ref(0)
const scale = computed(() => slideWidth.value / VIEWPORT_SIZE) const scale = computed(() => slideWidth.value / VIEWPORT_SIZE)
const slideListModelVisible = ref(false)
const setSlideContentSize = () => { const setSlideContentSize = () => {
const winWidth = document.body.clientWidth const winWidth = document.body.clientWidth
const winHeight = document.body.clientHeight const winHeight = document.body.clientHeight
@ -158,6 +190,12 @@ export default defineComponent({
animationIndex.value = 0 animationIndex.value = 0
} }
const turnSlideToIndex = (index: number) => {
slideListModelVisible.value = false
store.commit(MutationTypes.UPDATE_SLIDE_INDEX, index)
animationIndex.value = 0
}
const contextmenus = (): ContextmenuItem[] => { const contextmenus = (): ContextmenuItem[] => {
return [ return [
{ {
@ -188,6 +226,10 @@ export default defineComponent({
mousewheelListener, mousewheelListener,
animationIndex, animationIndex,
contextmenus, contextmenus,
execPrev,
execNext,
slideListModelVisible,
turnSlideToIndex,
} }
}, },
}) })
@ -212,17 +254,48 @@ export default defineComponent({
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
transition-property: transform;
transition-duration: .4s;
&.show { &.show {
z-index: 2; z-index: 2;
} }
&.prev {
transform: translateY(-100%); &.turning-mode-no {
&.prev {
transform: translateY(-100%);
}
&.next {
transform: translateY(100%);
}
} }
&.next { &.turning-mode-fade {
transform: translateY(100%); transition: opacity .75s;
&.prev {
pointer-events: none;
opacity: 0;
}
&.next {
pointer-events: none;
opacity: 0;
}
}
&.turning-mode-slideX {
transition: transform .35s;
&.prev {
transform: translateX(-100%);
}
&.next {
transform: translateX(100%);
}
}
&.turning-mode-slideY {
transition: transform .35s;
&.prev {
transform: translateY(-100%);
}
&.next {
transform: translateY(100%);
}
} }
} }
.slide-content { .slide-content {
@ -235,4 +308,47 @@ export default defineComponent({
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.tools {
position: fixed;
bottom: 8px;
left: 8px;
font-size: 25px;
color: #666;
z-index: 10;
cursor: pointer;
}
.tool-btn {
opacity: .35;
&:hover {
opacity: .7;
}
& + .tool-btn {
margin-left: 8px;
}
}
.slide-list-model {
height: 600px;
padding: 5px 10px;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
overflow: overlay;
.thumbnail {
width: 150px;
margin-bottom: 12px;
outline: 1px solid rgba($color: $themeColor, $alpha: .1);
&.active {
outline-color: $themeColor;
}
&:not(:nth-child(6n)) {
margin-right: 12px;
}
}
}
</style> </style>