Skip to content

Commit 5add3a3

Browse files
committed
Update: 主题模态框拖拽可变更
1 parent 4034bc6 commit 5add3a3

File tree

14 files changed

+585
-212
lines changed

14 files changed

+585
-212
lines changed

package/App.vue

Lines changed: 6 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,11 @@
11
<template>
22
<div
3-
class="fixed top-0 left-0 h-screen w-screen flex-center"
3+
class="fixed top-0 left-0 h-screen w-screen"
44
style="background-size: cover; background-position: center; background-repeat: no-repeat;"
55
:style="{ backgroundImage: `url(${ bgList[0] })` }"
66
>
7-
<slot name="homePage">
8-
<div class="w-80vw max-w-800px mb-12vh h-a flex-center flex-col py-10">
9-
<div
10-
class="relative w-60 h-60 max-w-80vw max-h-80vw"
11-
style="filter: drop-shadow(0 0 16px rgba(0,0,0,.36));"
12-
@click="$go(aboutMePath)"
13-
>
14-
<img class="w-full w-full rounded-sm cursor-pointer" :src="logo" alt=""/>
15-
</div>
16-
<div class="text-6 line-height-8 my-2 select-none">
17-
<strong class="text-white">{{ name }}</strong>
18-
</div>
19-
<div class="text-4 line-height-4 mb-2 select-none">
20-
<span class="text-gray-3">{{ motto }}</span>
21-
</div>
22-
<div
23-
v-if="socialLinks.length > 0"
24-
class="flex-center gap-2 flex-wrap rounded-full"
25-
>
26-
<div
27-
v-for="v in links"
28-
:key="v.link"
29-
class="h-10 w-10 line-height-10 rounded-full bg-transparent hover:bg-[rgba(255,255,255,.12)]"
30-
un-transition="colors duration-240 ease-in-out"
31-
un-text="center white 6"
32-
@click="$go(v.link, '_blank')"
33-
v-html="v.icon"
34-
/>
35-
</div>
36-
<div
37-
class="my-4 px-4 py-2 cursor-pointer"
38-
un-text="5.25 gray-4"
39-
un-border="~ solid 0.5 gray-4 rounded-2"
40-
un-hover="border-white text-white"
41-
un-transition="colors duration-300 ease"
42-
@click="$go('/learn/')"
43-
>
44-
OPEN BLOG ->
45-
</div>
46-
</div>
7+
<slot name="homepage">
8+
<NanoDefaultHomepage/>
479
</slot>
4810

4911
<NanoContainer v-if="!onlyShowIndex"/>
@@ -52,31 +14,13 @@
5214

5315
<script setup lang="ts">
5416
import NanoContainer from '@NanoUI/NanoContainer/index.vue';
17+
import NanoDefaultHomepage from '@NanoUI/NanoDefaultHomepage/index.vue';
5518
import { useData } from 'vitepress';
56-
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
57-
import { DefaultTheme } from 'vitepress/types/default-theme';
19+
import { onMounted, onUnmounted, ref, watch } from 'vue';
5820
import { controllerStore } from '@store/controller';
5921
6022
const { frontmatter, site } = useData();
61-
62-
// console.log(useData().site.value);
63-
64-
const { logo, socialLinks, backgrounds: bgList, motto, name, aboutMePath } = site.value.themeConfig;
65-
66-
const links = computed(() => {
67-
return site.value?.themeConfig.socialLinks?.map((v: DefaultTheme.SocialLink) => {
68-
let icon: string;
69-
if (typeof v.icon === 'string') {
70-
icon = `<span class="iconfont icon-nano-${ v.icon?.toLowerCase() }"/>`;
71-
} else {
72-
icon = v.icon?.svg;
73-
}
74-
return {
75-
...v,
76-
icon
77-
};
78-
}) || [];
79-
});
23+
const { backgrounds: bgList } = site.value.themeConfig;
8024
8125
const onlyShowIndex = ref<boolean>(false);
8226

package/components/NanoBody/index.vue

