Skip to content

Commit

Permalink
feat: 更新useFullScreen;发布1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
shiouhoo committed Mar 3, 2024
1 parent 079918f commit 20fc0aa
Show file tree
Hide file tree
Showing 11 changed files with 250 additions and 22 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/static.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ name: hooui构建
on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]
# branches: ["main"]
tags:
- '*'

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
Expand Down
3 changes: 2 additions & 1 deletion .serverless/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ http {
root /code;
index index.html;
location / {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri /index.html;
}
location ~* /.(js|css|png|jpg|jpeg|gif|ico)$ {
location ~* .(js|css|png|jpg|jpeg|gif|ico|woff2)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri /index.html;
}
Expand Down
5 changes: 3 additions & 2 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import unocssCongfig from '../../uno.config';
export default defineConfig({
title: 'hooui',
base: '/hooui',
description: '这是一个常用的vue3组件库',
description: '这是一个vue3工具集',
markdown: {
config: (md) => {
md.use(demoblockPlugin);
Expand All @@ -29,7 +29,7 @@ export default defineConfig({
{ text: 'directive', link: '/directive/', activeMatch: '/directive' },
{ text: 'components', link: '/package/expandcontainer', activeMatch: '/package' },
{ text: '工具函数', link: '/utils/download', activeMatch: '/utils' },
{ text: 'hooks', link: '/hooks/useTabScroll', activeMatch: '/hooks' }
{ text: 'hooks', link: '/hooks/useFullScreen', activeMatch: '/hooks' }
],

sidebar: {
Expand Down Expand Up @@ -70,6 +70,7 @@ export default defineConfig({
{
text: 'hooks',
items: [
{ text: 'useFullScreen', link: '/hooks/useFullScreen' },
{ text: 'useTabScroll', link: '/hooks/useTabScroll' },
]
}
Expand Down
5 changes: 5 additions & 0 deletions docs/.vitepress/layout/AsideTop.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
<a-switch :checked="preferUnocss" @change="toggleUnocssAPI" />
</div>
</template>
<template #nav-bar-title-after>
<!-- <span class="pl-10px text-16px">v</span> -->
<div class="pl-20px text-14px text-[rgba(60,60,67)] font-400">{{ pkg.version }}</div>
</template>
</Layout>
</template>

Expand All @@ -14,6 +18,7 @@ import DefaultTheme from 'vitepress/theme';
import { preferUnocssKey, preferUnocss } from '../preferences';
import { Ref, computed } from 'vue';
import { useRoute } from 'vitepress';
import pkg from '../../../package.json';
const route = useRoute();
const show = computed(() =>
Expand Down
106 changes: 106 additions & 0 deletions docs/hooks/useFullScreen.md
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>

2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ features:
- title: 目的
details: 一切为了,不加班!不加班!不加班!不加班!不加班!不加班!不加班!不加班!不加班!
- title: 未完待续
details: 桃李待日开,荣华照当年( ̄︶ ̄)↗
details: 桃李待日开,荣华照当年 ( ̄︶ ̄)↗
---

2 changes: 1 addition & 1 deletion package.json
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": {
Expand Down
5 changes: 5 additions & 0 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import DemoCopy from './demo/DemoCopy.vue';
import DemoLoading from './demo/DemoLoading.vue';
import DemoBottomPopup from './demo/DemoBottomPopup.vue';
import DemoTabScroll from './demo/DemoTabScroll.vue';
import DemoFullScreen from './demo/DemoFullScreen.vue';
const selectedKeys = ref<string[]>(['Copy']);
Expand All @@ -21,6 +22,10 @@ const coms = shallowRef([
name: 'ExpandContainer',
component: DemoExpandContainer
},
{
name: 'FullScreen',
component: DemoFullScreen
},
{
name: 'Loading',
component: DemoLoading
Expand Down
36 changes: 36 additions & 0 deletions src/demo/DemoFullScreen.vue
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>
101 changes: 87 additions & 14 deletions src/hooks/useFullScreen.ts
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 };

}
3 changes: 1 addition & 2 deletions src/hooks/useTabScroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ function getDom(target: TabValue): HTMLElement {
}
// 获取元素距离滚动容器顶部的距离
function getOffsetTop(element: HTMLElement, parent: HTMLElement | Window) {
const pTop = parent instanceof Window ? 0 : parent.offsetTop;
return element.offsetTop - pTop;
return parent instanceof Window ? element.getBoundingClientRect().top - document.body.getBoundingClientRect().top : element.getBoundingClientRect().top - parent.getBoundingClientRect().top;
}

function debounce(func: ()=>void, wait:number) {
Expand Down

0 comments on commit 20fc0aa

Please sign in to comment.