Skip to content
Snippets Groups Projects
VizTitle.vue 4.69 KiB
Newer Older
  • Learn to ignore specific revisions
  •   <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;
    }