Newer
Older
alt="Social vulnerability and water insecurity"
<img
ref="bwHeroImage"
id="bw-title-image"
:class="{ mobile: mobileView }"
alt="Social vulnerability and water insecurity (grayscale)"
/>
<!-- Using svg masks with a circle shape to reveal color image where circles are on top of bw -->
<svg ref="overlay" id="overlay" xmlns="http://www.w3.org/2000/svg">
<defs>
<mask id="circleMask">
<rect width="100%" height="100%" fill="white" />
</mask>
<rect width="100%" height="100%" fill="transparent" mask="url(#circleMask)" />
<div id="text-container">
<h1>Unequal access to water</h1>
<h3>How societal factors shape vulnerability to water insecurity</h3>
</div>
const overlay = ref(null);
const updateSvgDimensions = () => {
if (heroImage.value && bwHeroImage.value && overlay.value) {
const { width, height } = heroImage.value.getBoundingClientRect();
overlay.value.setAttribute('width', width);
overlay.value.setAttribute('height', height);
bwHeroImage.value.style.width = `${width}px`;
bwHeroImage.value.style.height = `${height}px`;
bwHeroImage.value.style.top = '0';
bwHeroImage.value.style.left = '0';
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
const addRandomCircles = () => {
nextTick(() => {
const mask = overlay.value.querySelector('#circleMask');
const svgWidth = overlay.value.clientWidth;
const svgHeight = overlay.value.clientHeight;
// Debugging output to check the dimensions
console.log('SVG Width:', svgWidth, 'SVG Height:', svgHeight);
if (svgWidth === 0 || svgHeight === 0) {
console.error('SVG dimensions are not set correctly.');
return;
}
// Clear existing circles
while (mask.lastChild) {
mask.removeChild(mask.lastChild);
}
// Re-add the white rectangle
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.setAttribute('width', '100%');
rect.setAttribute('height', '100%');
rect.setAttribute('fill', 'white');
mask.appendChild(rect);
const numberOfCircles = 30; // Number of random circles to add
for (let i = 0; i < numberOfCircles; i++) {
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
const cx = Math.random() * svgWidth;
const cy = Math.random() * svgHeight;
const r = Math.random() * (svgWidth / 10); // Adjust the maximum radius relative to the SVG width
circle.setAttribute('cx', cx);
circle.setAttribute('cy', cy);
circle.setAttribute('r', r);
circle.setAttribute('fill', 'black');
mask.appendChild(circle);
}
});
};
const onImageLoad = () => {
updateSvgDimensions();
addRandomCircles();
};
addRandomCircles();
window.addEventListener('resize', () => {
updateSvgDimensions();
addRandomCircles();
});
});
watch(mobileView, () => {
updateSvgDimensions();
});
<style lang="scss" scoped>
#grid-container {
display: grid;
#image-container {
position: relative;
width: 100%;
}
#title-image,
#bw-title-image {
width: 100%;
#bw-title-image {
filter: grayscale(100%);
position: absolute;
top: 0;
left: 0;
pointer-events: none; /* Ensure the grayscale image doesn't interfere with other interactions */
mask: url(#circleMask); /* Apply the SVG mask */
#overlay {
position: absolute;
top: 0;
left: 0;
pointer-events: none; /* Ensure the SVG overlay doesn't interfere with other interactions */
}
background: rgba(0, 0, 0, 0.95);
color: #1b1b1b;
padding: 20px;
h1 {
margin: -20px 20px;
color: white;
text-align: left; /* Optional: Align text to the left */
}
text-align: left; /* Optional: Align text to the left */
svg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: auto;
}