Lines changed: 54 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import NanoLeftActionBar from '@NanoUI/NanoLeftActionBar/index.vue';
2828
import NanoRightActionBar from '@NanoUI/NanoRightActionBar/index.vue';
2929
import { controllerStore } from '@store/controller';
30-
import { onMounted, ref, watch } from 'vue';
30+
import { nextTick, ref, watch } from 'vue';
3131
import { drag } from '../../utils/drag';
3232
import { contentLayoutStore } from '@store/contentLayout';
3333
import { debounce } from 'lodash-es';
@@ -67,49 +67,61 @@
6767
raw: number;
6868
};
6969
70-
onMounted(() => {
71-
if (container.value && leftSidebar.value && rightSidebar.value && leftActionBar.value && rightActionBar.value) {
72-
const originalData = (): OriginalDataType => {
73-
return {
74-
cw: container.value!.clientWidth,
75-
lsw: leftSidebar.value!.$el.clientWidth,
76-
rsw: rightSidebar.value!.$el.clientWidth,
77-
law: leftActionBar.value!.$el.clientWidth,
78-
raw: rightActionBar.value!.$el.clientWidth
79-
};
80-
};
81-
drag<OriginalDataType>({
82-
el: leftDraggableLine.value!,
83-
originalData,
84-
handlerFn: ({ x, originalData: { cw, law, lsw, rsw, raw } }) => {
85-
const newWidth = lsw + x;
86-
const otherElsWidth = law + raw + rsw;
87-
if (cw - otherElsWidth - 400 < newWidth) {
88-
return;
89-
}
90-
if (newWidth < 120) {
91-
return;
92-
}
93-
leftSidebarLayout.value = { width: newWidth / cw * 100 + '%' };
94-
}
95-
});
96-
drag<OriginalDataType>({
97-
el: rightDraggableLine.value!,
98-
originalData,
99-
handlerFn: ({ x, originalData: { cw, law, lsw, rsw, raw } }) => {
100-
const newWidth = rsw - x;
101-
const otherElsWidth = law + raw + lsw;
102-
if (cw - otherElsWidth - 400 < newWidth) {
103-
return;
70+
const originalData = (): OriginalDataType => {
71+
return {
72+
cw: container.value!.clientWidth,
73+
lsw: leftSidebar.value!.$el.clientWidth,
74+
rsw: rightSidebar.value!.$el.clientWidth,
75+
law: leftActionBar.value!.$el.clientWidth,
76+
raw: rightActionBar.value!.$el.clientWidth
77+
};
78+
};
79+
80+
watch(() => ctl.hideLeftSidebar, (val) => {
81+
nextTick().then(() => {
82+
if (!val) {
83+
const el = leftDraggableLine.value!;
84+
drag<OriginalDataType>({
85+
el,
86+
originalData,
87+
handlerFn: ({ x, originalData: { cw, law, lsw, rsw, raw } }) => {
88+
const newWidth = lsw + x;
89+
const otherElsWidth = law + raw + rsw;
90+
if (cw - otherElsWidth - 400 < newWidth) {
91+
return;
92+
}
93+
if (newWidth < 120) {
94+
return;
95+
}
96+
leftSidebarLayout.value = { width: newWidth / cw * 100 + '%' };
10497
}
105-
if (newWidth < 120) {
106-
return;
98+
});
99+
}
100+
});
101+
}, { immediate: true });
102+
103+
watch(() => ctl.hideRightSidebar, (val) => {
104+
nextTick().then(() => {
105+
if (!val) {
106+
const el = rightDraggableLine.value!;
107+
drag<OriginalDataType>({
108+
el,
109+
originalData,
110+
handlerFn: ({ x, originalData: { cw, law, lsw, rsw, raw } }) => {
111+
const newWidth = rsw - x;
112+
const otherElsWidth = law + raw + lsw;
113+
if (cw - otherElsWidth - 400 < newWidth) {
114+
return;
115+
}
116+
if (newWidth < 120) {
117+
return;
118+
}
119+
rightSidebarLayout.value = { width: newWidth / cw * 100 + '%' };
107120
}
108-
rightSidebarLayout.value = { width: newWidth / cw * 100 + '%' };
109-
}
110-
});
111-
}
112-
});
121+
});
122+
}
123+
});
124+
}, { immediate: true });
113125
</script>
114126

115127
<style scoped lang="scss">

package/components/NanoContainer/index.vue

Lines changed: 19 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
<template>
2-
<div
2+
<NanoModal
33
ref="container"
4-
class="nano-theme absolute"
5-
:style="{ ...containerLayoutStyle, ...animation }"
4+
v-model:fullscreen="ctl.fullscreen"
5+
v-model:layout="containerLayout"
6+
:drag-el="headerEl"
7+
:visible="visible"
8+
:width-range="[ '20vw', '100vw' ]"
9+
:height-range="[ '60vh', '100vh' ]"
10+
class="nano-theme"
611
>
712
<div v-show="!loading" class="relative w-full h-full flex flex-col">
813
<NanoHeader ref="header" @dblclick.self="ctl.fullscreen = !ctl.fullscreen"/>
@@ -14,7 +19,7 @@
1419
<NanoBackdrop/>
1520
<NanoNavModal/>
1621
<NanoSidebarDirModal/>
17-
</div>
22+
</NanoModal>
1823
</template>
1924

2025
<script setup lang="ts">
@@ -25,47 +30,28 @@
2530
import NanoBackdrop from '@NanoUI/NanoBackdrop/index.vue';
2631
import NanoNavModal from '@NanoUI/NanoNavModal/index.vue';
2732
import NanoSidebarDirModal from '@NanoUI/NanoSidebarDirModal/index.vue';
28-
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
33+
import NanoModal from '@NanoUI/NanoModal/index.vue';
34+
import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
2935
import { controllerStore } from '@store/controller';
30-
import { contentLayoutStore, getWidthFromString, LayoutBaseInfo } from '@store/contentLayout';
31-
import { drag } from '../../utils/drag';
32-
import { debounce } from 'lodash-es';
36+
import { contentLayoutStore } from '@store/contentLayout';
3337
3438
const ctl = controllerStore();
3539
const layout = contentLayoutStore();
3640
37-
const container = ref<HTMLElement | null>(null);
41+
const container = ref<InstanceType<typeof NanoModal> | null>(null);
3842
const header = ref<InstanceType<typeof NanoHeader> | null>();
3943
const resizeObserver = ref<ResizeObserver | null>(null);
4044
const loading = ref(true);
41-
const enableAnimation = ref(true);
45+
const visible = computed(() => !ctl.onlyFullscreen);
4246
43-
const animation = computed(() => {
44-
return enableAnimation.value ? {
45-
transition: 'top .12s, left .12s, width .12s, height .12s'
46-
} : {
47-
transition: 'width .12s, height .12s'
48-
};
47+
const headerEl = computed(() => header.value?.$el);
48+
const containerLayout = computed({
49+
get: () => layout.containerLayout,
50+
set: (value) => layout.setContainerLayout(value)
4951
});
5052
51-
const containerLayout = ref<LayoutBaseInfo>(layout.containerLayout);
52-
53-
const containerLayoutStyle = computed(() => {
54-
return !ctl.onlyFullscreen && !ctl.fullscreen ? containerLayout.value : {
55-
top: 0,
56-
left: 0,
57-
width: '100vw',
58-
height: '100vh'
59-
};
60-
});
61-
62-
watch(containerLayout, debounce((val) => {
63-
// console.log('containerLayout changed', val);
64-
layout.setContainerLayout(val);
65-
}, 200), { deep: true });
66-
6753
onMounted(() => {
68-
const containerEl = container.value!;
54+
const containerEl = container.value!.$el;
6955
resizeObserver.value = new ResizeObserver((entries: ResizeObserverEntry[]) => {
7056
for (const entry of entries) {
7157
const { target } = entry;
@@ -100,55 +86,7 @@
10086
});
10187
resizeObserver.value.observe(containerEl);
10288
103-
type OriginLayout = {
104-
isFullscreen: boolean;
105-
notFullScreenWidth: number;
106-
screenWidth: number;
107-
screenHeight: number;
108-
left: number;
109-
top: number;
110-
};
11189
112-
drag<OriginLayout>({
113-
el: header.value!.$el,
114-
originalData: () => {
115-
const { clientWidth, clientHeight } = document.documentElement;
116-
const { offsetLeft, offsetTop } = containerEl;
117-
const width = getWidthFromString(layout.container.changed?.width || layout.container.default?.width || '');
118-
return {
119-
isFullscreen: ctl.fullscreen,
120-
notFullScreenWidth: width,
121-
screenWidth: clientWidth,
122-
screenHeight: clientHeight,
123-
left: offsetLeft,
124-
top: offsetTop
125-
};
126-
},
127-
handlerFn: ({
128-
x,
129-
y,
130-
originalData: { isFullscreen, notFullScreenWidth, screenWidth, screenHeight, left, top },
131-
pointerWelt,
132-
initial
133-
}) => {
134-
let newLeft = left + x;
135-
const newTop = top + y;
136-
if (isFullscreen) {
137-
ctl.fullscreen = false;
138-
newLeft = initial.x - (initial.x / screenWidth) * notFullScreenWidth + x;
139-
}
140-
if (!pointerWelt.top && !pointerWelt.bottom && newTop > 0) {
141-
containerLayout.value.top = newTop / screenHeight * 100 + '%';
142-
} else {
143-
containerLayout.value.top = pointerWelt.bottom ? '98%' : '0';
144-
}
145-
if (!pointerWelt.left && !pointerWelt.right) {
146-
containerLayout.value.left = newLeft / screenWidth * 100 + '%';
147-
}
148-
},
149-
beforeFn: () => enableAnimation.value = false,
150-
afterFn: () => enableAnimation.value = true
151-
});
15290
});
15391
15492
onBeforeUnmount(() => {

0 commit comments

Comments
 (0)