enhance(client): ウィンドウを最大化できるように
This commit is contained in:
		
							parent
							
								
									01d7403dc4
								
							
						
					
					
						commit
						e9a97b4717
					
				
					 2 changed files with 316 additions and 279 deletions
				
			
		|  | @ -9,6 +9,15 @@ | ||||||
| You should also include the user name that made the change. | You should also include the user name that made the change. | ||||||
| --> | --> | ||||||
| 
 | 
 | ||||||
|  | ## 12.x.x (unreleased) | ||||||
|  | 
 | ||||||
|  | ### Improvements | ||||||
|  | - Client: ウィンドウを最大化できるように @syuilo | ||||||
|  | - Client: UIのブラッシュアップ @syuilo | ||||||
|  | 
 | ||||||
|  | ### Bugfixes | ||||||
|  | -  | ||||||
|  | 
 | ||||||
| ## 12.116.1 (2022/07/17) | ## 12.116.1 (2022/07/17) | ||||||
| 
 | 
 | ||||||
| ### Bugfixes | ### Bugfixes | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| <template> | <template> | ||||||
| <transition :name="$store.state.animation ? 'window' : ''" appear @after-leave="$emit('closed')"> | <transition :name="$store.state.animation ? 'window' : ''" appear @after-leave="$emit('closed')"> | ||||||
| 	<div v-if="showing" class="ebkgocck"> | 	<div v-if="showing" ref="rootEl" class="ebkgocck"> | ||||||
| 		<div class="body _shadow _narrow_" @mousedown="onBodyMousedown" @keydown="onKeydown"> | 		<div class="body _shadow _narrow_" @mousedown="onBodyMousedown" @keydown="onKeydown"> | ||||||
| 			<div class="header" :class="{ mini }" @contextmenu.prevent.stop="onContextmenu"> | 			<div class="header" :class="{ mini }" @contextmenu.prevent.stop="onContextmenu"> | ||||||
| 				<span class="left"> | 				<span class="left"> | ||||||
|  | @ -11,6 +11,8 @@ | ||||||
| 				</span> | 				</span> | ||||||
| 				<span class="right"> | 				<span class="right"> | ||||||
| 					<button v-for="button in buttonsRight" v-tooltip="button.title" class="button _button" :class="{ highlighted: button.highlighted }" @click="button.onClick"><i :class="button.icon"></i></button> | 					<button v-for="button in buttonsRight" v-tooltip="button.title" class="button _button" :class="{ highlighted: button.highlighted }" @click="button.onClick"><i :class="button.icon"></i></button> | ||||||
|  | 					<button v-if="canResize && maximized" class="button _button" @click="unMaximize()"><i class="fas fa-window-restore"></i></button> | ||||||
|  | 					<button v-else-if="canResize && !maximized" class="button _button" @click="maximize()"><i class="fas fa-window-maximize"></i></button> | ||||||
| 					<button v-if="closeButton" class="button _button" @click="close()"><i class="fas fa-times"></i></button> | 					<button v-if="closeButton" class="button _button" @click="close()"><i class="fas fa-times"></i></button> | ||||||
| 				</span> | 				</span> | ||||||
| 			</div> | 			</div> | ||||||
|  | @ -32,15 +34,16 @@ | ||||||
| </transition> | </transition> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script lang="ts"> | <script lang="ts" setup> | ||||||
| import { defineComponent } from 'vue'; | import { onBeforeUnmount, onMounted, provide } from 'vue'; | ||||||
| import contains from '@/scripts/contains'; | import contains from '@/scripts/contains'; | ||||||
| import * as os from '@/os'; | import * as os from '@/os'; | ||||||
|  | import { MenuItem } from '@/types/menu'; | ||||||
| 
 | 
 | ||||||
| const minHeight = 50; | const minHeight = 50; | ||||||
| const minWidth = 250; | const minWidth = 250; | ||||||
| 
 | 
 | ||||||
