1

Hello this is my first attemp at creating a website and all this different languages seems a little overwhelming. I have some experience with programming guis and I have to say that the geometry manager of css seems incredibly weird to me.

Anyways my objective page is:

  • To display images in an ordered way, the images are svg.
  • To be able to reorganize the grid of images to make them bigger or smaller.
  • To put the images in an array that way editing the page will be easier.
  • To be able to put a link in an area of each image.

So far Ive accomplished all the points except the last one, I dont know how to put a clickable link in an area of each image.

Ive seen that I could use an area tag using a map but as far as I know the coordinates need to be absoulte values and cant be relative to the image, meaning that when the image changes size the area will be wrong.

I have also tried puting the link in the element of the svg file that I want directly, but doesnt work in the html file for some reason.

Any suggestions?

Here's what I have so far:

// Create images
var images_names = ["Images/article_0.svg", "Images/article_1.svg", "Images/article_2.svg", "Images/article_3.svg", "Images/article_4.svg",
  "Images/article_5.svg", "Images/article_6.svg", "Images/article_7.svg", "Images/article_8.svg"
]
var i;
for (i = 0; i < images_names.length; i++) {
  var img = document.createElement('img');
  img.src = images_names[i];
  document.getElementById('container').appendChild(img);
}
// Create Maps

// Geometry functions
function two() {
  var i;
  var elements = document.getElementsByTagName("img");
  for (i = 0; i < elements.length; i++) {
    elements[i].style.width = "49%"; // IE10
  }
}

function four() {
  var i;
  var elements = document.getElementsByTagName("img");
  for (i = 0; i < elements.length; i++) {
    elements[i].style.width = "24%"; // IE10
  }
}

function eight() {
  var i;
  var elements = document.getElementsByTagName("img");
  for (i = 0; i < elements.length; i++) {
    elements[i].style.width = "12%"; // IE10
  }
}

function sixteen() {
  var i;
  var elements = document.getElementsByTagName("img");
  for (i = 0; i < elements.length; i++) {
    elements[i].style.width = "6%"; // IE10
  }
}
* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: Arial, Helvetica, sans-serif;
}

img {
  width: 24%;
  top: 0;
}

.header {
  text-align: center;
  padding: 32px;
  position: sticky;
  top: 0;
  background-color: white;
}

#container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: space-between;
}
<!-- Header -->
<div class="header">
  <h1>TITLE</h1>
  <p>Click on the buttons to change the grid view.</p>
  <button onclick="two()">2</button>
  <button onclick="four()">4</button>
  <button onclick="eight()">8</button>
  <button onclick="sixteen()">16</button>
</div>

