Skip to content
Snippets Groups Projects
VizTitle.vue 4.69 KiB
Newer Older
  <header id="grid-container">
    <div id="image-container">
Cee Nell's avatar
Cee Nell committed
        ref="heroImage"
Cee Nell's avatar
Cee Nell committed
        :class="{ mobile: mobileView }"
Cee Nell's avatar
Cee Nell committed
        src="@/assets/images/full-color_no-circle_strong-fade.png"
        alt="Social vulnerability and water insecurity"
Cee Nell's avatar
Cee Nell committed
        @load="onImageLoad"
Cee Nell's avatar
Cee Nell committed
      />
      <img
        ref="bwHeroImage"
        id="bw-title-image"
        :class="{ mobile: mobileView }"
Cee Nell's avatar
Cee Nell committed
        src="@/assets/images/full-color_no-circle_strong-fade.png"
        alt="Social vulnerability and water insecurity (grayscale)"
      />
Cee Nell's avatar
Cee Nell committed
      <!-- Using svg masks with a circle shape to reveal color image where circles are on top of bw -->
Cee Nell's avatar
Cee Nell committed
      <svg ref="overlay" id="overlay" xmlns="http://www.w3.org/2000/svg">
        <defs>
          <mask id="circleMask">
            <rect width="100%" height="100%" fill="white" />
          </mask>
Cee Nell's avatar
Cee Nell committed
        </defs>
Cee Nell's avatar
Cee Nell committed
        <rect width="100%" height="100%" fill="transparent" mask="url(#circleMask)" />
Cee Nell's avatar
Cee Nell committed
      </svg>
    </div>
Cee Nell's avatar
Cee Nell committed
    <div id="text-container">
      <h1>Unequal access to water</h1>
      <h3>How societal factors shape vulnerability to water insecurity</h3>
    </div>
Cee Nell's avatar
Cee Nell committed
<script setup>
Cee Nell's avatar
Cee Nell committed
import { ref, onMounted, watch, nextTick } from 'vue';
Cee Nell's avatar
Cee Nell committed
import { isMobile } from 'mobile-device-detect';
Cee Nell's avatar
Cee Nell committed
const mobileView = ref(isMobile);
Cee Nell's avatar
Cee Nell committed
const heroImage = ref(null);
const bwHeroImage = ref(null);
Cee Nell's avatar
Cee Nell committed
const overlay = ref(null);

const updateSvgDimensions = () => {
  if (heroImage.value && bwHeroImage.value && overlay.value) {
    const { width, height } = heroImage.value.getBoundingClientRect();
Cee Nell's avatar
Cee Nell committed
    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';
Cee Nell's avatar
Cee Nell committed
  }
};

Cee Nell's avatar
Cee Nell committed
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();
};

Cee Nell's avatar
Cee Nell committed
onMounted(() => {
  updateSvgDimensions();
Cee Nell's avatar
Cee Nell committed
  addRandomCircles();
  window.addEventListener('resize', () => {
    updateSvgDimensions();
    addRandomCircles();
  });
Cee Nell's avatar
Cee Nell committed
});

watch(mobileView, () => {
  updateSvgDimensions();
});
<style lang="scss" scoped>
#grid-container {
  display: grid;
  grid-template-rows: auto auto;
Cee Nell's avatar
Cee Nell committed
  width: 100vw;
Cee Nell's avatar
Cee Nell committed

#image-container {
  position: relative;
  width: 100%;
}

#title-image,
#bw-title-image {
  width: 100%;
  display: block;
#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 */
Cee Nell's avatar
Cee Nell committed
}

Cee Nell's avatar
Cee Nell committed
#overlay {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none; /* Ensure the SVG overlay doesn't interfere with other interactions */
}

#text-container {
  width: 100%;
Cee Nell's avatar
Cee Nell committed
  background: rgba(0, 0, 0, 0.95);
  color: #1b1b1b;
  padding: 20px;
  box-sizing: border-box;
Cee Nell's avatar
Cee Nell committed
}
Cee Nell's avatar
Cee Nell committed

Cee Nell's avatar
Cee Nell committed
#image-container {
Cee Nell's avatar
Cee Nell committed
  color: #1b1b1b;
Cee Nell's avatar
Cee Nell committed
  background: #1b1b1b;
Cee Nell's avatar
Cee Nell committed
}
Cee Nell's avatar
Cee Nell committed

Cee Nell's avatar
Cee Nell committed
h1 {
  margin: -20px 20px;
  color: white;
  text-align: left; /* Optional: Align text to the left */
}
Cee Nell's avatar
Cee Nell committed

Cee Nell's avatar
Cee Nell committed
  margin: 20px 20px 0px 20px;
  color: white;
  text-align: left; /* Optional: Align text to the left */
Cee Nell's avatar
Cee Nell committed
}
Cee Nell's avatar
Cee Nell committed

Cee Nell's avatar
Cee Nell committed
svg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: auto;
}