Change the colour of a specific area of a picture onclick

Viewed 139

I am a beginner learning from a tutorial on how to change the colour of a selected area of a picture with a range of colour options.

I can figure out how to change one area, but unsure how to implement the other areas.

What I want to achieve is to click on the selected area, it highlights the border (CSS), then change the colour by using the colour options.

What is the best way to implement this? I'm I correct in thinking maybe a switch statement with onclick to select the specific area of the picture?

const overlay = document.getElementById("product-a");
var el = document.getElementsByClassName("color");
for (var i = 0; i < el.length; i++) {
  el[i].onclick = changeColor;
}

function changeColor(e) {
  let hex = e.target.getAttribute("data-hex");
  overlay.style.fill = hex;
}
body,
html {
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
}
#container {
  height: 200px;
  width: 200px;

}

#product-svg {
  position: relative;
  z-index: 2;
  background-size: 100%;
  background-repeat: no-repeat;
  background-position: 50%;
  mix-blend-mode: multiply;
}

path {
  fill: #CCCCCC;
}


#background-image {
  position: absolute;
  top: 0;
  left: 0;
  height: 200px;
  width: 200px;
  height: auto;
  z-index: 1;
}

.colors {
  display: flex;
  position: fixed;
  bottom: 2em;
  right: 2em;
  z-index: 3;
}

.color {
  height: 36px;
  width: 36px;
  margin-left: 0.5em;
  border-radius: 18px;
  box-shadow: 0px 4px 10px rgba(0,0,0,0.3);
  border: 2px solid #aaa;
  cursor: pointer;
}
<div id="container">

    <svg id="product-svg" viewBox="0 0 744 1074">
      <path id="product-a" d="M51 207.5L51 348L686 348L686 67L51 67L51 207.5Z" />
      <path id="product-b" d="M51 544.5L51 685L686 685L686 404L51 404L51 544.5Z" />
      <path id="product-c" d="M51 883.5L51 1024L686 1024L686 743L51 743L51 883.5Z" />
    </svg>
    <img id="background-image" src="boxes.jpg" alt="">
  </div>

  <div class="colors">
    <div class="color" style="background-color: #ff0000" data-hex="#ff0000"></div>
    <div class="color" style="background-color: #ffff33" data-hex="#ffff33"></div>
    <div class="color" style="background-color: #3399ff" data-hex="#3399ff"></div>
  </div>

4 Answers

Instead of assigning overlay variable to #product-a, try changing the overlay variable onclick of product box

let overlay;
document.querySelectorAll('#product-a, #product-b, #product-c').forEach(function(path) {
  path.onclick = chooseProduct;
})

function chooseProduct(e) {
  if (overlay) overlay.classList.remove('highlight')
  overlay = e.target
  overlay.classList.add('highlight')
}


var el = document.getElementsByClassName("color");
for (var i = 0; i < el.length; i++) {
  el[i].onclick = changeColor;
}

function changeColor(e) {
  let hex = e.target.getAttribute("data-hex");
  if (overlay) overlay.style.fill = hex;
}
body,
html {
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
}

#container {
  height: 200px;
  width: 200px;
}

#product-svg {
  position: relative;
  z-index: 2;
  background-size: 100%;
  background-repeat: no-repeat;
  background-position: 50%;
  mix-blend-mode: multiply;
}

path {
  fill: #CCCCCC;
}

#background-image {
  position: absolute;
  top: 0;
  left: 0;
  height: 200px;
  width: 200px;
  height: auto;
  z-index: 1;
}

.colors {
  display: flex;
  position: fixed;
  bottom: 2em;
  right: 2em;
  z-index: 3;
}

.color {
  height: 36px;
  width: 36px;
  margin-left: 0.5em;
  border-radius: 18px;
  box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.3);
  border: 2px solid #aaa;
  cursor: pointer;
}

.highlight {
  stroke-width: 10px;
  stroke: #000;
}
<div id="container">

  <svg id="product-svg" viewBox="0 0 744 1074">
      <path id="product-a" d="M51 207.5L51 348L686 348L686 67L51 67L51 207.5Z" />
      <path id="product-b" d="M51 544.5L51 685L686 685L686 404L51 404L51 544.5Z" />
      <path id="product-c" d="M51 883.5L51 1024L686 1024L686 743L51 743L51 883.5Z" />
    </svg>
  <img id="background-image" src="boxes.jpg" alt="">
</div>

<div class="colors">
  <div class="color" style="background-color: #ff0000" data-hex="#ff0000"></div>
  <div class="color" style="background-color: #ffff33" data-hex="#ffff33"></div>
  <div class="color" style="background-color: #3399ff" data-hex="#3399ff"></div>
</div>

You could try having a "select" function run when you click on one of the areas. This function would "highlight" the area (border-color), and save the id of the area in a variable.