<div id="container">
</div>
David Thomas
  • 249,100
  • 51
  • 377
  • 410
  • Does this answer your question? [How to make a section of an image a clickable link](https://stackoverflow.com/questions/18560097/how-to-make-a-section-of-an-image-a-clickable-link) – gforce301 Aug 27 '20 at 14:49
  • Thanks for searching first! – gforce301 Aug 27 '20 at 14:50
  • I dont think it helps me since the solution they propose is to do a map using the area tag the problem I have is when the Images change sizes – Daniel Casasampera Aug 27 '20 at 14:56
  • So you have some random image of some random size and your asking how to make a "known" area of this randomly sized thing a link? How do you propose to locate this "clickable area" if you don't know the size of the image? Computer programs aren't very good at guessing. – gforce301 Aug 27 '20 at 15:00
  • 1
    I mean I dont know how to do it in this languages but the problem I am asking is mathematically well defined if that is what you are suggesting. If the coordinates of the area could be defined as (10%, 50%, 100%, 75%) then the area could be known by the program at any time, it just would need to recalculate the absolute coordinates of the area based on the current coordinates of the image. Another thing that Ive tried, which I say in the question, is to put the links in the svg element of the images that correspond with the area, but that doesnt work for some reason. – Daniel Casasampera Aug 27 '20 at 15:06
  • Linking this question: https://stackoverflow.com/questions/43611478/zoom-on-an-area-of-a-image-map – ControlAltDel Aug 27 '20 at 19:36

1 Answers1

0

A bit more detail in the question would have been very helpful.

However, based on the given description, I have tried to create a working prototype for you. It will give you the control over each individual image coordinates and you can tweak the position as per your requirement relative to each image.

HTML (No Change)

<!-- Header -->
<div class="header">
    <h1>TITLE</h1>
    <p>Click on the buttons to change the grid view.</p>
    <button onclick="two()">2</button>
    <button onclick="four()">4</button>
    <button onclick="eight()">8</button>
    <button onclick="sixteen()">16</button>
</div>

<div id="container">
</div>

Javascript (Changed):

  1. Added a image container in the first for loop to isolate images from each others and get relative coordinates.

  2. Assigned usemap attribute to img tag with our dynamically generated image map names for each image as value.

  3. Created a function createMaps() which will:

    3.1. iterate through each image container and get the first child element i.e. img element.

    3.2. get each image's width and height, calculate the XY Coordinates for the clickable area and store it in xCord, yCord variables.

    3.3. use a radius variable to define the size of the clickable area which is in the circular shape.

    3.4. create a image map element inside each image container and assign them the same name as in point 2.

    3.5. create an area element inside the map element and set its shape to circle, and coordinates in the format (x-axis, y-axis, radius) using the calculated values in point 3.2.

    3.6. Invoke createMap() function after the entire page has been loaded to avoid getting width/height of the image as 0 if the image is delayed in loading.

    3.7. Invoke createMap() function inside every Geometry function to regenerate the maps with the resized images.

for (var i = 0; i < images_names.length; i++) {
    var imgcontainer = document.createElement("div");
    imgcontainer.setAttribute("class", "imgcontainer");
    document.getElementById('container').appendChild(imgcontainer);

    var img = document.createElement('img');
    img.src = images_names[i];
    img.setAttribute("usemap", `#imgmap${i}`);
    imgcontainer.appendChild(img);
}

window.onload = function() {
    createMaps();
}

// Create Maps
function createMaps() {
    var elem = document.getElementsByClassName("imgcontainer");
    for (var i = 0; i < elem.length; i++) {
        var img = elem[i].children[0];
        var xCord = img.width * 15 / 100;
        var yCord = img.height * 15 / 100;
        var radius = 10;

        var imap = document.createElement("map");
        imap.setAttribute("name", `imgmap${i}`);
        elem[i].appendChild(imap);

        var area = document.createElement("area");
        area.setAttribute("shape", `circle`);
        area.setAttribute("title", `Click me`);
        area.setAttribute("href", `javascript:alert(1);`);
        area.setAttribute("coords", `${xCord},${yCord},${radius}`);
        imap.appendChild(area);
    }
}

// Geometry functions
function two() {
    var i;
    var elements = document.getElementsByClassName("imgcontainer");
    for (i = 0; i < elements.length; i++) {
        elements[i].style.width = "49%"; // IE10
    }
    createMaps();
}

function four() {
    var i;
    var elements = document.getElementsByClassName("imgcontainer");
    for (i = 0; i < elements.length; i++) {
        elements[i].style.width = "24%"; // IE10
    }
    createMaps();
}

function eight() {
    var i;
    var elements = document.getElementsByClassName("imgcontainer");
    for (i = 0; i < elements.length; i++) {
        elements[i].style.width = "12%"; // IE10
    }
    createMaps();
}

function sixteen() {
    var i;
    var elements = document.getElementsByClassName("imgcontainer");
    for (i = 0; i < elements.length; i++) {
        elements[i].style.width = "6%"; // IE10
    }
    createMaps();
}

CSS (Changed):

  1. Added imgcontainer class and assigned the default width of 24% and set the position relative to maintain its normal position in order to match the coordinates assigned in image map.
  2. img element width set to 100% to occupy entire width of the container and maintain the aspect ratio.
* {
    box-sizing: border-box;
}

body {
    margin: 0;
    font-family: Arial, Helvetica, sans-serif;
}

.imgcontainer {
    width: 24%;
    position: relative;
}

img {
    width: 100%;
    top: 0;
}

.header {
    text-align: center;
    padding: 32px;
    position: sticky;
    top: 0;
    background-color: white;
}

#container {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
    align-content: space-between;
}

Check the working prototype here: https://jsfiddle.net/manask/3ujsrp71/. Just hover over each image and click when the cursor changes to pointer/hand.

Let me know if have any queries about the code/implementation.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Ciber.ai
  • 36
  • 6