Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change an image source on hover with SVGs?

I have divided sm image into five different triangles. I'm trying to change an image's src attribute value on hover, and show the hovered' image in the center square.

This is what I'm trying to do, but with SVGs: How to change an image source on hover?

.overlay {
  background-image: url('https://picsum.photos/id/118/1000/800');
  background-repeat: no-repeat;
  background-size: cover;
}

.overlay use {
  opacity: 0;
  transition: all 0.4s linear;
}

.overlay use:hover {
  opacity: 1;
}

.vr-head-tilt {
  position: relative;
}

.big img {
  width: 200px;
  height: 200px;
  object-fit: cover;
}

.overlay .vr-images1:hover~.big .default {
  opacity: 0;
}

.overlay .vr-images1:hover~.big>img:nth-child(1) {
  z-index: 5;
  opacity: 1;
}

.overlay .vr-images2:hover~.big>img:nth-child(2) {
  z-index: 5;
  opacity: 1;
}

.overlay .vr-images3:hover~.big>img:nth-child(3) {
  z-index: 5;
  opacity: 1;
}

.overlay .vr-images4:hover~.big>img:nth-child(4) {
  z-index: 5;
  opacity: 1;
}

.overlay .vr-images5:hover~.big>img:nth-child(5) {
  z-index: 5;
  opacity: 1;
}

.big {
  position: relative;
}

.big img {
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translate(-50%, 7%);
  opacity: 0;
  transition: .2s .1s ease-out;
}

.big .default {
  opacity: 1;
}
<svg class="overlay" viewBox="0 0 200 100">
            <defs>
                <clipPath id='clip-1'>
                <polygon points="0,100 100,100 0,50"/>
                </clipPath>
                <clipPath id='clip-2'>
                <polygon points="0,50 100,100 50,00 0,0"/>
                </clipPath>
                <clipPath id='clip-3'>
                <polygon points="100,100 50,00 150,0"/>
                </clipPath>
                <clipPath id='clip-4'>
                <polygon points="100,100 200,50 200,0 150,0"/>
                </clipPath>
                <clipPath id='clip-5'>
                <polygon points="100,100 200,100, 200,50"/>
                </clipPath>
                <image id="img" x="0" y="0" width="200" height="100" preserveAspectRatio="xMidYMid slice"
                xlink:href="https://picsum.photos/id/1/1000/800" />
            </defs>
            <use xlink:href="#img" class="vr-images1" clip-path="url(#clip-1)"/>
            <use xlink:href="#img" class="vr-images2" clip-path="url(#clip-2)"/>
            <use xlink:href="#img" class="vr-images3" clip-path="url(#clip-3)"/>
            <use xlink:href="#img" class="vr-images4" clip-path="url(#clip-4)"/>
            <use xlink:href="#img" class="vr-images5" clip-path="url(#clip-5)"/>
        </svg>
<div class="box"></div>
<div class='big'>
  <img src="https://i.ibb.co/rxX8VMq/left.png" class='default'>
  <img src="https://i.ibb.co/r77CrCC/topleft.png">
  <img src="https://i.ibb.co/CzRdRtp/top.png">
  <img src="https://i.ibb.co/L8cSs3p/topright.png">
  <img src="https://i.ibb.co/D1cjqfD/right.png">
</div>

When we hover on each polygon, the center image should change.

like image 956
Husna Avatar asked Jun 17 '19 05:06

Husna


People also ask

How do I hover an SVG image?

If you need to do hover effects in svg you shouldn't use <img> tags. Instead reference the svg with an <iframe>, <object> or <embed> tag. If you want to save a http GET request you can put the svg markup inline in the html document.

Can you change color of SVG on hover?

One way to change SVG colors on hover is to use CSS. You can add CSS to your HTML file or you can use an external CSS file. To add CSS to your HTML file, you will need to use the <style> tag. The <style> tag goes in the <head> section of your HTML file.

How can change IMG tag color in SVG?

Edit your SVG file, add fill="currentColor" to svg tag and make sure to remove any other fill property from the file. Note that currentColor is a keyword (not a fixed color in use). After that, you can change the color using CSS, by setting the color property of the element or from it's parent.

How do I customize SVG?

To edit an SVG image in Office for Android, tap to select the SVG you want to edit and the Graphics tab should appear on the ribbon. Styles - These are a set of predefined styles you can add to quickly change the look of your SVG file.


2 Answers

You could simply use javascript and listen for the mouseenter event on your <use> elements:

const sources = [
  "rxX8VMq/left.png",
  "r77CrCC/topleft.png",
  "CzRdRtp/top.png",
  "L8cSs3p/topright.png",
  "D1cjqfD/right.png"
];
document.querySelectorAll('use[class^="vr-images"]').forEach(elem => {
  elem.addEventListener('mouseenter', updateImageSrc);
});

function updateImageSrc(evt) {
  const index = parseInt(this.classList[0].replace('vr-images', '')) || 1;
  const src = "https://i.ibb.co/" + sources[index - 1];
  document.querySelector('img').src = src;
}
.overlay {
  background-image: url('https://picsum.photos/id/118/1000/800');
  background-repeat: no-repeat;
  background-size: cover;
}

.overlay use {
  opacity: 0;
  transition: all 0.4s linear;
}

.overlay use:hover {
  opacity: 1;
}

.vr-head-tilt {
  position: relative;
}

.big img {
  width: 200px;
  height: 200px;
  object-fit: cover;
}

.big {
  position: relative;
}

.big img {
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translate(-50%, 7%);
  opacity: 0;
  transition: .2s .1s ease-out;
}

.big .default {
  opacity: 1;
}
<svg class="overlay" viewBox="0 0 200 100">
  <defs>
    <clipPath id='clip-1'>
      <polygon points="0,100 100,100 0,50"/>
    </clipPath>
    <clipPath id='clip-2'>
      <polygon points="0,50 100,100 50,00 0,0"/>
    </clipPath>
    <clipPath id='clip-3'>
      <polygon points="100,100 50,00 150,0"/>
    </clipPath>
    <clipPath id='clip-4'>
      <polygon points="100,100 200,50 200,0 150,0"/>
    </clipPath>
    <clipPath id='clip-5'>
      <polygon points="100,100 200,100, 200,50"/>
    </clipPath>
    <image id="img" x="0" y="0" width="200" height="100" preserveAspectRatio="xMidYMid slice"
    xlink:href="https://picsum.photos/id/1/1000/800" />
  </defs>
  <use xlink:href="#img" class="vr-images1" clip-path="url(#clip-1)"/>
  <use xlink:href="#img" class="vr-images2" clip-path="url(#clip-2)"/>
  <use xlink:href="#img" class="vr-images3" clip-path="url(#clip-3)"/>
  <use xlink:href="#img" class="vr-images4" clip-path="url(#clip-4)"/>
  <use xlink:href="#img" class="vr-images5" clip-path="url(#clip-5)"/>
</svg>
<div class="box"></div>
<div class='big'>
  <img src="https://i.ibb.co/rxX8VMq/left.png" class='default'>
</div>

You could also do it only with CSS by modifying a bit your document's structure:

You need to separate each polygons overlay as their own <svg> element so that you can target them when they are hovered as siblings of your .big container.

.container {
  position: relative;
}
.background {
  background-image: url('https://picsum.photos/id/118/1000/800');
  background-repeat: no-repeat;
  background-size: cover;
}
.overlay {
  position: absolute;
  pointer-events: none;
  top: 0;
  right: 0;
}

.overlay use {
  opacity: 0;
  transition: all 0.4s linear;
  pointer-events: all;
}

.overlay use:hover {
  opacity: 1;
}

.vr-head-tilt {
  position: relative;
}

.big img {
  width: 200px;
  height: 200px;
  object-fit: cover;
}

.vr-images1:hover ~ .big img:nth-of-type(1) {
  opacity: 1;
}
.vr-images2:hover ~ .big img:nth-of-type(2) {
  opacity: 1;
}
.vr-images3:hover ~ .big img:nth-of-type(3) {
  opacity: 1;
}
.vr-images4:hover ~ .big img:nth-of-type(4) {
  opacity: 1;
}
.vr-images5:hover ~ .big img:nth-of-type(5) {
  opacity: 1;
}

svg[class*="vr-images"]:not(.vr-images1):hover ~ .big img.default {
  opacity: 0;
}

.big {
  position: relative;
  background: white;
}
.big .default {
  opacity: 1;
}
.big img, .big .white-bg {
  position: absolute;
  bottom: 0;
  left: 50%;
  opacity: 0;
  transform: translate(-50%, 7%);
  transition: .2s .1s ease-out;
  background-size: cover;
  pointer-events: none;
}
.big .white-bg {
  background: white;
  width: 200px;
  height: 200px;
  opacity: 1;
}
.container:not(:hover) .vr-images1{ opacity:1; }
<svg width="0" height="0" style="position:aboslute;pointer-events:none">
  <defs>
    <clipPath id='clip-1'>
    <polygon points="0,100 100,100 0,50"/>
    </clipPath>
    <clipPath id='clip-2'>
    <polygon points="0,50 100,100 50,00 0,0"/>
    </clipPath>
    <clipPath id='clip-3'>
    <polygon points="100,100 50,00 150,0"/>
    </clipPath>
    <clipPath id='clip-4'>
    <polygon points="100,100 200,50 200,0 150,0"/>
    </clipPath>
    <clipPath id='clip-5'>
    <polygon points="100,100 200,100, 200,50"/>
    </clipPath>
    <image id="img" x="0" y="0" width="200" height="100" preserveAspectRatio="xMidYMid slice"
    xlink:href="https://picsum.photos/id/1/1000/800" />
  </defs>
<div class="container">
  <svg class="background" viewBox="0 0 200 100"></svg>

  <svg class="overlay vr-images1" viewBox="0 0 200 100">
    <use xlink:href="#img" class="vr-images1" clip-path="url(#clip-1)"/>
  </svg>
  <svg class="overlay vr-images2" viewBox="0 0 200 100">
    <use xlink:href="#img" class="vr-images2" clip-path="url(#clip-2)"/>
  </svg>
  <svg class="overlay vr-images3" viewBox="0 0 200 100">
    <use xlink:href="#img" clip-path="url(#clip-3)"/>
  </svg>
  <svg class="overlay vr-images4" viewBox="0 0 200 100">
    <use xlink:href="#img" clip-path="url(#clip-4)"/>
  </svg>
  <svg class="overlay vr-images5" viewBox="0 0 200 100">
    <use xlink:href="#img" clip-path="url(#clip-5)"/>
  </svg>
  <div class="box"></div>
  <div class='big'>
   <div class="white-bg"></div>
   <img src="https://i.ibb.co/rxX8VMq/left.png" class='default'>
   <img src="https://i.ibb.co/r77CrCC/topleft.png">
   <img src="https://i.ibb.co/CzRdRtp/top.png">
   <img src="https://i.ibb.co/L8cSs3p/topright.png">
   <img src="https://i.ibb.co/D1cjqfD/right.png">
  </div>
</div>
like image 136
Kaiido Avatar answered Sep 28 '22 17:09

Kaiido


I would update my previous answer like below. I will add the extra element for the images that you change on hover:

.box {
  width: 450px;
  height: 250px;
  position: relative;
  overflow: hidden;
  z-index: 0; 
  background: url(https://picsum.photos/id/13/1000/800) center/cover;
 
}

.box>div:not(.big) {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-image: url(https://picsum.photos/id/118/1000/800);
  background-size: cover;
  background-position: center;
  opacity: 0;
}


.box>div:nth-child(1) {
  clip-path: polygon(20% 0, 80% 0, 50% 100%);
}

.box>div:nth-child(2) {
  clip-path: polygon(0 0, 20% 0, 50% 100%, 0 40%);
}

.box>div:nth-child(3) {
  clip-path: polygon(100% 0, 80% 0, 50% 100%, 100% 40%);
}

.box>div:nth-child(4) {
  clip-path: polygon(0 100%, 50% 100%, 0 40%);
}

.box>div:nth-child(5) {
  clip-path: polygon(100% 100%, 50% 100%, 100% 40%);
}

.box>div:hover {
  opacity: 1;
}

.big {
  position: absolute;
  bottom:0;
  width:150px;
  height:150px;
  left:calc(50% - 75px);
}  
.big img {
  position: absolute;
  width: 100%;
  height:100%;
  top:0;
  left:0;
  object-fit: cover;
  opacity: 0;
  transition: .2s .1s ease-out;
}

.big .default {
  opacity: 1;
}

.box>div:nth-child(1):hover ~ .big > img:nth-child(1) {
  opacity:1;
  z-index:1;
}
.box>div:nth-child(2):hover ~ .big > img:nth-child(2) {
  opacity:1;
  z-index:1;
}
.box>div:nth-child(3):hover ~ .big > img:nth-child(3) {
  opacity:1;
  z-index:1;
}
.box>div:nth-child(4):hover ~ .big > img:nth-child(4) {
  opacity:1;
  z-index:1;
}
.box>div:nth-child(5):hover ~ .big > img:nth-child(5) {
  opacity:1;
  z-index:1;
}
<div class="box">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div class='big'>
    <img src="https://i.ibb.co/CzRdRtp/top.png">
    <img src="https://i.ibb.co/r77CrCC/topleft.png">
    <img src="https://i.ibb.co/L8cSs3p/topright.png">
    <img src="https://i.ibb.co/rxX8VMq/left.png" class='default'>
    <img src="https://i.ibb.co/D1cjqfD/right.png">
  </div>
</div>
like image 44
Temani Afif Avatar answered Sep 28 '22 17:09

Temani Afif