-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
250 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
--- | ||
outline: [2,3] | ||
--- | ||
|
||
# useFullScreen | ||
|
||
这是一个全屏的hook,可以快速将一个元素全屏显示,并且支持了iframe。 | ||
|
||
## 源文件 | ||
|
||
[useFullScreen.ts](https://github.com/shiouhoo/hooui/blob/main/src/hooks/useFullScreen.ts) | ||
|
||
## 示例 | ||
|
||
### 基本使用 | ||
|
||
:::demo | ||
|
||
```vue | ||
<script setup lang="ts"> | ||
import { useFullScreen } from '../../src/hooks'; | ||
const dom = ref<HTMLElement>(); | ||
const { isFull } = useFullScreen(dom as Ref<HTMLElement>); | ||
function handleClick() { | ||
isFull.value = !isFull.value; | ||
} | ||
</script> | ||
<template> | ||
<div ref="dom" class="h-100% flex flex-col bg-#f5f5f5 p-20px" border="1px solid red"> | ||
<a-button class="w-180px" type="primary" @click="handleClick">{{isFull?"退出全屏":"全屏" }}</a-button> | ||
</div> | ||
</template> | ||
``` | ||
::: | ||
|
||
### 局域内全屏 | ||
|
||
将元素在他的祖先容器中全屏显示,祖先元素会被修改为relative且无论中间节点是否有定位。 | ||
|
||
:::demo | ||
|
||
```vue | ||
<script setup lang="ts"> | ||
import { useFullScreen } from '../../src/hooks'; | ||
const dom = ref<HTMLElement>(); | ||
/** 局域内全屏 */ | ||
const boxDom = ref<HTMLElement>(); | ||
const { isFull: isFull2 } = useFullScreen(boxDom as Ref<HTMLElement>, dom as Ref<HTMLElement>); | ||
function handleClick2() { | ||
isFull2.value = !isFull2.value; | ||
} | ||
</script> | ||
<template> | ||
<div ref="dom" class="h-300px flex flex-col bg-#f5f5f5 p-20px" border="1px solid red"> | ||
<div ref="boxDom" class="w-30% h-30% flex flex-col mt-20px bg-#999" border="1px solid red"> | ||
<a-button class="w-180px" type="primary" @click="handleClick2">{{isFull2?"退出全屏":"局域内全屏" }}</a-button> | ||
</div> | ||
</div> | ||
</template> | ||
``` | ||
::: | ||
|
||
## props 参数 | ||
|
||
<script setup lang="ts"> | ||
|
||
const data = [ | ||
{ | ||
name: '第一个参数', | ||
desc: '要全屏的节点', | ||
type: 'Ref<HTMLElement>| string | HTMLElement', | ||
defaultValue: '-', | ||
}, | ||
{ | ||
name: '第二个参数', | ||
desc: '全屏容器,将目标节点在此容器上全屏,不填默认为window', | ||
type: 'Ref<HTMLElement>| string | HTMLElement | Window ', | ||
defaultValue: 'window', | ||
}, | ||
]; | ||
|
||
const data2 = [ | ||
{ | ||
name: 'isFull', | ||
desc: '标识是否全屏', | ||
type: 'Ref<boolean>', | ||
defaultValue: '-', | ||
}, | ||
]; | ||
|
||
</script> | ||
|
||
<ParamsTable :data="data"></ParamsTable> | ||
|
||
## 返回值 | ||
|
||
<ParamsTable :data="data2"></ParamsTable> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"name": "hooui", | ||
"version": "0.0.1", | ||
"version": "1.0.0", | ||
"private": true, | ||
"type": "module", | ||
"scripts": { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<script setup lang="ts"> | ||
import { useFullScreen } from '../hooks'; | ||
const dom = ref<HTMLElement>(); | ||
const { isFull } = useFullScreen(dom as Ref<HTMLElement>); | ||
function handleClick() { | ||
isFull.value = !isFull.value; | ||
} | ||
/** 局域内全屏 */ | ||
const boxDom = ref<HTMLElement>(); | ||
const { isFull: isFull2 } = useFullScreen(boxDom as Ref<HTMLElement>, dom as Ref<HTMLElement>); | ||
function handleClick2() { | ||
isFull2.value = !isFull2.value; | ||
} | ||
</script> | ||
<template> | ||
<div ref="dom" class="h-100% flex flex-col bg-#f5f5f5 p-20px" border="1px solid red"> | ||
<a-button class="w-180px" type="primary" @click="handleClick">{{isFull?"退出全屏":"全屏" }}</a-button> | ||
<div class="w-100% h-100%"> | ||
<div ref="boxDom" class="w-30% h-30% flex flex-col mt-20px bg-#999" border="1px solid red"> | ||
<a-button class="w-180px" type="primary" @click="handleClick2">{{isFull2?"退出全屏":"局域内全屏" }}</a-button> | ||
</div> | ||
|
||
</div> | ||
</div> | ||
</template> | ||
|
||
<style scoped lang="less"> | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,112 @@ | ||
import { onMounted, type Ref } from 'vue'; | ||
import { ref, watch, isRef, nextTick, type Ref } from 'vue'; | ||
|
||
const frameStyle: string[] = []; | ||
function getDom(target: Ref<HTMLElement>| string | HTMLElement): HTMLElement { | ||
if (isRef(target)) { | ||
return target.value; | ||
}else if(typeof target === 'string') { | ||
if(!document.querySelector(target)) { | ||
console.error(`useTabScroll: 节点目标错误,没有找到${target}的元素`); | ||
} | ||
return document.querySelector(target)!; | ||
}else { | ||
return target; | ||
} | ||
} | ||
|
||
/** | ||
* | ||
* @param target 被全屏的元素 | ||
* @param fullDom 全屏的容器 | ||
* @returns | ||
*/ | ||
export function useFullScreen( | ||
target: Ref<HTMLElement>| string | HTMLElement, | ||
fullDom: Ref<HTMLElement>| string | HTMLElement | Window = window | ||
) { | ||
const logStyle: Record<string, any> = {}; | ||
let targetParent: HTMLElement; | ||
const frameStyleMap = new WeakMap<HTMLElement, string>(); | ||
const isFull = ref(false); | ||
|
||
export function useFullScreen(target: Ref<HTMLElement>) { | ||
let targetStyle: string = ''; | ||
onMounted(()=>{ | ||
targetStyle = target.value.getAttribute('style') || ''; | ||
}); | ||
watch(isFull, (val)=>{ | ||
nextTick(()=>{ | ||
if(val) { | ||
fullScreen(); | ||
}else{ | ||
reset(); | ||
} | ||
}); | ||
}, { immediate: true }); | ||
function fullScreen() { | ||
target.value.setAttribute('style', 'position: fixed; top: 0; left: 0; width: 100%; height: 100%;'); | ||
const _fulldom = getDom(fullDom as string); | ||
const _targetdom = getDom(target); | ||
if(!_targetdom) { | ||
return; | ||
} | ||
logStyle.target = getDom(target).getAttribute('style') || ''; | ||
if(_fulldom instanceof Window) { | ||
childFullWindow(_targetdom); | ||
}else{ | ||
targetParent = _targetdom.parentElement!; | ||
childFullParent(_targetdom, _fulldom); | ||
} | ||
} | ||
function reset() { | ||
document.body.setAttribute('style', logStyle.body || ''); | ||
getDom(target).setAttribute('style', logStyle.target || ''); | ||
if(!(getDom(fullDom as string) instanceof Window)) { | ||
getDom(fullDom as string)?.setAttribute('style', logStyle.fulldom); | ||
} | ||
if(targetParent) { | ||
targetParent.appendChild(getDom(target)); | ||
} | ||
let w: Window = window; | ||
while(w.parent !== w) { | ||
for(const i of Array.from(w.parent.document.querySelectorAll('iframe'))) { | ||
if(i.contentWindow === w) { | ||
frameStyle.push(i.getAttribute('style') || ''); | ||
i.setAttribute('style', 'position: fixed; top: 0; left: 0; width: 100%; height: 100%;'); | ||
i?.setAttribute('style', frameStyleMap.get(i) || ''); | ||
break; | ||
} | ||
} | ||
w = w.parent; | ||
} | ||
} | ||
function reset() { | ||
target.value.setAttribute('style', targetStyle); | ||
|
||
function childFullWindow(target: HTMLElement) { | ||
logStyle.body = document.body.getAttribute('style') || ''; | ||
document.body.setAttribute('style', 'overflow: hidden;width: 100%;height: 100%;'); | ||
target.setAttribute('style', 'position: fixed; top: 0; left: 0; width: 100%; height: 100%;margin:0;z-index: 99999;'); | ||
let w: Window = window; | ||
while(w.parent !== w) { | ||
for(const i of Array.from(w.parent.document.querySelectorAll('iframe'))) { | ||
if(i.contentWindow === w) { | ||
i.setAttribute('style', frameStyle.shift() || ''); | ||
frameStyleMap.set(i, i.getAttribute('style') || ''); | ||
i?.setAttribute('style', 'position: fixed; top: 0; left: 0; width: 100%; height: 100%;margin: 0;z-index: 99999;'); | ||
break; | ||
} | ||
} | ||
w = w.parent; | ||
} | ||
} | ||
return { fullScreen, reset }; | ||
|
||
function childFullParent(target: HTMLElement, parent: HTMLElement | Window) { | ||
let _fulldom = getDom(parent as HTMLElement); | ||
let w: Window = window; | ||
while(!_fulldom && w.parent !== w) { | ||
w = w.parent; | ||
_fulldom = getDom(parent as HTMLElement); | ||
} | ||
if(!_fulldom) { | ||
console.error('useFullScreen: 找不到全屏容器'); | ||
return; | ||
} | ||
logStyle.fulldom = _fulldom.getAttribute('style'); | ||
_fulldom.setAttribute('style', 'position: relative'); | ||
// 将目标元素放入容器节点中 | ||
target.setAttribute('style', 'position: absolute; top: 0; left: 0; width: 100%; height: 100%;margin:0;z-index: 99999;'); | ||
_fulldom.appendChild(target); | ||
|
||
} | ||
return { isFull }; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters