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:
<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?