| function dragListen(fn) { | function dragListen(fn: (ev: MouseEvent) => void) { | ||||||
| 	window.addEventListener('mousemove', fn); | 	window.addEventListener('mousemove', fn); | ||||||
| 	window.addEventListener('touchmove', fn); | 	window.addEventListener('touchmove', fn); | ||||||
| 	window.addEventListener('mouseleave', dragClear.bind(null, fn)); | 	window.addEventListener('mouseleave', dragClear.bind(null, fn)); | ||||||
|  | @ -56,315 +59,340 @@ function dragClear(fn) { | ||||||
| 	window.removeEventListener('touchend', dragClear); | 	window.removeEventListener('touchend', dragClear); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export default defineComponent({ | const props = withDefaults(defineProps<{ | ||||||
| 	provide: { | 	initialWidth?: number; | ||||||
| 		inWindow: true, | 	initialHeight?: number | null; | ||||||
| 	}, | 	canResize?: boolean; | ||||||
|  | 	closeButton?: boolean; | ||||||
|  | 	mini?: boolean; | ||||||
|  | 	front?: boolean; | ||||||
|  | 	contextmenu?: MenuItem[] | null; | ||||||
|  | 	buttonsLeft?: any[]; | ||||||
|  | 	buttonsRight?: any[]; | ||||||
|  | }>(), { | ||||||
|  | 	initialWidth: 400, | ||||||
|  | 	initialHeight: null, | ||||||
|  | 	canResize: false, | ||||||
|  | 	closeButton: true, | ||||||
|  | 	mini: false, | ||||||
|  | 	front: true, | ||||||
|  | 	contextmenu: null, | ||||||
|  | 	buttonsLeft: () => [], | ||||||
|  | 	buttonsRight: () => [], | ||||||
|  | }); | ||||||
| 
 | 
 | ||||||
| 	props: { | const emit = defineEmits<{ | ||||||
| 		initialWidth: { | 	(ev: 'closed'): void; | ||||||
| 			type: Number, | }>(); | ||||||
| 			required: false, |  | ||||||
| 			default: 400, |  | ||||||
| 		}, |  | ||||||
| 		initialHeight: { |  | ||||||
| 			type: Number, |  | ||||||
| 			required: false, |  | ||||||
| 			default: null, |  | ||||||
| 		}, |  | ||||||
| 		canResize: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			required: false, |  | ||||||
| 			default: false, |  | ||||||
| 		}, |  | ||||||
| 		closeButton: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			required: false, |  | ||||||
| 			default: true, |  | ||||||
| 		}, |  | ||||||
| 		mini: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			required: false, |  | ||||||
| 			default: false, |  | ||||||
| 		}, |  | ||||||
| 		front: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			required: false, |  | ||||||
| 			default: false, |  | ||||||
| 		}, |  | ||||||
| 		contextmenu: { |  | ||||||
| 			type: Array, |  | ||||||
| 			required: false, |  | ||||||
| 		}, |  | ||||||
| 		buttonsLeft: { |  | ||||||
| 			type: Array, |  | ||||||
| 			required: false, |  | ||||||
| 			default: () => [], |  | ||||||
| 		}, |  | ||||||
| 		buttonsRight: { |  | ||||||
| 			type: Array, |  | ||||||
| 			required: false, |  | ||||||
| 			default: () => [], |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| 
 | 
 | ||||||
| 	emits: ['closed'], | provide('inWindow', true); | ||||||
| 
 | 
 | ||||||
| 	data() { | let rootEl = $ref<HTMLElement>(); | ||||||
| 		return { | let showing = $ref(true); | ||||||
| 			showing: true, | let beforeClickedAt = 0; | ||||||
| 			id: Math.random().toString(), // TODO: UUIDとかにする | let maximized = $ref(false); | ||||||
| 		}; | let unMaximizedTop = ''; | ||||||
| 	}, | let unMaximizedLeft = ''; | ||||||
|  | let unMaximizedWidth = ''; | ||||||
|  | let unMaximizedHeight = ''; | ||||||
| 
 | 
 | ||||||
| 	mounted() { | function close() { | ||||||
| 		if (this.initialWidth) this.applyTransformWidth(this.initialWidth); | 	showing = false; | ||||||
| 		if (this.initialHeight) this.applyTransformHeight(this.initialHeight); | } | ||||||
| 
 | 
 | ||||||
| 		this.applyTransformTop((window.innerHeight / 2) - (this.$el.offsetHeight / 2)); | function onKeydown(evt) { | ||||||
| 		this.applyTransformLeft((window.innerWidth / 2) - (this.$el.offsetWidth / 2)); | 	if (evt.which === 27) { // Esc | ||||||
|  | 		evt.preventDefault(); | ||||||
|  | 		evt.stopPropagation(); | ||||||
|  | 		close(); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 		// 他のウィンドウ内のボタンなどを押してこのウィンドウが開かれた場合、親が最前面になろうとするのでそれに隠されないようにする | function onContextmenu(ev: MouseEvent) { | ||||||
| 		this.top(); | 	if (props.contextmenu) { | ||||||
|  | 		os.contextMenu(props.contextmenu, ev); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 		window.addEventListener('resize', this.onBrowserResize); | // 最前面へ移動 | ||||||
| 	}, | function top() { | ||||||
|  | 	rootEl.style.zIndex = os.claimZIndex(props.front ? 'middle' : 'low'); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 	unmounted() { | function maximize() { | ||||||
| 		window.removeEventListener('resize', this.onBrowserResize); | 	maximized = true; | ||||||
| 	}, | 	unMaximizedTop = rootEl.style.top; | ||||||
|  | 	unMaximizedLeft = rootEl.style.left; | ||||||
|  | 	unMaximizedWidth = rootEl.style.width; | ||||||
|  | 	unMaximizedHeight = rootEl.style.height; | ||||||
|  | 	rootEl.style.top = '0'; | ||||||
|  | 	rootEl.style.left = '0'; | ||||||
|  | 	rootEl.style.width = '100%'; | ||||||
|  | 	rootEl.style.height = '100%'; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 	methods: { | function unMaximize() { | ||||||
| 		close() { | 	maximized = false; | ||||||
| 			this.showing = false; | 	rootEl.style.top = unMaximizedTop; | ||||||
| 		}, | 	rootEl.style.left = unMaximizedLeft; | ||||||
|  | 	rootEl.style.width = unMaximizedWidth; | ||||||
|  | 	rootEl.style.height = unMaximizedHeight; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 		onKeydown(evt) { | function onBodyMousedown() { | ||||||
| 			if (evt.which === 27) { // Esc | 	top(); | ||||||
| 				evt.preventDefault(); | } | ||||||
| 				evt.stopPropagation(); | 
 | ||||||
| 				this.close(); | function onDblClick() { | ||||||
|  | 	maximize(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function onHeaderMousedown(evt: MouseEvent) { | ||||||
|  | 	// 右クリックはコンテキストメニューを開こうとした可能性が高いため無視 | ||||||
|  | 	if (evt.button === 2) return; | ||||||
|  | 
 | ||||||
|  | 	let beforeMaximized = false; | ||||||
|  | 
 | ||||||
|  | 	if (maximized) { | ||||||
|  | 		beforeMaximized = true; | ||||||
|  | 		unMaximize(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// ダブルクリック判定 | ||||||
|  | 	if (Date.now() - beforeClickedAt < 300) { | ||||||
|  | 		beforeClickedAt = Date.now(); | ||||||
|  | 		onDblClick(); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	beforeClickedAt = Date.now(); | ||||||
|  | 
 | ||||||
|  | 	const main = rootEl; | ||||||
|  | 
 | ||||||
|  | 	if (!contains(main, document.activeElement)) main.focus(); | ||||||
|  | 
 | ||||||
|  | 	const position = main.getBoundingClientRect(); | ||||||
|  | 
 | ||||||
|  | 	const clickX = evt.touches && evt.touches.length > 0 ? evt.touches[0].clientX : evt.clientX; | ||||||
|  | 	const clickY = evt.touches && evt.touches.length > 0 ? evt.touches[0].clientY : evt.clientY; | ||||||
|  | 	const moveBaseX = beforeMaximized ? parseInt(unMaximizedWidth, 10) / 2 : clickX - position.left; // TODO: parseIntやめる | ||||||
|  | 	const moveBaseY = beforeMaximized ? 20 : clickY - position.top; | ||||||
|  | 	const browserWidth = window.innerWidth; | ||||||
|  | 	const browserHeight = window.innerHeight; | ||||||
|  | 	const windowWidth = main.offsetWidth; | ||||||
|  | 	const windowHeight = main.offsetHeight; | ||||||
|  | 
 | ||||||
|  | 	function move(x: number, y: number) { | ||||||
|  | 		let moveLeft = x - moveBaseX; | ||||||
|  | 		let moveTop = y - moveBaseY; | ||||||
|  | 
 | ||||||
|  | 		// 下はみ出し | ||||||
|  | 		if (moveTop + windowHeight > browserHeight) moveTop = browserHeight - windowHeight; | ||||||
|  | 
 | ||||||
|  | 		// 左はみ出し | ||||||
|  | 		if (moveLeft < 0) moveLeft = 0; | ||||||
|  | 
 | ||||||
|  | 		// 上はみ出し | ||||||
|  | 		if (moveTop < 0) moveTop = 0; | ||||||
|  | 
 | ||||||
|  | 		// 右はみ出し | ||||||
|  | 		if (moveLeft + windowWidth > browserWidth) moveLeft = browserWidth - windowWidth; | ||||||
|  | 
 | ||||||
|  | 		rootEl.style.left = moveLeft + 'px'; | ||||||
|  | 		rootEl.style.top = moveTop + 'px'; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (beforeMaximized) { | ||||||
|  | 		move(clickX, clickY); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// 動かした時 | ||||||
|  | 	dragListen(me => { | ||||||
|  | 		const x = me.touches && me.touches.length > 0 ? me.touches[0].clientX : me.clientX; | ||||||
|  | 		const y = me.touches && me.touches.length > 0 ? me.touches[0].clientY : me.clientY; | ||||||
|  | 
 | ||||||
|  | 		move(x, y); | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // 上ハンドル掴み時 | ||||||
|  | function onTopHandleMousedown(evt) { | ||||||
|  | 	const main = rootEl; | ||||||
|  | 
 | ||||||
|  | 	const base = evt.clientY; | ||||||
|  | 	const height = parseInt(getComputedStyle(main, '').height, 10); | ||||||
|  | 	const top = parseInt(getComputedStyle(main, '').top, 10); | ||||||
|  | 
 | ||||||
|  | 	// 動かした時 | ||||||
|  | 	dragListen(me => { | ||||||
|  | 		const move = me.clientY - base; | ||||||
|  | 		if (top + move > 0) { | ||||||
|  | 			if (height + -move > minHeight) { | ||||||
|  | 				applyTransformHeight(height + -move); | ||||||
|  | 				applyTransformTop(top + move); | ||||||
|  | 			} else { // 最小の高さより小さくなろうとした時 | ||||||
|  | 				applyTransformHeight(minHeight); | ||||||
|  | 				applyTransformTop(top + (height - minHeight)); | ||||||
| 			} | 			} | ||||||
| 		}, | 		} else { // 上のはみ出し時 | ||||||
|  | 			applyTransformHeight(top + height); | ||||||
|  | 			applyTransformTop(0); | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 		onContextmenu(ev: MouseEvent) { | // 右ハンドル掴み時 | ||||||
| 			if (this.contextmenu) { | function onRightHandleMousedown(evt) { | ||||||
| 				os.contextMenu(this.contextmenu, ev); | 	const main = rootEl; | ||||||
|  | 
 | ||||||
|  | 	const base = evt.clientX; | ||||||
|  | 	const width = parseInt(getComputedStyle(main, '').width, 10); | ||||||
|  | 	const left = parseInt(getComputedStyle(main, '').left, 10); | ||||||
|  | 	const browserWidth = window.innerWidth; | ||||||
|  | 
 | ||||||
|  | 	// 動かした時 | ||||||
|  | 	dragListen(me => { | ||||||
|  | 		const move = me.clientX - base; | ||||||
|  | 		if (left + width + move < browserWidth) { | ||||||
|  | 			if (width + move > minWidth) { | ||||||
|  | 				applyTransformWidth(width + move); | ||||||
|  | 			} else { // 最小の幅より小さくなろうとした時 | ||||||
|  | 				applyTransformWidth(minWidth); | ||||||
| 			} | 			} | ||||||
| 		}, | 		} else { // 右のはみ出し時 | ||||||
|  | 			applyTransformWidth(browserWidth - left); | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 		// 最前面へ移動 | // 下ハンドル掴み時 | ||||||
| 		top() { | function onBottomHandleMousedown(evt) { | ||||||
| 			(this.$el as any).style.zIndex = os.claimZIndex(this.front ? 'middle' : 'low'); | 	const main = rootEl; | ||||||
| 		}, |  | ||||||
| 
 | 
 | ||||||
| 		onBodyMousedown() { | 	const base = evt.clientY; | ||||||
| 			this.top(); | 	const height = parseInt(getComputedStyle(main, '').height, 10); | ||||||
| 		}, | 	const top = parseInt(getComputedStyle(main, '').top, 10); | ||||||
|  | 	const browserHeight = window.innerHeight; | ||||||
| 
 | 
 | ||||||
| 		onHeaderMousedown(evt: MouseEvent) { | 	// 動かした時 | ||||||
| 			// 右クリックはコンテキストメニューを開こうとした可能性が高いため無視 | 	dragListen(me => { | ||||||
| 			if (evt.button === 2) return; | 		const move = me.clientY - base; | ||||||
|  | 		if (top + height + move < browserHeight) { | ||||||
|  | 			if (height + move > minHeight) { | ||||||
|  | 				applyTransformHeight(height + move); | ||||||
|  | 			} else { // 最小の高さより小さくなろうとした時 | ||||||
|  | 				applyTransformHeight(minHeight); | ||||||
|  | 			} | ||||||
|  | 		} else { // 下のはみ出し時 | ||||||
|  | 			applyTransformHeight(browserHeight - top); | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 			const main = this.$el as any; | // 左ハンドル掴み時 | ||||||
|  | function onLeftHandleMousedown(evt) { | ||||||
|  | 	const main = rootEl; | ||||||
| 
 | 
 | ||||||
| 			if (!contains(main, document.activeElement)) main.focus(); | 	const base = evt.clientX; | ||||||
|  | 	const width = parseInt(getComputedStyle(main, '').width, 10); | ||||||
|  | 	const left = parseInt(getComputedStyle(main, '').left, 10); | ||||||
| 
 | 
 | ||||||
| 			const position = main.getBoundingClientRect(); | 	// 動かした時 | ||||||
|  | 	dragListen(me => { | ||||||
|  | 		const move = me.clientX - base; | ||||||
|  | 		if (left + move > 0) { | ||||||
|  | 			if (width + -move > minWidth) { | ||||||
|  | 				applyTransformWidth(width + -move); | ||||||
|  | 				applyTransformLeft(left + move); | ||||||
|  | 			} else { // 最小の幅より小さくなろうとした時 | ||||||
|  | 				applyTransformWidth(minWidth); | ||||||
|  | 				applyTransformLeft(left + (width - minWidth)); | ||||||
|  | 			} | ||||||
|  | 		} else { // 左のはみ出し時 | ||||||
|  | 			applyTransformWidth(left + width); | ||||||
|  | 			applyTransformLeft(0); | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 			const clickX = evt.touches && evt.touches.length > 0 ? evt.touches[0].clientX : evt.clientX; | // 左上ハンドル掴み時 | ||||||
| 			const clickY = evt.touches && evt.touches.length > 0 ? evt.touches[0].clientY : evt.clientY; | function onTopLeftHandleMousedown(evt) { | ||||||
| 			const moveBaseX = clickX - position.left; | 	onTopHandleMousedown(evt); | ||||||
| 			const moveBaseY = clickY - position.top; | 	onLeftHandleMousedown(evt); | ||||||
| 			const browserWidth = window.innerWidth; | } | ||||||
| 			const browserHeight = window.innerHeight; |  | ||||||
| 			const windowWidth = main.offsetWidth; |  | ||||||
| 			const windowHeight = main.offsetHeight; |  | ||||||
| 
 | 
 | ||||||
| 			// 動かした時 | // 右上ハンドル掴み時 | ||||||
| 			dragListen(me => { | function onTopRightHandleMousedown(evt) { | ||||||
| 				const x = me.touches && me.touches.length > 0 ? me.touches[0].clientX : me.clientX; | 	onTopHandleMousedown(evt); | ||||||
| 				const y = me.touches && me.touches.length > 0 ? me.touches[0].clientY : me.clientY; | 	onRightHandleMousedown(evt); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 				let moveLeft = x - moveBaseX; | // 右下ハンドル掴み時 | ||||||
| 				let moveTop = y - moveBaseY; | function onBottomRightHandleMousedown(evt) { | ||||||
|  | 	onBottomHandleMousedown(evt); | ||||||
|  | 	onRightHandleMousedown(evt); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 				// 下はみ出し | // 左下ハンドル掴み時 | ||||||
| 				if (moveTop + windowHeight > browserHeight) moveTop = browserHeight - windowHeight; | function onBottomLeftHandleMousedown(evt) { | ||||||
|  | 	onBottomHandleMousedown(evt); | ||||||
|  | 	onLeftHandleMousedown(evt); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 				// 左はみ出し | // 高さを適用 | ||||||
| 				if (moveLeft < 0) moveLeft = 0; | function applyTransformHeight(height) { | ||||||
|  | 	if (height > window.innerHeight) height = window.innerHeight; | ||||||
|  | 	rootEl.style.height = height + 'px'; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 				// 上はみ出し | // 幅を適用 | ||||||
| 				if (moveTop < 0) moveTop = 0; | function applyTransformWidth(width) { | ||||||
|  | 	if (width > window.innerWidth) width = window.innerWidth; | ||||||
|  | 	rootEl.style.width = width + 'px'; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 				// 右はみ出し | // Y座標を適用 | ||||||
| 				if (moveLeft + windowWidth > browserWidth) moveLeft = browserWidth - windowWidth; | function applyTransformTop(top) { | ||||||
|  | 	rootEl.style.top = top + 'px'; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 				this.$el.style.left = moveLeft + 'px'; | // X座標を適用 | ||||||
| 				this.$el.style.top = moveTop + 'px'; | function applyTransformLeft(left) { | ||||||
| 			}); | 	rootEl.style.left = left + 'px'; | ||||||
| 		}, | } | ||||||
| 
 | 
 | ||||||
| 		// 上ハンドル掴み時 | function onBrowserResize() { | ||||||
| 		onTopHandleMousedown(evt) { | 	const main = rootEl; | ||||||
| 			const main = this.$el as any; | 	const position = main.getBoundingClientRect(); | ||||||
|  | 	const browserWidth = window.innerWidth; | ||||||
|  | 	const browserHeight = window.innerHeight; | ||||||
|  | 	const windowWidth = main.offsetWidth; | ||||||
|  | 	const windowHeight = main.offsetHeight; | ||||||
|  | 	if (position.left < 0) main.style.left = '0'; // 左はみ出し | ||||||
|  | 	if (position.top + windowHeight > browserHeight) main.style.top = browserHeight - windowHeight + 'px'; // 下はみ出し | ||||||
|  | 	if (position.left + windowWidth > browserWidth) main.style.left = browserWidth - windowWidth + 'px'; // 右はみ出し | ||||||
|  | 	if (position.top < 0) main.style.top = '0'; // 上はみ出し | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 			const base = evt.clientY; | onMounted(() => { | ||||||
| 			const height = parseInt(getComputedStyle(main, '').height, 10); | 	if (props.initialWidth) applyTransformWidth(props.initialWidth); | ||||||
| 			const top = parseInt(getComputedStyle(main, '').top, 10); | 	if (props.initialHeight) applyTransformHeight(props.initialHeight); | ||||||
| 
 | 
 | ||||||
| 			// 動かした時 | 	applyTransformTop((window.innerHeight / 2) - (rootEl.offsetHeight / 2)); | ||||||
| 			dragListen(me => { | 	applyTransformLeft((window.innerWidth / 2) - (rootEl.offsetWidth / 2)); | ||||||
| 				const move = me.clientY - base; |  | ||||||
| 				if (top + move > 0) { |  | ||||||
| 					if (height + -move > minHeight) { |  | ||||||
| 						this.applyTransformHeight(height + -move); |  | ||||||
| 						this.applyTransformTop(top + move); |  | ||||||
| 					} else { // 最小の高さより小さくなろうとした時 |  | ||||||
| 						this.applyTransformHeight(minHeight); |  | ||||||
| 						this.applyTransformTop(top + (height - minHeight)); |  | ||||||
| 					} |  | ||||||
| 				} else { // 上のはみ出し時 |  | ||||||
| 					this.applyTransformHeight(top + height); |  | ||||||
| 					this.applyTransformTop(0); |  | ||||||
| 				} |  | ||||||
| 			}); |  | ||||||
| 		}, |  | ||||||
| 
 | 
 | ||||||
| 		// 右ハンドル掴み時 | 	// 他のウィンドウ内のボタンなどを押してこのウィンドウが開かれた場合、親が最前面になろうとするのでそれに隠されないようにする | ||||||
| 		onRightHandleMousedown(evt) { | 	top(); | ||||||
| 			const main = this.$el as any; |  | ||||||
| 
 | 
 | ||||||
| 			const base = evt.clientX; | 	window.addEventListener('resize', onBrowserResize); | ||||||
| 			const width = parseInt(getComputedStyle(main, '').width, 10); | }); | ||||||
| 			const left = parseInt(getComputedStyle(main, '').left, 10); |  | ||||||
| 			const browserWidth = window.innerWidth; |  | ||||||
| 
 | 
 | ||||||
| 			// 動かした時 | onBeforeUnmount(() => { | ||||||
| 			dragListen(me => { | 	window.removeEventListener('resize', onBrowserResize); | ||||||
| 				const move = me.clientX - base; | }); | ||||||
| 				if (left + width + move < browserWidth) { |  | ||||||
| 					if (width + move > minWidth) { |  | ||||||
| 						this.applyTransformWidth(width + move); |  | ||||||
| 					} else { // 最小の幅より小さくなろうとした時 |  | ||||||
| 						this.applyTransformWidth(minWidth); |  | ||||||
| 					} |  | ||||||
| 				} else { // 右のはみ出し時 |  | ||||||
| 					this.applyTransformWidth(browserWidth - left); |  | ||||||
| 				} |  | ||||||
| 			}); |  | ||||||
| 		}, |  | ||||||
| 
 | 
 | ||||||
| 		// 下ハンドル掴み時 | defineExpose({ | ||||||
| 		onBottomHandleMousedown(evt) { | 	close, | ||||||
| 			const main = this.$el as any; |  | ||||||
| 
 |  | ||||||
| 			const base = evt.clientY; |  | ||||||
| 			const height = parseInt(getComputedStyle(main, '').height, 10); |  | ||||||
| 			const top = parseInt(getComputedStyle(main, '').top, 10); |  | ||||||
| 			const browserHeight = window.innerHeight; |  | ||||||
| 
 |  | ||||||
| 			// 動かした時 |  | ||||||
| 			dragListen(me => { |  | ||||||
| 				const move = me.clientY - base; |  | ||||||
| 				if (top + height + move < browserHeight) { |  | ||||||
| 					if (height + move > minHeight) { |  | ||||||
| 						this.applyTransformHeight(height + move); |  | ||||||
| 					} else { // 最小の高さより小さくなろうとした時 |  | ||||||
| 						this.applyTransformHeight(minHeight); |  | ||||||
| 					} |  | ||||||
| 				} else { // 下のはみ出し時 |  | ||||||
| 					this.applyTransformHeight(browserHeight - top); |  | ||||||
| 				} |  | ||||||
| 			}); |  | ||||||
| 		}, |  | ||||||
| 
 |  | ||||||
| 		// 左ハンドル掴み時 |  | ||||||
| 		onLeftHandleMousedown(evt) { |  | ||||||
| 			const main = this.$el as any; |  | ||||||
| 
 |  | ||||||
| 			const base = evt.clientX; |  | ||||||
| 			const width = parseInt(getComputedStyle(main, '').width, 10); |  | ||||||
| 			const left = parseInt(getComputedStyle(main, '').left, 10); |  | ||||||
| 
 |  | ||||||
| 			// 動かした時 |  | ||||||
| 			dragListen(me => { |  | ||||||
| 				const move = me.clientX - base; |  | ||||||
| 				if (left + move > 0) { |  | ||||||
| 					if (width + -move > minWidth) { |  | ||||||
| 						this.applyTransformWidth(width + -move); |  | ||||||
| 						this.applyTransformLeft(left + move); |  | ||||||
| 					} else { // 最小の幅より小さくなろうとした時 |  | ||||||
| 						this.applyTransformWidth(minWidth); |  | ||||||
| 						this.applyTransformLeft(left + (width - minWidth)); |  | ||||||
| 					} |  | ||||||
| 				} else { // 左のはみ出し時 |  | ||||||
| 					this.applyTransformWidth(left + width); |  | ||||||
| 					this.applyTransformLeft(0); |  | ||||||
| 				} |  | ||||||
| 			}); |  | ||||||
| 		}, |  | ||||||
| 
 |  | ||||||
| 		// 左上ハンドル掴み時 |  | ||||||
| 		onTopLeftHandleMousedown(evt) { |  | ||||||
| 			this.onTopHandleMousedown(evt); |  | ||||||
| 			this.onLeftHandleMousedown(evt); |  | ||||||
| 		}, |  | ||||||
| 
 |  | ||||||
| 		// 右上ハンドル掴み時 |  | ||||||
| 		onTopRightHandleMousedown(evt) { |  | ||||||
| 			this.onTopHandleMousedown(evt); |  | ||||||
| 			this.onRightHandleMousedown(evt); |  | ||||||
| 		}, |  | ||||||
| 
 |  | ||||||
| 		// 右下ハンドル掴み時 |  | ||||||
| 		onBottomRightHandleMousedown(evt) { |  | ||||||
| 			this.onBottomHandleMousedown(evt); |  | ||||||
| 			this.onRightHandleMousedown(evt); |  | ||||||
| 		}, |  | ||||||
| 
 |  | ||||||
| 		// 左下ハンドル掴み時 |  | ||||||
| 		onBottomLeftHandleMousedown(evt) { |  | ||||||
| 			this.onBottomHandleMousedown(evt); |  | ||||||
| 			this.onLeftHandleMousedown(evt); |  | ||||||
| 		}, |  | ||||||
| 
 |  | ||||||
| 		// 高さを適用 |  | ||||||
| 		applyTransformHeight(height) { |  | ||||||
| 			if (height > window.innerHeight) height = window.innerHeight; |  | ||||||
| 			(this.$el as any).style.height = height + 'px'; |  | ||||||
| 		}, |  | ||||||
| 
 |  | ||||||
| 		// 幅を適用 |  | ||||||
| 		applyTransformWidth(width) { |  | ||||||
| 			if (width > window.innerWidth) width = window.innerWidth; |  | ||||||
| 			(this.$el as any).style.width = width + 'px'; |  | ||||||
| 		}, |  | ||||||
| 
 |  | ||||||
| 		// Y座標を適用 |  | ||||||
| 		applyTransformTop(top) { |  | ||||||
| 			(this.$el as any).style.top = top + 'px'; |  | ||||||
| 		}, |  | ||||||
| 
 |  | ||||||
| 		// X座標を適用 |  | ||||||
| 		applyTransformLeft(left) { |  | ||||||
| 			(this.$el as any).style.left = left + 'px'; |  | ||||||
| 		}, |  | ||||||
| 
 |  | ||||||
| 		onBrowserResize() { |  | ||||||
| 			const main = this.$el as any; |  | ||||||
| 			const position = main.getBoundingClientRect(); |  | ||||||
| 			const browserWidth = window.innerWidth; |  | ||||||
| 			const browserHeight = window.innerHeight; |  | ||||||
| 			const windowWidth = main.offsetWidth; |  | ||||||
| 			const windowHeight = main.offsetHeight; |  | ||||||
| 			if (position.left < 0) main.style.left = 0; // 左はみ出し |  | ||||||
| 			if (position.top + windowHeight > browserHeight) main.style.top = browserHeight - windowHeight + 'px'; // 下はみ出し |  | ||||||
| 			if (position.left + windowWidth > browserWidth) main.style.left = browserWidth - windowWidth + 'px'; // 右はみ出し |  | ||||||
| 			if (position.top < 0) main.style.top = 0; // 上はみ出し |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| }); | }); | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue