Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Dinamically reposition buttons on image using Sveltekit and tailwind

I have created an html map by declaring an array

<script>
  let areas = [
    { shape: 'rect', left: '4.94%', top: '60.55%', width: '7.28%', height: '22.78%', title: 'EVK30-200', id: 1 },
    { shape: 'rect', left: '19%', top: '60.72%', width: '6.97%', height: '22.45%', title: 'EVK30-200', id: 2 },
    { shape: 'rect', left: '32.81%', top: '60.72%', width: '7.09%', height: '22.45%', title: 'EVK30-200', id: 3 },
    { shape: 'rect', left: '46.61%', top: '60.72%', width: '6.97%', height: '22.61%', title: 'EVK30-200', id: 4 },
    { shape: 'rect', left: '74.48%', top: '60.89%', width: '6.84%', height: '22.45%', title: 'EVK30-200', id: 5 },
    { shape: 'rect', left: '18.37%', top: '25.46%', width: '3.17%', height: '15.58%', title: 'EVK14-40-T', id: 6 },
    { shape: 'rect', left: '25.4%', top: '25.96%', width: '1.9%', height: '11.31%', title: 'EVK10-30-T', id: 7 },
    { shape: 'rect', left: '31.6%', top: '26.05%', width: '2.09%', height: '11.39%', title: 'EVK10-30-T', id: 8 },
    { shape: 'rect', left: '37.94%', top: '26.13%', width: '2.22%', height: '11.47%', title: 'EVK10-30-T', id: 9 },
    { shape: 'circle', left: '44.97%', top: '38.69%', width: '3.1%', height: '4.44%', title: 'screw_1', id: 10, isScrew: true },
    { shape: 'circle', left: '53.7%', top: '36.18%', width: '3.36%', height: '3.43%', title: 'screw_2', id: 11, isScrew: true },
  ];
<script/>

and I calculate the coordinates in an onMount() function. In that istance, I also create a button for each area calculated:

<script>
  onMount(() => {
    const container = document.querySelector('.map-container');

    areas.forEach(area => {
      const coords = area.coords.split(',').map(coord => parseInt(coord.trim()));

      const wrapper = document.createElement('div');
      wrapper.classList.add('tooltip');
      wrapper.classList.add('absolute', 'group');
      wrapper.setAttribute('data-tip', area.title);

      const button = document.createElement('button');
      button.classList.add('btn');
      button.classList.add('variant-ghost', 'rounded-none', 'pointer-events-auto', 'group-hover:block', 'hidden', 'w-full', 'h-full');
      button.addEventListener('click', () => passData(area));
      wrapper.appendChild(button);

      wrapper.style.left = area.left;
      wrapper.style.top = area.top;
      wrapper.style.width = area.width;
      wrapper.style.height = area.height;

      if (area.shape === 'circle') {
        wrapper.style.borderRadius = '50%';
        button.classList.remove('rounded-none');
      }

      container.appendChild(wrapper);

      // Recalculate map coord every 500ms
      ImageMap('img[usemap]', 500);
    });
  });
<script/>

I also styled the .map-container as relative.
At the end, I render everything using a {#each} block:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

<div class="flex">
  <div class="map-container">
    <img src="../src/images/pdu-kitting-step.png" usemap="#image-map" id="map-image" alt="PDU Kitting" width="1579px" height="1194px" />
    <map name="image-map">
      {#each areas as area}
        <area shape={area.shape} coords={area.coords} href={area.href} alt={area.alt} />
      {/each}
    </map>
  </div>
  <div class="ml-16 flex-1">
    <SideData />
  </div>
</div>
 

The issue is that, if I resize the viewport or the image, the positions of the buttons are not aligned with the map.
Is it possible to fix that?

>Solution :

onMount only runs once, if you need to react to layout changes, use a ResizeObserver.

Instead of creating elements in the script, use the HTML template language. You can still calculate intermediate state as necessary in the script; if the base data can change as well, use a reactive statement in addition to the observer to trigger updates/calculations.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading