Skip to content

Commit 9a79091

Browse files
committed
Falling snow/ash effect working for about me page
1 parent e76bc79 commit 9a79091

File tree

5 files changed

+224
-98
lines changed

5 files changed

+224
-98
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<template>
2+
<div class="particle-container" ref="container"></div>
3+
</template>
4+
5+
<script>
6+
export default {
7+
mounted() {
8+
this.particles = [];
9+
this.$nextTick(() => {
10+
// Ensures DOM is fully rendered before accessing the container
11+
this.createParticles();
12+
this.animateParticles();
13+
});
14+
},
15+
methods: {
16+
createParticles() {
17+
for (let i = 0; i < 50; i++) {
18+
this.addParticle();
19+
}
20+
},
21+
addParticle() {
22+
const container = this.$refs.container;
23+
if (!container) return; // Prevents error if container isn't available
24+
25+
const particle = document.createElement('div');
26+
particle.className = 'particle';
27+
container.appendChild(particle);
28+
29+
const size = Math.random() * 5 + 2; // Random size between 2px and 7px
30+
const x = Math.random() * container.clientWidth;
31+
const y = -size;
32+
33+
particle.style.width = `${size}px`;
34+
particle.style.height = `${size}px`;
35+
particle.style.left = `${x}px`;
36+
particle.style.top = `${y}px`;
37+
38+
this.particles.push({ element: particle, x, y, size, velocityY: Math.random() * 2 + 1 });
39+
},
40+
animateParticles() {
41+
const container = this.$refs.container;
42+
if (!container) return; // Prevents error if container isn't available
43+
44+
this.particles.forEach(particle => {
45+
particle.y += particle.velocityY;
46+
particle.element.style.top = `${particle.y}px`;
47+
48+
if (particle.y > container.clientHeight) {
49+
// Reset particle to the top
50+
particle.y = -particle.size;
51+
particle.x = Math.random() * container.clientWidth;
52+
particle.element.style.left = `${particle.x}px`;
53+
}
54+
});
55+
56+
// Bind 'this' to the method to ensure it has the correct context
57+
requestAnimationFrame(this.animateParticles.bind(this));
58+
}
59+
}
60+
}
61+
</script>
62+
63+
<style>
64+
.particle-container {
65+
position: fixed;
66+
top: 0;
67+
left: 0;
68+
width: 100%;
69+
height: 100vh;
70+
overflow: hidden;
71+
pointer-events: none;
72+
z-index: 1;
73+
}
74+
75+
.particle {
76+
position: absolute;
77+
background-color: rgba(255, 255, 255, 0.8);
78+
border-radius: 50%;
79+
pointer-events: none;
80+
}
81+
</style>
Lines changed: 121 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,132 @@
1+
/* eslint-disable */
2+
13
<template>
2-
<div class="fullpage-container" @wheel="handleScroll">
3-
<div
4-
class="section"
5-
v-for="(section, index) in sections"
6-
:key="section.id"
7-
:ref="`section-${index}`"
8-
>
9-
<h2>{{ section.title }}</h2>
10-
<p>{{ section.content }}</p>
11-
</div>
12-
<div class="scroll-indicator" v-if="showIndicator">
13-
<button v-for="(section, index) in sections" :key="index" @click="scrollToSection(index)">
14-
{{ section.title }}
15-
</button>
16-
</div>
4+
<div class="fullpage-container" @wheel="handleScroll">
5+
<div
6+
class="section"
7+
v-for="(section, index) in sections"
8+
:key="section.id"
9+
:ref="`section-${index}`"
10+
:class="`section-${index}`"
11+
>
12+
<h2 class="content">{{ section.title }}</h2>
13+
<p class="content">{{ section.content }}</p>
14+
</div>
15+
<div class="scroll-indicator" v-if="showIndicator">
16+
<button v-for="(section, index) in sections" :key="index" @click="scrollToSection(index)">
17+
{{ section.title }}
18+
</button>
1719
</div>
18-
</template>
19-
20-
<script>
21-
export default {
22-
props: {
23-
sections: {
24-
type: Array,
25-
required: true
26-
},
27-
showIndicator: {
28-
type: Boolean,
29-
default: true
20+
</div>
21+
</template>
22+
23+
<script>
24+
import AshEffect from './AshEffect.vue';
25+
26+
export default {
27+
components: {
28+
},
29+
props: {
30+
sections: {
31+
type: Array,
32+
required: true
33+
},
34+
showIndicator: {
35+
type: Boolean,
36+
default: true
37+
}
38+
},
39+
data() {
40+
return {
41+
activeSection: 0,
42+
isScrolling: false,
43+
};
44+
},
45+
methods: {
46+
scrollToSection(index) {
47+
const section = this.$refs[`section-${index}`][0];
48+
if (section) {
49+
section.scrollIntoView({ behavior: 'smooth' });
50+
51+
// Set a delay after the animation to prevent accepting new inputs too soon
52+
setTimeout(() => {
53+
this.isScrolling = false;
54+
}, 1200); // Delay for accepting new scroll inputs
3055
}
3156
},
32-
data() {
33-
return {
34-
activeSection: 0,
35-
isScrolling: false,
36-
};
57+
handleScroll(event) {
58+
if (this.isScrolling) return;
59+
60+
this.isScrolling = true;
61+
62+
const direction = event.deltaY > 0 ? 1 : -1;
63+
this.activeSection += direction;
64+
65+
if (this.activeSection < 0) {
66+
this.activeSection = 0;
67+
} else if (this.activeSection >= this.sections.length) {
68+
this.activeSection = this.sections.length - 1;
69+
}
70+
setTimeout(() => {
71+
this.scrollToSection(this.activeSection);
72+
}, 100);
73+
74+
},
75+
computeGradient(index, totalSections) {
76+
const step = 255 / (totalSections - 1);
77+
const rgbValue = Math.round(step * index);
78+
return `linear-gradient(rgb(${rgbValue}, ${rgbValue}, ${rgbValue}), rgb(${rgbValue + step}, ${rgbValue + step}, ${rgbValue + step}))`;
3779
},
38-
methods: {
39-
scrollToSection(index) {
80+
applyGradients() {
81+
this.sections.forEach((_, index) => {
4082
const section = this.$refs[`section-${index}`][0];
4183
if (section) {
42-
section.scrollIntoView({ behavior: 'smooth' });
43-
44-
// Set a delay after the animation to prevent accepting new inputs too soon
45-
setTimeout(() => {
46-
this.isScrolling = false;
47-
}, 1200); // Delay for accepting new scroll inputs
48-
}
49-
},
50-
handleScroll(event) {
51-
if (this.isScrolling) return;
52-
53-
this.isScrolling = true;
54-
55-
const direction = event.deltaY > 0 ? 1 : -1;
56-
this.activeSection += direction;
57-
58-
if (this.activeSection < 0) {
59-
this.activeSection = 0;
60-
} else if (this.activeSection >= this.sections.length) {
61-
this.activeSection = this.sections.length - 1;
84+
section.style.backgroundImage = this.computeGradient(index, this.sections.length);
6285
}
63-
setTimeout(() => {
64-
this.scrollToSection(this.activeSection);
65-
}, 100);
66-
67-
}
68-
},
69-
mounted() {
70-
this.$nextTick(() => {
71-
this.scrollToSection(this.activeSection);
7286
});
7387
}
74-
};
75-
</script>
76-
77-
<style scoped>
78-
.fullpage-container {
79-
overflow: hidden;
80-
height: 100vh;
81-
position: relative;
82-
}
83-
84-
.section {
85-
height: 100vh;
86-
display: flex;
87-
align-items: center;
88-
justify-content: center;
89-
background-color: lightgray;
90-
border-bottom: 1px solid #ccc;
91-
}
92-
93-
.scroll-indicator {
94-
position: fixed;
95-
right: 10px;
96-
top: 50%;
97-
transform: translateY(-50%);
98-
display: flex;
99-
flex-direction: column;
100-
}
101-
102-
.scroll-indicator button {
103-
margin-bottom: 10px;
88+
},
89+
mounted() {
90+
this.$nextTick(() => {
91+
this.applyGradients();
92+
this.scrollToSection(this.activeSection);
93+
});
10494
}
105-
</style>
106-
95+
};
96+
</script>
97+
98+
<style scoped>
99+
.fullpage-container {
100+
overflow: hidden;
101+
height: 100vh;
102+
position: relative;
103+
}
104+
105+
.section {
106+
height: 100vh;
107+
display: flex;
108+
align-items: center;
109+
justify-content: center;
110+
}
111+
112+
.section:nth-child(1) .content {
113+
color: white;
114+
}
115+
116+
.content {
117+
z-index: 2;
118+
}
119+
120+
.scroll-indicator {
121+
position: fixed;
122+
right: 10px;
123+
top: 50%;
124+
transform: translateY(-50%);
125+
display: flex;
126+
flex-direction: column;
127+
}
128+
129+
.scroll-indicator button {
130+
margin-bottom: 10px;
131+
}
132+
</style>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<template>
2+
3+
4+
</template>
5+
6+
<script>
7+
8+
</script>
9+

src/components/SidebarComponents/SideBar.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export default {
134134
.sidebar {
135135
height: 100%;
136136
position: fixed;
137-
z-index: 1;
137+
z-index: 4;
138138
top: 0;
139139
left: 0;
140140
overflow-x: hidden;

src/views/AboutMe.vue

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
<template>
1+
<template class="page">
2+
<AshEffect />
23
<div>
34
<FullPage :sections="sections" :showIndicator="true" />
45
</div>
56
</template>
67

78
<script>
89
import FullPage from '../components/AboutMeComponents/FullPage.vue';
10+
import AshEffect from '../components/AboutMeComponents/AshEffect.vue';
911
1012
export default {
1113
components: {
12-
FullPage
14+
FullPage,
15+
AshEffect,
1316
},
1417
data() {
1518
return {
@@ -23,3 +26,10 @@ export default {
2326
}
2427
};
2528
</script>
29+
30+
<style>
31+
.page{
32+
33+
}
34+
35+
</style>

0 commit comments

Comments
 (0)