Add slideshow widget
This commit is contained in:
		
							parent
							
								
									d1bd9fa552
								
							
						
					
					
						commit
						2112fb3896
					
				
					 3 changed files with 171 additions and 0 deletions
				
			
		|  | @ -995,6 +995,7 @@ _widgets: | |||
|   digitalClock: "デジタル時計" | ||||
|   federation: "連合" | ||||
|   postForm: "投稿フォーム" | ||||
|   slideshow: "スライドショー" | ||||
| 
 | ||||
| _cw: | ||||
|   hide: "隠す" | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ export default function(app: App) { | |||
| 	app.component('MkwDigitalClock', defineAsyncComponent(() => import('./digital-clock.vue'))); | ||||
| 	app.component('MkwFederation', defineAsyncComponent(() => import('./federation.vue'))); | ||||
| 	app.component('MkwPostForm', defineAsyncComponent(() => import('./post-form.vue'))); | ||||
| 	app.component('MkwSlideshow', defineAsyncComponent(() => import('./slideshow.vue'))); | ||||
| } | ||||
| 
 | ||||
| export const widgets = [ | ||||
|  | @ -28,4 +29,5 @@ export const widgets = [ | |||
| 	'digitalClock', | ||||
| 	'federation', | ||||
| 	'postForm', | ||||
| 	'slideshow', | ||||
| ]; | ||||
|  |  | |||
							
								
								
									
										168
									
								
								src/client/widgets/slideshow.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								src/client/widgets/slideshow.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,168 @@ | |||
| <template> | ||||
| <div class="kvausudm _panel"> | ||||
| 	<div @click="choose"> | ||||
| 		<p v-if="props.folderId == null"> | ||||
| 			<template v-if="isCustomizeMode">{{ $t('folder-customize-mode') }}</template> | ||||
| 			<template v-else>{{ $t('folder') }}</template> | ||||
| 		</p> | ||||
| 		<p v-if="props.folderId != null && images.length === 0 && !fetching">{{ $t('no-image') }}</p> | ||||
| 		<div ref="slideA" class="slide a"></div> | ||||
| 		<div ref="slideB" class="slide b"></div> | ||||
| 	</div> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import {  } from '@fortawesome/free-solid-svg-icons'; | ||||
| import define from './define'; | ||||
| import * as os from '@/os'; | ||||
| 
 | ||||
| const widget = define({ | ||||
| 	name: 'slideshow', | ||||
| 	props: () => ({ | ||||
| 		height: { | ||||
| 			type: 'number', | ||||
| 			default: 300, | ||||
| 		}, | ||||
| 		folderId: { | ||||
| 			type: 'string', | ||||
| 			default: null, | ||||
| 			hidden: true, | ||||
| 		}, | ||||
| 	}) | ||||
| }); | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	extends: widget, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			images: [], | ||||
| 			fetching: true, | ||||
| 			clock: null | ||||
| 		}; | ||||
| 	}, | ||||
| 	mounted() { | ||||
| 		this.$nextTick(() => { | ||||
| 			this.applySize(); | ||||
| 		}); | ||||
| 
 | ||||
| 		if (this.props.folderId != null) { | ||||
| 			this.fetch(); | ||||
| 		} | ||||
| 
 | ||||
| 		this.clock = setInterval(this.change, 10000); | ||||
| 	}, | ||||
| 	beforeUnmount() { | ||||
| 		clearInterval(this.clock); | ||||
| 	}, | ||||
| 	methods: { | ||||
| 		applySize() { | ||||
| 			let h; | ||||
| 
 | ||||
| 			if (this.props.size == 1) { | ||||
| 				h = 250; | ||||
| 			} else { | ||||
| 				h = 170; | ||||
| 			} | ||||
| 
 | ||||
| 			this.$el.style.height = `${h}px`; | ||||
| 		}, | ||||
| 		resize() { | ||||
| 			if (this.props.size == 1) { | ||||
| 				this.props.size = 0; | ||||
| 			} else { | ||||
| 				this.props.size++; | ||||
| 			} | ||||
| 			this.save(); | ||||
| 
 | ||||
| 			this.applySize(); | ||||
| 		}, | ||||
| 		change() { | ||||
| 			if (this.images.length == 0) return; | ||||
| 
 | ||||
| 			const index = Math.floor(Math.random() * this.images.length); | ||||
| 			const img = `url(${ this.images[index].url })`; | ||||
| 
 | ||||
| 			(this.$refs.slideB as any).style.backgroundImage = img; | ||||
| 
 | ||||
| 			this.$refs.slideB.classList.add('anime'); | ||||
| 			setTimeout(() => { | ||||
| 				// 既にこのウィジェットがunmountされていたら要素がない | ||||
| 				if ((this.$refs.slideA as any) == null) return; | ||||
| 
 | ||||
| 				(this.$refs.slideA as any).style.backgroundImage = img; | ||||
| 
 | ||||
| 				this.$refs.slideB.classList.remove('anime'); | ||||
| 			}, 1000); | ||||
| 		}, | ||||
| 		fetch() { | ||||
| 			this.fetching = true; | ||||
| 
 | ||||
| 			os.api('drive/files', { | ||||
| 				folderId: this.props.folderId, | ||||
| 				type: 'image/*', | ||||
| 				limit: 100 | ||||
| 			}).then(images => { | ||||
| 				this.images = images; | ||||
| 				this.fetching = false; | ||||
| 				(this.$refs.slideA as any).style.backgroundImage = ''; | ||||
| 				(this.$refs.slideB as any).style.backgroundImage = ''; | ||||
| 				this.change(); | ||||
| 			}); | ||||
| 		}, | ||||
| 		choose() { | ||||
| 			os.selectDriveFolder(false).then(folder => { | ||||
| 				if (folder == null) { | ||||
| 					return; | ||||
| 				} | ||||
| 				this.props.folderId = folder.id; | ||||
| 				this.save(); | ||||
| 				this.fetch(); | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .kvausudm { | ||||
| 	position: relative; | ||||
| 
 | ||||
| 	> div { | ||||
| 		width: 100%; | ||||
| 		height: 100%; | ||||
| 		cursor: pointer; | ||||
| 
 | ||||
| 		> p { | ||||
| 			display: block; | ||||
| 			margin: 1em; | ||||
| 			text-align: center; | ||||
| 			color: #888; | ||||
| 		} | ||||
| 
 | ||||
| 		> * { | ||||
| 			pointer-events: none; | ||||
| 		} | ||||
| 
 | ||||
| 		> .slide { | ||||
| 			position: absolute; | ||||
| 			top: 0; | ||||
| 			left: 0; | ||||
| 			width: 100%; | ||||
| 			height: 100%; | ||||
| 			background-size: cover; | ||||
| 			background-position: center; | ||||
| 
 | ||||
| 			&.b { | ||||
| 				opacity: 0; | ||||
| 			} | ||||
| 
 | ||||
| 			&.anime { | ||||
| 				transition: opacity 1s; | ||||
| 				opacity: 1; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue