I have a runnable code snippet below and here as well: https://stackblitz.com/edit/js-ecyxnt?file=index.html
What I would like to know is how I can elegantly accomplish with es6, toggling the <use href="">
attribute somehow so that the svg switches between the regular and filled version.
I want one svg element that starts out unfilled and on each click it toggle between it's normal state and being filled. I am confused how to do this, if I actually need two svgs in a parent svg in order to use <use>
or what the best way to implement this would be.
.wishlist-btn {
display: flex;
align-items: center;
justify-content: center;
height: 100px;
width: 100px;
border: none;
background: #fff;
transition: all 0.5s ease-in-out;
box-shadow: 0 0 15px rgba(0 0 0 / 25%);
}
.icon {
height: 60px;
width: 60px;
margin: 20px;
}
<h1>Svg <use> href toggle</h1>
<button >
<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<!-- how can I toggle #wishlist-add/#wishlist with JavaScript? -->
<use href="#wishlist-add"/>
</svg>
</button>
<svg viewBox="0 0 20 20" id="wishlist-add" xmlns="http://www.w3.org/2000/svg">
<path
d="M2.813 10.88l7.204 7.2 7.875-7.873a4.993 4.993 0 000-7.05 4.884 4.884 0 00-6.977 0l-.897.902-.46-.465-.476-.479A4.89 4.89 0 005.594 1.65a4.893 4.893 0 00-3.49 1.465 4.998 4.998 0 00-.001 7.05l.706.706.004.008z"
stroke="currentColor"
stroke-width="1.3"
fill="none"
fill-rule="evenodd"
></path>
</svg>
<svg viewBox="0 0 20 20" id="wishlist" xmlns="http://www.w3.org/2000/svg">
<path
d="M20 6.681c0 1.44-.55 2.88-1.646 3.984L10.017 19l-7.753-7.75-.004-.009-.617-.617a5.649 5.649 0 010-7.966A5.543 5.543 0 015.593 1c1.428 0 2.855.552 3.95 1.658l.476.479.435-.438a5.533 5.533 0 017.9 0A5.64 5.64 0 0120 6.681z"
fill="currentColor"
fill-rule="evenodd"
></path>
</svg>
CodePudding user response:
Use setAttribute on the use element to change its href attribute...
function run(event) {
let use = event.target.querySelector("use");
use.setAttribute("href", use.getAttribute("href") === "#wishlist-add" ? "#wishlist" : "#wishlist-add");
}
.wishlist-btn {
display: flex;
align-items: center;
justify-content: center;
height: 100px;
width: 100px;
border: none;
background: #fff;
transition: all 0.5s ease-in-out;
box-shadow: 0 0 15px rgba(0 0 0 / 25%);
}
<h1>Svg <use> href toggle</h1>
<button onclick="run(event)">
<svg viewBox="0 0 20 20" pointer-events="none" xmlns="http://www.w3.org/2000/svg">
<!-- how can I toggle #wishlist-add/#wishlist with JavaScript? -->
<use href="#wishlist-add"/>
</svg>
</button>
<svg viewBox="0 0 20 20" id="wishlist-add" xmlns="http://www.w3.org/2000/svg">
<path
d="M2.813 10.88l7.204 7.2 7.875-7.873a4.993 4.993 0 000-7.05 4.884 4.884 0 00-6.977 0l-.897.902-.46-.465-.476-.479A4.89 4.89 0 005.594 1.65a4.893 4.893 0 00-3.49 1.465 4.998 4.998 0 00-.001 7.05l.706.706.004.008z"
stroke="currentColor"
stroke-width="1.3"
fill="none"
fill-rule="evenodd"
></path>
</svg>
<svg viewBox="0 0 20 20" id="wishlist" xmlns="http://www.w3.org/2000/svg">
<path
d="M20 6.681c0 1.44-.55 2.88-1.646 3.984L10.017 19l-7.753-7.75-.004-.009-.617-.617a5.649 5.649 0 010-7.966A5.543 5.543 0 015.593 1c1.428 0 2.855.552 3.95 1.658l.476.479.435-.438a5.533 5.533 0 017.9 0A5.64 5.64 0 0120 6.681z"
fill="currentColor"
fill-rule="evenodd"
></path>
</svg>
CodePudding user response:
Why change the DOM using JavaScript when you can use CSS. Here are two examples (with the same technique). In the first the SVG is embedded on the "button". It is more simple, but I guess that you have more buttons on the same page. In that case the second example makes use of <use>
, so all the buttons can make use of the same SVG. In both examples there is a hidden checkbox. This can be useful if you need to collect information about what items was clicked.
.wishlist-btn {
display: flex;
align-items: center;
justify-content: center;
height: 100px;
width: 100px;
border: none;
background: #fff;
transition: all 0.5s ease-in-out;
box-shadow: 0 0 15px rgba(0 0 0 / 25%);
}
.wishlist-btn input {
display: none;
}
.icon {
height: 60px;
width: 60px;
margin: 20px;
cursor: pointer;
fill: none;
stroke: currentColor;
stroke-width: 1.3px;
}
.wishlist-btn input:checked~.icon {
fill: currentColor;
stroke: none;
stroke-width: 0;
}
<h1>Svg <use> href toggle</h1>
<label >
<input type="checkbox" name="wishlist" />
<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path
d="M2.813 10.88l7.204 7.2 7.875-7.873a4.993 4.993 0 000-7.05 4.884 4.884 0 00-6.977 0l-.897.902-.46-.465-.476-.479A4.89 4.89 0 005.594 1.65a4.893 4.893 0 00-3.49 1.465 4.998 4.998 0 00-.001 7.05l.706.706.004.008z"
fill-rule="evenodd" />
</svg>
</label>
.wishlist-btn {
display: flex;
align-items: center;
justify-content: center;
height: 100px;
width: 100px;
border: none;
background: #fff;
transition: all 0.5s ease-in-out;
box-shadow: 0 0 15px rgba(0 0 0 / 25%);
}
.wishlist-btn input {
display: none;
}
.icon {
height: 60px;
width: 60px;
margin: 20px;
cursor: pointer;
fill: none;
stroke: currentColor;
stroke-width: 1.3px;
}
.wishlist-btn input:checked~.icon {
fill: currentColor;
stroke: none;
stroke-width: 0;
}
<h1>Svg <use> href toggle</h1>
<label >
<input type="checkbox" name="wishlist" value="1" />
<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<use href="#icon" />
</svg>
</label>
<label >
<input type="checkbox" name="wishlist" value="2" />
<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<use href="#icon" />
</svg>
</label>
<svg width="0" height="0" style="display: none;" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<symbol id="icon">
<path
d="M2.813 10.88l7.204 7.2 7.875-7.873a4.993 4.993 0 000-7.05 4.884 4.884 0 00-6.977 0l-.897.902-.46-.465-.476-.479A4.89 4.89 0 005.594 1.65a4.893 4.893 0 00-3.49 1.465 4.998 4.998 0 00-.001 7.05l.706.706.004.008z"
fill-rule="evenodd" />
</symbol>
</svg>