Then when you click on the color swatches another function would run that will take the value previously saved id and select the HTML element based on that.

I recommend to have a class to indicate which one is selected and change that class on click.

var el = document.getElementsByClassName("color");
for (var i = 0; i < el.length; i++) {
  el[i].onclick = changeColor;
}

function changeColor(e) {
  let hex = e.target.getAttribute("data-hex");
  document.querySelector('.product.selected').style.fill = hex;
}

document.querySelectorAll('.product').forEach((el) => {
  el.addEventListener('click', (e) => {
    document.querySelectorAll('.product').forEach((el) => {
      el.classList.remove('selected')
    });
    e.currentTarget.classList.add('selected');
  });
});
body,
html {
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
}

#container {
  height: 200px;
  width: 200px;
}

#product-svg {
  position: relative;
  z-index: 2;
  background-size: 100%;
  background-repeat: no-repeat;
  background-position: 50%;
  mix-blend-mode: multiply;
}

path {
  fill: #CCCCCC;
}

#background-image {
  position: absolute;
  top: 0;
  left: 0;
  height: 200px;
  width: 200px;
  height: auto;
  z-index: 1;
}

.colors {
  display: flex;
  position: fixed;
  bottom: 2em;
  right: 2em;
  z-index: 3;
}

.color {
  height: 36px;
  width: 36px;
  margin-left: 0.5em;
  border-radius: 18px;
  box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.3);
  border: 2px solid #aaa;
  cursor: pointer;
}
<div id="container">

  <svg id="product-svg" viewBox="0 0 744 1074">
      <path class="product selected" id="product-a" d="M51 207.5L51 348L686 348L686 67L51 67L51 207.5Z" />
      <path class="product" id="product-b" d="M51 544.5L51 685L686 685L686 404L51 404L51 544.5Z" />
      <path class="product" id="product-c" d="M51 883.5L51 1024L686 1024L686 743L51 743L51 883.5Z" />
    </svg>
  <img id="background-image" src="boxes.jpg" alt="">
</div>

<div class="colors">
  <div class="color" style="background-color: #ff0000" data-hex="#ff0000"></div>
  <div class="color" style="background-color: #ffff33" data-hex="#ffff33"></div>
  <div class="color" style="background-color: #3399ff" data-hex="#3399ff"></div>
</div>

You can use querySelectorAll to select all <path> elements, iterate over it, to add an onclick function that adds temporary class to clicked overlay, and change its fill.

const overlays = document.querySelectorAll("#product-svg path"); //Select all path
var el = document.getElementsByClassName("color");
for (var i = 0; i < el.length; i++) {
  el[i].onclick = changeColor;
}

overlays.forEach(overlay => { //Iterate over all overlays
  overlay.onclick = () => {
    let id = this.id; // Get the id of clicked overlay
    overlays.forEach(overlay => {
      if (overlay.id != id) {
        overlay.classList.remove("active") //Remove the active class from other overlays
      }
    });
    overlay.classList.add("active") //Add active class to clicked overlay
  };
})

function changeColor(e) {
  let hex = e.target.getAttribute("data-hex");
  document.querySelector(".active").style.fill = hex; //change the color of element with active class
}
body,
html {
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
}

#container {
  height: 200px;
  width: 200px;
}

#product-svg {
  position: relative;
  z-index: 2;
  background-size: 100%;
  background-repeat: no-repeat;
  background-position: 50%;
  mix-blend-mode: multiply;
}

path {
  fill: #CCCCCC;
}

#background-image {
  position: absolute;
  top: 0;
  left: 0;
  height: 200px;
  width: 200px;
  height: auto;
  z-index: 1;
}

.colors {
  display: flex;
  position: fixed;
  bottom: 2em;
  right: 2em;
  z-index: 3;
}

.color {
  height: 36px;
  width: 36px;
  margin-left: 0.5em;
  border-radius: 18px;
  box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.3);
  border: 2px solid #aaa;
  cursor: pointer;
}
<div id="container">

  <svg id="product-svg" viewBox="0 0 744 1074">
      <path class="active" id="product-a" d="M51 207.5L51 348L686 348L686 67L51 67L51 207.5Z" />
      <path id="product-b" d="M51 544.5L51 685L686 685L686 404L51 404L51 544.5Z" />
      <path id="product-c" d="M51 883.5L51 1024L686 1024L686 743L51 743L51 883.5Z" />
    </svg>
  <img id="background-image" src="boxes.jpg" alt="">
</div>

<div class="colors">
  <div class="color" style="background-color: #ff0000" data-hex="#ff0000"></div>
  <div class="color" style="background-color: #ffff33" data-hex="#ffff33"></div>
  <div class="color" style="background-color: #3399ff" data-hex="#3399ff"></div>
</div>

Related