Here, I have a background that I want to add some dynamic text on it for every single user..
for example.. an image bg.jpg on an html page, and an input that takes a value from users, say user1, user2..etc. I need every time to generate a new image that consists of (the specified background & the username over it)
to use it later on to enable the user to share the result on Facebook with the og:image in the data-image attribute: Share
I have set the user input in a js variable, then passed it to a div with an id centered over the image background as follows:
HTML:
<div class="container">
<img src="img_snow_wide.jpg" alt="Snow" style="width:100%;">
<div id="centered-user"></div>
</div>
CSS:
/* Container holding the image and the text */
.container {
position: relative;
text-align: center;
color: white;
}
/* Centered text */
#centered-user {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
JS:
var user = document.form.username.value.toUpperCase();
var x = document.getElementById("myDIV");
x.innerHTML = user;
Now that the image has the text over it in the center, how can I pass the resulted new image to the html data-image attribute?
You could generate an SVG on the fly and embed it in an <img> tag.
const generateImage = text =>
document.querySelector('#bg').innerHTML =
`<img src="data:image/svg+xml;charset=UTF-8,${encodeURIComponent(svg(text))}">`;
const svg = text => `
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="960px" height="590px"
viewBox="0 0 960 590" preserveAspectRatio="xMidYMid meet">
<defs id="svgEditorDefs">
<symbol id="1f60e" viewBox="0 0 64 64" preserveAspectRatio="xMidYMid meet">
<rect x="0" y="0" width="64" height="64" style="stroke:none;fill:none;" />
<g xmlns="http://www.w3.org/2000/svg">
<g fill-rule="evenodd">
<path d="M32,2c16.568,0,30,13.432,30,30S48.567,62,32,62 C15.431,62,2,48.568,2,32S15.431,2,32,2"
fill="#ffdd67" />
<path
d="m36.12 21.983c-2.355 1.177-5.89 1.177-8.247 0-2.517-1.292-5.593-2.119-9.274-2.442-3.595-.314-11.215-.304-15.03 1.039-.437.153-.869.352-1.283.564-.234.119-.281.207-.281.646v.565c0 1.063-.133.649.626 1.094 1.479.865 2.32 3.116 2.771 6.214.641 4.515 2.857 7.343 6.453 8.694 3.338 1.254 7.07 1.21 10.383-.112 1.811-.724 3.402-1.867 4.666-3.724 2.215-3.257 1.551-5.289 2.695-8.09.996-2.441 3.794-2.441 4.792 0 1.143 2.798.479 4.83 2.695 8.09 1.262 1.856 2.854 3 4.665 3.724 3.311 1.322 7.05 1.366 10.384.112 3.596-1.352 5.812-4.18 6.453-8.694.449-3.098 1.291-5.349 2.77-6.214.76-.444.627-.03.627-1.094v-.565c0-.438-.047-.526-.281-.646-.414-.213-.846-.411-1.283-.564-3.813-1.343-11.434-1.354-15.03-1.039-3.683.323-6.759 1.15-9.276 2.442"
fill="#262626" />
</g>
<path
d="m21.462 43.09c1.133 1.779 2.712 3.071 4.548 3.956 1.831.886 3.908 1.326 5.991 1.328 2.081-.007 4.156-.445 5.986-1.331 1.834-.886 3.414-2.176 4.549-3.953.246 2.078-.826 4.341-2.82 5.944-1.974 1.626-4.844 2.58-7.716 2.567-2.871.008-5.738-.944-7.713-2.57-1.991-1.602-3.066-3.863-2.825-5.941"
fill="#664e27" />
</g>
</symbol>
<polygon id="svgEditorShapeDefs"
style="fill:khaki;stroke:black;vector-effect:non-scaling-stroke;stroke-width:1px;" />
</defs>
<rect id="svgEditorBackground" x="0" y="0" width="960" height="590" style="fill: none; stroke: none;" />
<use xlink:href="#1f60e" x="292" y="249" width="179" height="179" id="e5_emoji" />
<path
d="M9.778,96h22.222v43.962710649591656l32,-43.962710649591656h54.22200000000001c5.400000000000006,0,9.777999999999992,-4.378,9.777999999999992,-9.778000000000006v-76.445c0,-5.4,-4.378,-9.778,-9.778000000000006,-9.778h-108.445c-5.4,0,-9.778,4.378,-9.778,9.778v76.445c0,5.400000000000006,4.378,9.778000000000006,9.778,9.778000000000006Z"
style="fill:none; stroke:black; vector-effect:non-scaling-stroke;stroke-width:1px;" id="e6_shape"
transform="matrix(1.56655 0 0 0.835931 423.742 142.001)" /><text
style="fill:black;font-family:Arial;font-size:20px;" x="446" y="167" id="e11_texte"
transform="matrix(1 0 0 1 32 21)">${text}</text>
</svg>
`;
#bg img {position: absolute; top: -100px; left: -200px;}
<input type="text" placeholder="Some text..." oninput="generateImage(this.value)">
<div id="bg"></div>
var h1 = document.getElementsByTagName("H1")[0]; // Get your element
var att = document.createAttribute("class"); // Create at attribute
att.value = "democlass"; // Set value to the attribute
h1.setAttributeNode(att);
Related
With some elbow grease I managed to create a 2D version of the effect:
But it feels contrived. I would like to animate this, change the size and the angle.
Before I start digging into maths to calc all those hardcoded coordinates...
Can this be done in a smarter way? (Without dependencies on 3rd party libraries)
<svg viewBox="0 0 200 278" style="height:180px">
<defs>
<pattern id="back" width="200" height="278" patternUnits="userSpaceOnUse">
<image width="200" href="https://svg-cdn.github.io/cm-back-red.svg" />
</pattern>
<pattern id="front" width="200" height="278" patternUnits="userSpaceOnUse">
<image width="200" href="https://svg-cdn.github.io/cm-hearts-king.svg" />
</pattern>
<clipPath id="clip">
<path d="M0 178L0 0h200v278h-59z" />
</clipPath>
</defs>
<g clip-path="url(#clip)">
<rect width="200" height="278" fill="url(#back)" />
<rect width="200" height="278" fill="url(#front)"
transform="translate(-100 139) rotate(-100 100 139)" />
</g>
</svg>
Version 1
From CCProg his answer, Heiko his answer takes some more work.
My math fails me again, how to make the card corner follow the mouse position. It now calculates the x and y offsets.
And a full card turn would be cool
customElements.define("fold-card", class extends HTMLElement {
constructor() {
super()
.attachShadow({mode:"open"})
.innerHTML = `<svg viewBox="0 0 300 378" style="height:95vh;cursor:hand;background:pink">
<defs><pattern id="back" width="200" height="278" patternUnits="userSpaceOnUse"><image width="200" href="https://svg-cdn.github.io/cm-back-red.svg" /></pattern>
<pattern id="front" width="200" height="278" patternUnits="userSpaceOnUse"><image width="200" href="https://svg-cdn.github.io/cm-hearts-king.svg" /></pattern>
<clipPath id="clip"><path /></clipPath></defs>
<g clip-path="url(#clip)">
<rect width="200" height="278" fill="url(#back)" />
<rect id="below" width="200" height="278" fill="url(#front)" />
</g></svg>`;
}
connectedCallback() {
let svg = this.shadowRoot.querySelector("svg");
let pt = svg.createSVGPoint();
let [x,y] = (this.getAttribute("crease")||"0,0").split(",");
this.fold({x,y});
this.onmousemove = evt =>{
pt.x = evt.clientX;
pt.y = evt.clientY;
this.fold( pt.matrixTransform(svg.getScreenCTM().inverse()) );
}
}
fold({x,y}){
if(x>=0 && x<=200 && y>=0 && y<=278) {
this.shadowRoot.querySelector('#clip path')
.setAttribute('d', `M0 ${y}L0 0H300V278H${x}z`);
let a = Math.atan2(x, 278 - y) * 180 / Math.PI;
this.shadowRoot.querySelector('#below')
.setAttribute('transform', `rotate(${-2*a} 0 ${y}) translate(-200)`);
}
}
})
<style> fold-card { height: 180px } </style>
<fold-card crease="200,10"></fold-card>
<fold-card crease="100,50"></fold-card>
Version 2 - almost no Math using <marker>
chrwahl his answer is cleverly using a <marker> to position the revealing card at the end of a rotating <line>
Work in progress: https://jsfiddle.net/WebComponents/r2y7x3fd/
Still need to calculate the position of the red dot, to create a <clip-path>
Don't fear the math, it is really quite simple.
Start with the two points where the "crease" meets the card sides, because you can choose them freely.
P1 = 0, 178 // x is fixed
P2 = 141, 278 // y is fixed
Compute the angle of the "crease" from the vertical in degrees:
a = Math.atan2((P2.x - P1.x), (P2.y - P1.y))*180/Math.PI
= Math.atan2(141, 100)*180/Math.PI
= 54.655
Move the second card to the left side of the y-axis
transform ="translate(-200)"
...and rotate it by -2a around P1
transform ="rotate(-109.31 0 178) translate(-200)"
That's all.
function crease (y1, x2) {
document.querySelector('#clip path')
.setAttribute('d', `M0 ${y1}L0 0H200V278H${x2}z`);
const a = Math.atan2(x2, 278 - y1)*180/Math.PI;
document.querySelector('#below')
.setAttribute('transform', `rotate(${-2*a} 0 ${y1}) translate(-200)`);
}
crease(178, 141);
<svg viewBox="0 0 200 278" style="height:180px">
<defs>
<pattern id="back" width="200" height="278" patternUnits="userSpaceOnUse">
<image width="200" href="https://svg-cdn.github.io/cm-back-red.svg" />
</pattern>
<pattern id="front" width="200" height="278" patternUnits="userSpaceOnUse">
<image width="200" href="https://svg-cdn.github.io/cm-hearts-king.svg" />
</pattern>
<clipPath id="clip">
<path />
</clipPath>
</defs>
<g clip-path="url(#clip)">
<rect width="200" height="278" fill="url(#back)" />
<rect id="below" width="200" height="278" fill="url(#front)" />
</g>
</svg>
Here is an animated solution that uses the CSS rotate3d transformation. I achieved it with quite some trial and error, and it is still not clear to me how exactly the transform-origin affects the animation.
I found that the animation changes when I move the transform-origin: 81px bottom; rule from div.back to input:checked~div.back.corner. Apparently, elements should have the same transform-origin before and after the animation for it to be smooth, even if the element before the animation is not transformed at all.
I have added a Javascript function that computes all the parameters from just the height and width and the x and y coordinates of the "crease".
var rules = document.styleSheets[0].rules;
function render(form) {
rules[1].styleMap.set("width", `${form.w.value}px`);
rules[1].styleMap.set("height", `${form.h.value}px`);
rules[2].styleMap.set("transform-origin", `${form.x.value}px bottom`);
rules[3].styleMap.set("clip-path", `path("M${form.w.value},${form.h.value} l${-form.x.value},0 l${form.x.value},${-form.y.value} l0,${form.y.value}z")`);
rules[3].styleMap.set("transform", `translateX(${form.x.value - form.w.value / 2}px) rotateY(180deg) translateX(${form.w.value / 2 - form.x.value}px)`);
rules[3].styleMap.set("transform-origin", `${form.w.value - form.x.value}px bottom`);
rules[4].styleMap.set("clip-path", `path("M0,0 l${form.w.value},0 l0,${form.h.value} l${form.x.value - form.w.value},0 l${-form.x.value},${-form.y.value} l0,${form.y.value-form.h.value}z")`);
rules[5].styleMap.set("clip-path", `path("M0,${form.h.value} l${form.x.value},0 l${-form.x.value},${-form.y.value} l0,${form.y.value}z")`);
rules[6].styleMap.set("transform", `rotate3d(${-form.x.value}, ${-form.y.value}, 0, -170deg)`);
rules[7].styleMap.set("transform", `translateX(${form.x.value - form.w.value / 2}px) rotateY(180deg) translateX(${form.w.value / 2 - form.x.value}px) rotate3d(${form.x.value}, ${-form.y.value}, 0, -170deg)`);
}
body {
position: relative;
}
div {
position: absolute;
width: 200px;
height: 278px;
transform-style: preserve-3d;
backface-visibility: hidden;
transition: 0.5s;
zoom: 0.5;
}
div.back {
background: url(https://svg-cdn.github.io/cm-back-red.svg);
transform-origin: 81px bottom;
}
div.front {
background: url(https://svg-cdn.github.io/cm-hearts-king.svg);
clip-path: path("M200,278 l-81,0 l81,-99 l0,99z");
transform: translateX(-19px) rotateY(180deg) translateX(19px);
transform-origin: 119px bottom;
}
div.nocorner {
clip-path: path("M0,0 l200,0 l0,278 l-119,0 l-81,-99 l0,-179z");
}
div.corner {
clip-path: path("M0,278 l81,0 l-81,-99 l0,99z");
}
input:checked~div.back.corner {
transform: rotate3d(-81, -99, 0, -170deg);
}
input:checked~div.front {
transform: translateX(-19px) rotateY(180deg) translateX(19px) rotate3d(81, -99, 0, -170deg);
}
<form onsubmit="render(this); return false;">
width <input name="w" size="3" value="200" />
height <input name="h" size="3" value="278" />
x axis <input name="x" size="3" value="81" />
y axis <input name="y" size="3" value="99" />
<input type="submit" value="Render" />
</form>
<input type="checkbox" /> Fold
<div class="back nocorner"></div>
<div class="back corner"></div>
<div class="front"></div>
Remark on the "interactive card folder": If the folded card corner is (x, bottom - y), then the crease goes from ((x²+y²)/2x, bottom) to (0, bottom - (x²+y²)/2y).
This is not perfect, but maybe you can work more in this direction. I really did some experimentation here.
The front card is a marker, making it follow the angle of the line that it is placed on. The line is then positions according to the mouse. The mask that cuts off the cards in the bottom is made with a line that has a wide (large) stroke and fixed in the bottom left corner.
let SVG = document.getElementById("SVG");
let LINE1 = document.getElementById("LINE1");
let LINE2 = document.getElementById("LINE2");
const toSVGPoint = (x, y) => (new DOMPoint(x, y)).matrixTransform(SVG.getScreenCTM().inverse());
SVG.addEventListener('mousemove', e => {
let p = toSVGPoint(e.clientX, e.clientY);
LINE1.setAttribute('x2', p.x);
LINE1.setAttribute('y2', p.y);
LINE1.setAttribute('x1', 0-p.x);
LINE1.setAttribute('y1', 278-p.x);
LINE2.setAttribute('x2', p.x);
LINE2.setAttribute('y2', p.y);
});
<svg id="SVG" viewBox="0 0 300 278" style="height:180px">
<defs>
<pattern id="back" width="200" height="278" patternUnits="userSpaceOnUse" >
<image width="200" href="https://svg-cdn.github.io/cm-back-red.svg" />
</pattern>
<mask id="mask1">
<rect width="100%" height="100%" fill="white"/>
<line id="LINE2" x1="0" y1="278" x2="0" y2="278"
stroke="black" stroke-width="500"
stroke-dasharray="50 50" pathLength="100" />
</mask>
<marker id="card" viewBox="-278 0 278 200" refX="0" refY="0"
markerWidth="278" markerHeight="200"
markerUnits="userSpaceOnUse" orient="auto">
<image transform="rotate(90)" width="200"
href="https://svg-cdn.github.io/cm-hearts-king.svg" />
</marker>
</defs>
<g mask="url(#mask1)">
<rect class="back" width="200" height="278" fill="url(#back)" />
<line id="LINE1" x1="0" y1="278" x2="0" y2="0" stroke="none" marker-end="url(#card)" />
</g>
</svg>
I have an SVG icon like this:
<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
<rect width="19" height="19" fill="url(#pattern0)"/>
<defs>
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
<use xlinkHref="#image0" transform="scale(0.00444444)"/>
</pattern>
<image id="image0" width="225" height="225" xlinkHref="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIPEBIQDw8PEBERFRAVEhAQFRAPFRIWFRUYFxYVFhUaHSggGBolGxUVIjEhJSkrLy4uFx8zODMsNygtLisBCgoKDg0OGhAQGy0lICYtLS0tKy0vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLf/AABEIAOEA4QMBEQACEQEDEQH/xAAbAAEAAgMBAQAAAAAAAAAAAAAABQYBAgcEA//EAEUQAAIBAQUCCAsFBgYDAAAAAAABAgMEBQYRITFREjJBYXGBkbETFiJCUlNyocHR0hQjYoKSBxckNJOyFUNjouHwM1TC/8QAGwEBAAIDAQEAAAAAAAAAAAAAAAQFAQMGAgf/xAAxEQEAAgECBQEGBQQDAAAAAAAAAQIDBBEFEiExUUEUFSJhcYETMjORoQYjsdFCUvH/2gAMAwEAAhEDEQA/AO4gAAAAAAAAAAAAAwwNXNb0YZ2ljwsfSj2obnLPhnhLeZY2mGUww2DIAAAAAAAAAAAAAAAAAAAAABq2GHgvK+qFmWdatCD9HbJ9EVqeLZK17ykYdNlyztSsyqtv/aJBZqz0JT/FVfAXTwVm37iNbVxHaFth4HeeuS2306oC2Y2tlTPKpGkt1OKXvebI9tVkn5LLHwfT17xv9URXvW0VOPaK8uZ1J5dmeRqnJafVMro8Fe1I/Z5Jty4zb6dTzvLfFKx2hrwFuRhnaH0p1ZR4spR9ltdx6i0x2l4nFS3eI/Z77Nf9qp8S1V+iU5TXZLNHuM16+rRfQafJ3pH+EzYsfWqH/kVOsudcB9sdPcba6u/r1QMvBMNvyTMSsl3Y+s9TJVlOg978uPate1EmmqpPfoq83Bs9Otfij5LNZbXCrFSpzjOL5YNSXuN9bRP5VXfHak7WjZ90enlkAAAAAAAAAAAAAAABhgRl835Rskc608m+LCPlTl0R+L0Nd8tad0nT6TLnnakfdz++8b2ivnGj9xT/AA6zfTLk6u0g5NVae3Z0Wl4Njx7Tk+Kf4VeUm22223tbebfSyLM791vWsVjasbMB6AAAAAAAAAHosVtq0JcOjUnTlvi8s+lbH1nqt5rPRqy6fHlja9Yld7ix/shbI5cnhoLT80eTpXYTceqjtdz+q4LMfFhnf5LxZ7TGpFThOM4y1UotNMmRO8bworVtSdrRs+qMvLIAAAAAAAAAAAw2BhsClYoxuqfCo2RxnNaSq7Yw5o+k/d0kPNqYr0r1Xeh4TOTa+XpHj1lz20V5VJOdSUpyltlJ5tkC1ptO8umx4646xWsbQ+Zh7AAAAAAAAAAAAAASdyX5WscuFSlnF8anLWMurkfOjbjy2pPRC1WgxaivxR18upXBiClbYZ03wZrj0pcaPzXOWWPLW8dHJ6rR5NPba0dPSUumbURkAAAAAAAABhsDWc0lm9Etr3A2c2xfi51nKhZpNUtkqi0dTeluj399fn1G+9YdNw3hcVj8XLHX0jwpxDXwAAAAAAAAAAAAAAAAAS2GbFXrWiP2aThOOrq8kFve/o5Tdhrab9EDiGbFTDP4vX5OywWiz1eWr2Zls4ue7YMAAAAAAAAGGBzfHGJnVlKzUJfdp5VZrz2vNX4Vy7++BqM+/wANXScJ4dtEZsnf0/2pZCdAAAAAAAAABvDOwGAAAAAAAEhcl0VLZVVOkt3Dm+LBb38FymzFjm87Qi6vV009Oa37eXXLlumnZKSpUlptlJ8ab3tlrjxxSNocZqNRfPfnv/4kEj20MgAAAAAAAYzAqWPcQfZ6fgKUvvqq1a2wg9M+l6pdZF1ObkjljutuFaL8a/Pb8sfzLmBWuujwAAAAABtCDk1GKcm9iSbb6EZiN52h5taKxvPZZ7pwNaayUqvBoRfpeVN/lWzraJNNJe3foqdRxnDj6Ujmn+FosWArLBLwnhKz/FJwXZHIk10tIVGXjGot+Xp9EvRw5ZI6KyUPzQjPvzNsYqR6IdtZnt3vP7vtK5bM9HZbP/Tp/IzyV8PEajL/ANp/d47RhSx1Ntmpr2M6f9rR4nBSfRupr9TTteUJeH7PKUs3QqzpvkjPKpH4M030dZ7J+HjeWv6kRP8AlUL4w1abJm6lPhQ9ZT8uPXyx60RcmC1PoutNxLBn6RO0+JQ5pTwCQuS6KlsqqnSW5zm+LBb38FymzFjnJO0fuiavV009Oa32j1dcuW6KdkpKlSjzyk+NN72y1x0ikbQ43Uam+e/Pf/xIJHtoZAAAAAAAAAeS87bCz0p1qnFgm3z7kudvJdZ5taKxvLZixWy3ilfVxa8LbO0VZ1ajzlN5vm3JcyWhT3vN55pd1p8FcOOK1eY8twAAAAJjD2HqttllBcGmuPVlsXMvSfMbsWG1+3ZA1nEMemjr1nw6bceH6Njj91DOeXlVZazl18i5kWOPFWnZyup1mXUT8c9PCXRtRGQAAAAA1aB2VDEmCYVk6lmSpVdW4bIT+l9GneRMunifir3XOh4tfF8OTrX+YUe7bhr17Q7OoShKD+8ck0qa3v4b/eQ6Yb2tyx0X2bX4sWH8SJ337fN1i5bpp2SkqdJc8pPjTlyybLSmOKRtDj9RqL57ze8pBHtoZAAAAAAAAAAKvjHg1o/Z23lpKWTy18359hzfGOI2xZK46enWVrw2JpP4sd/Rza8bunQflaxeya2P5M8abVUzx06T6w6jDnrl+rxkv5t4AAAT2FMOyttTOWcaEH5c1tb9CPP3JkjDhnJPXsrOI6+unry1/N/j5usWSywowVOnFQhFZKK0SLKI2jaHIXva9ua07vuenkAAAAAAAAAfNQSbeSze16aj5ky3QGQAAAAAAAAADSpJJNvYs2zxe3JWbSzEbz0Um01nOcpvzm38vcfN9TmnLltefWXQYqclIq+FWmpJxkk09qeprpeaTvE7NsTMTvCtXrcrp5zp5yhyx2uPzRf6TiEZNq36T5WODVc3w26Shy033TQD23Rd07VWhRp7ZPWXJGK2yfQjZjpN7bQj6rUV0+Ob29PTy7LdthhZ6UaVJZRgslve9vnbLateWNocPmzWy3m9u8vWemsAAAAAAAAAAAAAAAAAAAAAAARt/VuBRlvk1Fde33JlTxrN+FpbfPok6SnNkj5KmcIvGTAGYELetyKec6WUZcsdil8mWuj4jNPhydYTMGqmnS3ZW6kHFuMk01tT0aL6totG8TusotFo3h0v9nV0eCofaJLy63F5qaena9ews9Lj2rzT6uT4xqvxMv4cdq/5XDIlqgAAAAAAAAAAAAAAAAAAAAAAAAK/iiprCHtSfcvict/UeT8lPusuH16zKCOXWYYAAZY2ea03RG1SjF6SbSU1tS5elFjw7PkjLWleu8vftNsNJmHQbPSUIxhFZRikktySyR30RttDmbWm07y+p6YAAAABhgV++cWUrJVdGdOrJpRecFDLXpkibp9BkzV5q7I2XU1x25ZeHx/oeptHZS+o3+6c3mGv26niTx/oeptHZS+oe6c3mD26niTx/oeptHZS+oe6c3mD26niT94FD1No7KX1D3Tm8we3U8SfvAoeptHZS+oe6c3mD26niT94FD1No7KX1D3Tm8we3U8SfvAoeptHZS+oe6c3mD26niTx/oeptHZS+oe6c3mD26niTx/oeptHZS+oe6c3mD26niTx/oeptHZS+oe6c3mD26niTx/oeptHZS+oe6c/mD26niXuubFlK11fBQhVjLgylnNQyeWWmjeuvuI+fQ5MNea2z3i1VMk8sLCQ0oAAVXEU862W6MV8TiePW31O3iFxoI/towo00AADIksPUuFXT9FSfw+JdcBxc2p38dULXW2x7eVqyO3U7IAAAAAYYHMMffzsvYp9zOj4X+h91Rrf1FcLJDAAAAAAAAAAABNYOq8G20edyj2xaIXEK74LfZJ0s7ZYdZOXXQAAqF+P+In+X+1HB8ZnfV2+y70fTFDwlSlAAABN4Xj5VR80e9nTf05Hx3lW8QnpCxHWKwAAAAADDA5hj7+dl7FPuZ0nC/0PuqNZ+orhZIgAAAAAAAAAADAkMPyytdnf+rS98kiNq4/sWj5S24P1I+rsZya9AAFQvxfxE/y/2o4LjMbau32Xej/Sh4SrSgwAACbwu/KqLmj3s6f+nJ+K8K3iHp91iOrVgAAAAAGGBzDH387L2KfczpOF/ofdUaz9RXCyRAAAAAAAAAAAGB7blX8TQy9bS/uRo1X6V/pLZi/PH1dmORXwAAqmIY5V298Yv4HEcdptqt/MLnQz/bRpSJgAAASmHKnBrZelFrs1+DL3gGTl1E1n1hB19d8e60ZnaqhkAAAAAMMDmGPv52XsU+5nScK/Q+6o1n6iuFkiAAAAAAAAYAyADAkcOw4Vrs6/1ab7Hn8CNrZ2wX+jbp43yR9XYjk16AAK7iin5UJb012a/FnKf1Hi+Kl/ss+H27whDmVkGAAGYYns1/xGFmnCpN5ZSWi2tbHkujMseGY8k6itqek90DXanDhxzzz39F8hJNJrVPJo7+FTE7tzLIAAAAMMCjYtw5abTaXUpQjKDjBZuUY6pa6MudDrcWLFy2nrur9Tp75L7whvEy2eqj+uHzJnvPB5/hH9jyeDxMtnqo/rh8x7zwef4PY8ng8TLZ6qP64fMe88Hn+D2PJ4PEy2eqj+uHzHvPB5/g9jyeDxMtnqo/rh8x7zwef4PY8ng8TbZ6qP64fMe88Hn+GPY8nhGXpddWyyUK0VGUlmkpRlpnlyEnBqaZo3o1ZMVsfSzxEhrAAAwJ3BNHh26l+Hhy7ItfEgcSttgn57JOkjfLH7urHMrkAAReIaPCot8sGpfB95Tccw/iaWZ9a9UrR35cn1VY4ddhgDMMSjryvSNLyY5Snu5I9PyLTRcOvn+K3Sqn4hxamn+GnW38QrlatKcnKTbb5WdNixUxRtSNnIZs+TNbmyTu6XgW9fD2dU5P7yhlF88fMfZp+UscNt67T3W+izc9Np7wsxuTAAAAAAAAAAAAAMMDlGMrb4a2VGnmqeVNfl2/7nI6fhuLkwR8+ql1V+bJKEJ6OAAAYXD9m1nzrVqvoQjFdM3n/8lNxe/wANa+Vhoa/FNnQyiWYAA+dampRcXsaafWastIvSaz6s1tyzEwpFWm4ScXti2n1HzjPinHktSfSXQ0tFqxaGjeWr0S5TXWs2naGbWisbyg7yvnPOFF9M/p+Z0Gi4Vy7XzR9nMcQ4zNt6YJ+6FL2IiHNzO87ywZYSVwXrKyV41Vm47Jx9KL29fKug90vy23b9Pm/Cvu67Zq8asIzhJSjJJxa2NMnRO/V0FbRaN4fYy9AAAAAAAAAAAAicTXqrLZ5zz8trg01vk9j6tvUSNLgnNlivp6/Roz5Yx0mXI289XqzrYiIjaFJLBkAAADpmALH4OycN7aspS6l5Me5vrOY4lk588x46LfR02x7z6rOQEsAAAKtiuEaL8NLSMsk/aS07V3HK8Z4de+aL4479/wDadg1lcWKeeeyhXjecq2i8mHo7+d/I3aPh9MEbz1t/DndfxTJqJ2idq+PV4Cy7Krr6gAABZ8H4k+yy8DWb8BJ6Pb4OT5fZfL27zfiy7dJT9Jqfw55L9nS4TUknFpp6prVPrJS5id43bmWQAAAAAAAAB8bVaI04SnOSjGKblJ8iM1rNpisR1YtaKxvLlOJb6lbK3C1VOOapxfIuVvnfy3HUaLSxgptPee6kz5py26dkQTWkAAAw+tks8qtSFOHGnKMV1vLM15b/AIdJtPo91rNpisOz2SgqcI046RhGMV0JZHH3tNrc0r6teWIh9zy9AAAB4L6u6Nqozoy85aP0ZLWL6nkebV5o2as2OMleWXHrTQlSnKnNZSg2pLnRAmNp2c7as1tNZfIw8gAABkCwYaxRUsmUJ51KHo+dDni/h3cu3Hl5e6bptXbH0nrH+HSLuvKlaYKdGamuXLauaS2p9JLraLdlxjyVyRvWXsR6bAAAAAAMZgeK9L1pWaHDrTUVyLbKXNFbWY367NeTLXHG9pc1xHiOpbJZawop5xp7/wAUt79y950+i0dMUc3efP8ApU59ROWdo7IQsEcMAZAABcf2eXXw6krTJeTTzjDnk15T6k8vzFLxXUbRGKPrKfoce8zeXQcijWbIAAAAw0BS8fXFw19qpLyorKql50V53SuXm6CPmx7/ABQrddg3jnr93PyIqOwZAAAAAfex2upRlw6U5QkuWLy6nvXSZiZjs90yWpO9Z2W668fSjlG00lP8dPR9cXo+rI31z+Vjj4hMfnj9lmseKbJV2V4Rfo1Pu379DfGSsplNXit2slaVeM9YyjLni0+49bt8WifV9MzLO74VrZThx6lOOXpSjHvMc0eXmb1jvMIq2YuslL/OVR7qSdTPrWnvPE5aR6tN9Xir6qzemPKk842emqa9OflS6lsXXmabZ9+yDl4haelIVO1WmdWTnUnKcntlJ5v/AINFp5u6Be9rzvaXyRZaHieTTztbrXwxFpZOvwZ6Zq81JbNw3MgAD72GySr1IUqazlN5Lm3t8yWb6jVmyxipNp9HrHSbztDsF12GNnpQpQ2QWWe97W3zt5s5HLknJebT6r3HSKViIew8PYAAAAAGs457QxLmOL8OuzT8LSX3E3/Tb81827s6YeXHt1jsptXppxzzR2Vo0IAZAAAAADAA3kyM7yzE7NnJvRt9rG8s80+WuQ3ljcDAYAyAGSTptVkwX5qT9vLMTszmddouI4tRXxPj/TZE7hYPQJnubS6Tgm4fs8PDVV99UWie2nHd0vl7Dm+Iav8AFtyV/LH8yttLg5I3nutORWpjJkAAAAAAwwPnaKEakXCcVKMk1KL1TT5DHd5msTG0uYYow1KySc6ec6Dektrh+GXNuf8A1w8mLl6wpdVpJxTvHZXjUhAAAAAAAAAAAAAAAAxIHut7UtFqjOZ1HD+LRk+DJ0ny21svODcLvONptEcssnSpy905LuQ1+ui39vHPT1lZ6XS7fFZekimWLJkAAAAAAAAMAa1KaknGSTTzTTSaae1NGJ692JjeNpUDEuDJQzq2ROUdsqO2UfY3rm27syNkw+tVVqdDt8WP9lNay0aya2p6ZEdWzEwwYYDIAAAAAAAAAAAABvSpSnJRhFylJ5KMU22+gREzPR6rWbTtEL/hfBypZVrUlKpo40tGoc8uRv3LnJePDt1lbabRRT4r9/C5JG9YsgAAAAAAAAAAAAYEFfuF6Nrzk14Or6yHL7S2S7+c13xVsi5tLTL8p8qBfGGrRZc3KHDp+sp5tda2x6yLbFaFTm0mTHPyQyNaMAAAAAAAAAAAMp+5sJ2i05ScXRpvz6iabX4Y7X3G2mG1u6Vh0eTJ17fVf7kuCjZI/dxzm+NUlrJ/JcyJVaRXst8Onrijp38pZHtvZAAAAAAAAAAAAAAAAatZhhCXphWzWjNun4Ob8+llB9a2PsNdsVZR8ulx5O8dVXt+Aqsc3QqwqL0Zp05duqfuNNtP4QcnD7/8JQNruG1UuPZ6uW+K4a7Y5mqcdo7wiW02SveJR0tHk9GuR6M8bbNO2zAYAGYG1KDm8oJye6Kcn2Icu7MVmeyUsmG7XV4tnqJb5rwa/wB2R7jFafRIrpctvSf8J6wYAm9a9aMFyxprhP8AU8kuxm2un8pWPh9v+crTdeG7NZsnTppzX+ZU8uXVyLqyN1cdYTsWmx4/ywl0bEhkAAAAAAAAAAAAAAAAAAAAAAB8qtGM+NGMvaSfeYmHmaxPd5KlzWaXGs1B9NOD+B55K+Hj8HHPesNP8Asn/qWf+nD5Dkr4hj2fF/1j9n1p3VZ48Wz0Y9EIL4GYrHh6jFSO0PXCCiskkluWh6e4iI7Q3DIAAAAAAAAAAAAAAAAAAAAAAAAAAGrMSxPdkxDIeoYkAwZefVsYewAAAAAAAAAAAAP/2Q=="/>
</defs>
</svg>
It displays on screen width > 1279 but disappears from the screen width <= 1279. Because of the page's layout, I have three divs that render on different screen sizes and contain this svg. I tried using svgs with different ids but the same content. However, it didn't work for me. Can somebody help me with that?
logic code:
component that uses svg icons (all of them disappear on width <= 1279 except star svgs that rendered in a list)
<div className="position__reviews--social-wrapper">
<div className="position__reviews--social">
<Icon className="position__reviews--social-icon" name="google" />
<Icon className="position__reviews--social-icon" name="vivino" />
</div>
<div className="position__reviews--vivino-wrapper">
<Icon className="position__reviews--vivino-text-icon" name="vivino-text" />
{[...Array(5)].map((star,idx) => idx + 1 <= redStars ? <Icon className="position__reviews--star-red" name="position__review-star-red" /> : <Icon className="position__reviews--star-gray" name="position__review-star-gray" />)}
</div>
</div>
Icon (svgIcons is a list of jsx items: () => (<svg>...</svg>) ):
const Icon = ({ name, fill, onClick, className }) => {
const svg = svgIcons[name];
const iconClasses = cn(className, {
'icon--active': !!onClick,
});
return svg ? (
<span className={iconClasses} onClick={onClick}>
{svg(fill)}
</span>
) : null;
};
css:
.position__reviews--social-icon {
border: 1px solid #C4C4C4;
box-sizing: border-box;
border-radius: 3px;
margin-right: 6px;
padding: 4px;
padding-top: 9px;
padding-bottom: 1px;
cursor: pointer;
}
What happens:
width > 1279:
width <= 1279:
This:
<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink">
<rect width="19" height="19" fill="url(#pattern0)"/>
<defs>
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
<use xlinkHref="#image0" transform="scale(0.00444444)"/>
</pattern>
<image id="image0" width="225" height="225" xlinkHref="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIPEBIQDw8PEBERFRAVEhAQFRAPFRIWFRUYFxYVFhUaHSggGBolGxUVIjEhJSkrLy4uFx8zODMsNygtLisBCgoKDg0OGhAQGy0lICYtLS0tKy0vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLf/AABEIAOEA4QMBEQACEQEDEQH/xAAbAAEAAgMBAQAAAAAAAAAAAAAABQYBAgcEA//EAEUQAAIBAQUCCAsFBgYDAAAAAAABAgMEBQYRITFREjJBYXGBkbETFiJCUlNyocHR0hQjYoKSBxckNJOyFUNjouHwM1TC/8QAGwEBAAIDAQEAAAAAAAAAAAAAAAQFAQMGAgf/xAAxEQEAAgECBQEGBQQDAAAAAAAAAQIDBBEFEiExUUEUFSJhcYETMjORoQYjsdFCUvH/2gAMAwEAAhEDEQA/AO4gAAAAAAAAAAAAAwwNXNb0YZ2ljwsfSj2obnLPhnhLeZY2mGUww2DIAAAAAAAAAAAAAAAAAAAAABq2GHgvK+qFmWdatCD9HbJ9EVqeLZK17ykYdNlyztSsyqtv/aJBZqz0JT/FVfAXTwVm37iNbVxHaFth4HeeuS2306oC2Y2tlTPKpGkt1OKXvebI9tVkn5LLHwfT17xv9URXvW0VOPaK8uZ1J5dmeRqnJafVMro8Fe1I/Z5Jty4zb6dTzvLfFKx2hrwFuRhnaH0p1ZR4spR9ltdx6i0x2l4nFS3eI/Z77Nf9qp8S1V+iU5TXZLNHuM16+rRfQafJ3pH+EzYsfWqH/kVOsudcB9sdPcba6u/r1QMvBMNvyTMSsl3Y+s9TJVlOg978uPate1EmmqpPfoq83Bs9Otfij5LNZbXCrFSpzjOL5YNSXuN9bRP5VXfHak7WjZ90enlkAAAAAAAAAAAAAAABhgRl835Rskc608m+LCPlTl0R+L0Nd8tad0nT6TLnnakfdz++8b2ivnGj9xT/AA6zfTLk6u0g5NVae3Z0Wl4Njx7Tk+Kf4VeUm22223tbebfSyLM791vWsVjasbMB6AAAAAAAAAHosVtq0JcOjUnTlvi8s+lbH1nqt5rPRqy6fHlja9Yld7ix/shbI5cnhoLT80eTpXYTceqjtdz+q4LMfFhnf5LxZ7TGpFThOM4y1UotNMmRO8bworVtSdrRs+qMvLIAAAAAAAAAAAw2BhsClYoxuqfCo2RxnNaSq7Yw5o+k/d0kPNqYr0r1Xeh4TOTa+XpHj1lz20V5VJOdSUpyltlJ5tkC1ptO8umx4646xWsbQ+Zh7AAAAAAAAAAAAAASdyX5WscuFSlnF8anLWMurkfOjbjy2pPRC1WgxaivxR18upXBiClbYZ03wZrj0pcaPzXOWWPLW8dHJ6rR5NPba0dPSUumbURkAAAAAAAABhsDWc0lm9Etr3A2c2xfi51nKhZpNUtkqi0dTeluj399fn1G+9YdNw3hcVj8XLHX0jwpxDXwAAAAAAAAAAAAAAAAAS2GbFXrWiP2aThOOrq8kFve/o5Tdhrab9EDiGbFTDP4vX5OywWiz1eWr2Zls4ue7YMAAAAAAAAGGBzfHGJnVlKzUJfdp5VZrz2vNX4Vy7++BqM+/wANXScJ4dtEZsnf0/2pZCdAAAAAAAAABvDOwGAAAAAAAEhcl0VLZVVOkt3Dm+LBb38FymzFjm87Qi6vV009Oa37eXXLlumnZKSpUlptlJ8ab3tlrjxxSNocZqNRfPfnv/4kEj20MgAAAAAAAYzAqWPcQfZ6fgKUvvqq1a2wg9M+l6pdZF1ObkjljutuFaL8a/Pb8sfzLmBWuujwAAAAABtCDk1GKcm9iSbb6EZiN52h5taKxvPZZ7pwNaayUqvBoRfpeVN/lWzraJNNJe3foqdRxnDj6Ujmn+FosWArLBLwnhKz/FJwXZHIk10tIVGXjGot+Xp9EvRw5ZI6KyUPzQjPvzNsYqR6IdtZnt3vP7vtK5bM9HZbP/Tp/IzyV8PEajL/ANp/d47RhSx1Ntmpr2M6f9rR4nBSfRupr9TTteUJeH7PKUs3QqzpvkjPKpH4M030dZ7J+HjeWv6kRP8AlUL4w1abJm6lPhQ9ZT8uPXyx60RcmC1PoutNxLBn6RO0+JQ5pTwCQuS6KlsqqnSW5zm+LBb38FymzFjnJO0fuiavV009Oa32j1dcuW6KdkpKlSjzyk+NN72y1x0ikbQ43Uam+e/Pf/xIJHtoZAAAAAAAAAeS87bCz0p1qnFgm3z7kudvJdZ5taKxvLZixWy3ilfVxa8LbO0VZ1ajzlN5vm3JcyWhT3vN55pd1p8FcOOK1eY8twAAAAJjD2HqttllBcGmuPVlsXMvSfMbsWG1+3ZA1nEMemjr1nw6bceH6Njj91DOeXlVZazl18i5kWOPFWnZyup1mXUT8c9PCXRtRGQAAAAA1aB2VDEmCYVk6lmSpVdW4bIT+l9GneRMunifir3XOh4tfF8OTrX+YUe7bhr17Q7OoShKD+8ck0qa3v4b/eQ6Yb2tyx0X2bX4sWH8SJ337fN1i5bpp2SkqdJc8pPjTlyybLSmOKRtDj9RqL57ze8pBHtoZAAAAAAAAAAKvjHg1o/Z23lpKWTy18359hzfGOI2xZK46enWVrw2JpP4sd/Rza8bunQflaxeya2P5M8abVUzx06T6w6jDnrl+rxkv5t4AAAT2FMOyttTOWcaEH5c1tb9CPP3JkjDhnJPXsrOI6+unry1/N/j5usWSywowVOnFQhFZKK0SLKI2jaHIXva9ua07vuenkAAAAAAAAAfNQSbeSze16aj5ky3QGQAAAAAAAAADSpJJNvYs2zxe3JWbSzEbz0Um01nOcpvzm38vcfN9TmnLltefWXQYqclIq+FWmpJxkk09qeprpeaTvE7NsTMTvCtXrcrp5zp5yhyx2uPzRf6TiEZNq36T5WODVc3w26Shy033TQD23Rd07VWhRp7ZPWXJGK2yfQjZjpN7bQj6rUV0+Ob29PTy7LdthhZ6UaVJZRgslve9vnbLateWNocPmzWy3m9u8vWemsAAAAAAAAAAAAAAAAAAAAAAARt/VuBRlvk1Fde33JlTxrN+FpbfPok6SnNkj5KmcIvGTAGYELetyKec6WUZcsdil8mWuj4jNPhydYTMGqmnS3ZW6kHFuMk01tT0aL6totG8TusotFo3h0v9nV0eCofaJLy63F5qaena9ews9Lj2rzT6uT4xqvxMv4cdq/5XDIlqgAAAAAAAAAAAAAAAAAAAAAAAAK/iiprCHtSfcvict/UeT8lPusuH16zKCOXWYYAAZY2ea03RG1SjF6SbSU1tS5elFjw7PkjLWleu8vftNsNJmHQbPSUIxhFZRikktySyR30RttDmbWm07y+p6YAAAABhgV++cWUrJVdGdOrJpRecFDLXpkibp9BkzV5q7I2XU1x25ZeHx/oeptHZS+o3+6c3mGv26niTx/oeptHZS+oe6c3mD26niTx/oeptHZS+oe6c3mD26niT94FD1No7KX1D3Tm8we3U8SfvAoeptHZS+oe6c3mD26niT94FD1No7KX1D3Tm8we3U8SfvAoeptHZS+oe6c3mD26niTx/oeptHZS+oe6c3mD26niTx/oeptHZS+oe6c3mD26niTx/oeptHZS+oe6c3mD26niTx/oeptHZS+oe6c/mD26niXuubFlK11fBQhVjLgylnNQyeWWmjeuvuI+fQ5MNea2z3i1VMk8sLCQ0oAAVXEU862W6MV8TiePW31O3iFxoI/towo00AADIksPUuFXT9FSfw+JdcBxc2p38dULXW2x7eVqyO3U7IAAAAAYYHMMffzsvYp9zOj4X+h91Rrf1FcLJDAAAAAAAAAAABNYOq8G20edyj2xaIXEK74LfZJ0s7ZYdZOXXQAAqF+P+In+X+1HB8ZnfV2+y70fTFDwlSlAAABN4Xj5VR80e9nTf05Hx3lW8QnpCxHWKwAAAAADDA5hj7+dl7FPuZ0nC/0PuqNZ+orhZIgAAAAAAAAAADAkMPyytdnf+rS98kiNq4/sWj5S24P1I+rsZya9AAFQvxfxE/y/2o4LjMbau32Xej/Sh4SrSgwAACbwu/KqLmj3s6f+nJ+K8K3iHp91iOrVgAAAAAGGBzDH387L2KfczpOF/ofdUaz9RXCyRAAAAAAAAAAAGB7blX8TQy9bS/uRo1X6V/pLZi/PH1dmORXwAAqmIY5V298Yv4HEcdptqt/MLnQz/bRpSJgAAASmHKnBrZelFrs1+DL3gGTl1E1n1hB19d8e60ZnaqhkAAAAAMMDmGPv52XsU+5nScK/Q+6o1n6iuFkiAAAAAAAAYAyADAkcOw4Vrs6/1ab7Hn8CNrZ2wX+jbp43yR9XYjk16AAK7iin5UJb012a/FnKf1Hi+Kl/ss+H27whDmVkGAAGYYns1/xGFmnCpN5ZSWi2tbHkujMseGY8k6itqek90DXanDhxzzz39F8hJNJrVPJo7+FTE7tzLIAAAAMMCjYtw5abTaXUpQjKDjBZuUY6pa6MudDrcWLFy2nrur9Tp75L7whvEy2eqj+uHzJnvPB5/hH9jyeDxMtnqo/rh8x7zwef4PY8ng8TLZ6qP64fMe88Hn+D2PJ4PEy2eqj+uHzHvPB5/g9jyeDxMtnqo/rh8x7zwef4PY8ng8TbZ6qP64fMe88Hn+GPY8nhGXpddWyyUK0VGUlmkpRlpnlyEnBqaZo3o1ZMVsfSzxEhrAAAwJ3BNHh26l+Hhy7ItfEgcSttgn57JOkjfLH7urHMrkAAReIaPCot8sGpfB95Tccw/iaWZ9a9UrR35cn1VY4ddhgDMMSjryvSNLyY5Snu5I9PyLTRcOvn+K3Sqn4hxamn+GnW38QrlatKcnKTbb5WdNixUxRtSNnIZs+TNbmyTu6XgW9fD2dU5P7yhlF88fMfZp+UscNt67T3W+izc9Np7wsxuTAAAAAAAAAAAAAMMDlGMrb4a2VGnmqeVNfl2/7nI6fhuLkwR8+ql1V+bJKEJ6OAAAYXD9m1nzrVqvoQjFdM3n/8lNxe/wANa+Vhoa/FNnQyiWYAA+dampRcXsaafWastIvSaz6s1tyzEwpFWm4ScXti2n1HzjPinHktSfSXQ0tFqxaGjeWr0S5TXWs2naGbWisbyg7yvnPOFF9M/p+Z0Gi4Vy7XzR9nMcQ4zNt6YJ+6FL2IiHNzO87ywZYSVwXrKyV41Vm47Jx9KL29fKug90vy23b9Pm/Cvu67Zq8asIzhJSjJJxa2NMnRO/V0FbRaN4fYy9AAAAAAAAAAAAicTXqrLZ5zz8trg01vk9j6tvUSNLgnNlivp6/Roz5Yx0mXI289XqzrYiIjaFJLBkAAADpmALH4OycN7aspS6l5Me5vrOY4lk588x46LfR02x7z6rOQEsAAAKtiuEaL8NLSMsk/aS07V3HK8Z4de+aL4479/wDadg1lcWKeeeyhXjecq2i8mHo7+d/I3aPh9MEbz1t/DndfxTJqJ2idq+PV4Cy7Krr6gAABZ8H4k+yy8DWb8BJ6Pb4OT5fZfL27zfiy7dJT9Jqfw55L9nS4TUknFpp6prVPrJS5id43bmWQAAAAAAAAB8bVaI04SnOSjGKblJ8iM1rNpisR1YtaKxvLlOJb6lbK3C1VOOapxfIuVvnfy3HUaLSxgptPee6kz5py26dkQTWkAAAw+tks8qtSFOHGnKMV1vLM15b/AIdJtPo91rNpisOz2SgqcI046RhGMV0JZHH3tNrc0r6teWIh9zy9AAAB4L6u6Nqozoy85aP0ZLWL6nkebV5o2as2OMleWXHrTQlSnKnNZSg2pLnRAmNp2c7as1tNZfIw8gAABkCwYaxRUsmUJ51KHo+dDni/h3cu3Hl5e6bptXbH0nrH+HSLuvKlaYKdGamuXLauaS2p9JLraLdlxjyVyRvWXsR6bAAAAAAMZgeK9L1pWaHDrTUVyLbKXNFbWY367NeTLXHG9pc1xHiOpbJZawop5xp7/wAUt79y950+i0dMUc3efP8ApU59ROWdo7IQsEcMAZAABcf2eXXw6krTJeTTzjDnk15T6k8vzFLxXUbRGKPrKfoce8zeXQcijWbIAAAAw0BS8fXFw19qpLyorKql50V53SuXm6CPmx7/ABQrddg3jnr93PyIqOwZAAAAAfex2upRlw6U5QkuWLy6nvXSZiZjs90yWpO9Z2W668fSjlG00lP8dPR9cXo+rI31z+Vjj4hMfnj9lmseKbJV2V4Rfo1Pu379DfGSsplNXit2slaVeM9YyjLni0+49bt8WifV9MzLO74VrZThx6lOOXpSjHvMc0eXmb1jvMIq2YuslL/OVR7qSdTPrWnvPE5aR6tN9Xir6qzemPKk842emqa9OflS6lsXXmabZ9+yDl4haelIVO1WmdWTnUnKcntlJ5v/AINFp5u6Be9rzvaXyRZaHieTTztbrXwxFpZOvwZ6Zq81JbNw3MgAD72GySr1IUqazlN5Lm3t8yWb6jVmyxipNp9HrHSbztDsF12GNnpQpQ2QWWe97W3zt5s5HLknJebT6r3HSKViIew8PYAAAAAGs457QxLmOL8OuzT8LSX3E3/Tb81827s6YeXHt1jsptXppxzzR2Vo0IAZAAAAADAA3kyM7yzE7NnJvRt9rG8s80+WuQ3ljcDAYAyAGSTptVkwX5qT9vLMTszmddouI4tRXxPj/TZE7hYPQJnubS6Tgm4fs8PDVV99UWie2nHd0vl7Dm+Iav8AFtyV/LH8yttLg5I3nutORWpjJkAAAAAAwwPnaKEakXCcVKMk1KL1TT5DHd5msTG0uYYow1KySc6ec6Dektrh+GXNuf8A1w8mLl6wpdVpJxTvHZXjUhAAAAAAAAAAAAAAAAxIHut7UtFqjOZ1HD+LRk+DJ0ny21svODcLvONptEcssnSpy905LuQ1+ui39vHPT1lZ6XS7fFZekimWLJkAAAAAAAAMAa1KaknGSTTzTTSaae1NGJ692JjeNpUDEuDJQzq2ROUdsqO2UfY3rm27syNkw+tVVqdDt8WP9lNay0aya2p6ZEdWzEwwYYDIAAAAAAAAAAAABvSpSnJRhFylJ5KMU22+gREzPR6rWbTtEL/hfBypZVrUlKpo40tGoc8uRv3LnJePDt1lbabRRT4r9/C5JG9YsgAAAAAAAAAAAAYEFfuF6Nrzk14Or6yHL7S2S7+c13xVsi5tLTL8p8qBfGGrRZc3KHDp+sp5tda2x6yLbFaFTm0mTHPyQyNaMAAAAAAAAAAAMp+5sJ2i05ScXRpvz6iabX4Y7X3G2mG1u6Vh0eTJ17fVf7kuCjZI/dxzm+NUlrJ/JcyJVaRXst8Onrijp38pZHtvZAAAAAAAAAAAAAAAAatZhhCXphWzWjNun4Ob8+llB9a2PsNdsVZR8ulx5O8dVXt+Aqsc3QqwqL0Zp05duqfuNNtP4QcnD7/8JQNruG1UuPZ6uW+K4a7Y5mqcdo7wiW02SveJR0tHk9GuR6M8bbNO2zAYAGYG1KDm8oJye6Kcn2Icu7MVmeyUsmG7XV4tnqJb5rwa/wB2R7jFafRIrpctvSf8J6wYAm9a9aMFyxprhP8AU8kuxm2un8pWPh9v+crTdeG7NZsnTppzX+ZU8uXVyLqyN1cdYTsWmx4/ywl0bEhkAAAAAAAAAAAAAAAAAAAAAAB8qtGM+NGMvaSfeYmHmaxPd5KlzWaXGs1B9NOD+B55K+Hj8HHPesNP8Asn/qWf+nD5Dkr4hj2fF/1j9n1p3VZ48Wz0Y9EIL4GYrHh6jFSO0PXCCiskkluWh6e4iI7Q3DIAAAAAAAAAAAAAAAAAAAAAAAAAAGrMSxPdkxDIeoYkAwZefVsYewAAAAAAAAAAAAP/2Q=="/>
</defs>
</svg>
was most likely created by a developer in a K-Hole
"Falling into a k-hole" is slang for how it feels when you take a high enough dose of ketamine that your awareness of the world around you and your control over your own body become so profoundly impaired that you're temporarily unable to interact with others—or the world around you.
It wraps a Base64 data (the Google G logo)
in an <image>
in a <pattern>
in a <rect>
in a <svg>
I would ask that developer what the meaning is, because all you have to do is:
wrap the Base64 data in an IMG element
<img width="19" src="data:image/jpeg;base64,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">
If you do want the contrived SVG, write proper SVG:
<svg width="19" height="19" viewBox="0 0 19 19">
<rect width="19" height="19" fill="url(#pattern0)"/>
<defs>
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
<use href="#image0" transform="scale(0.00444444)"/>
</pattern>
<image id="image0" width="225" height="225" href="data:image/jpeg;base64,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"/>
</defs>
</svg>
I have svg mask which determines holes in rectangular. Behind svg mask I have some clickable elements and I would like to pass events to them, but only through holes. I've experimented with pointer-events values, but I can only make either whole mask to pass events or whole mask to capture them. For one hole it can be simply done using clip-path, just determining outer part of the hole, but several holes make things more difficult. Is there any possibility to avoid using clip-path? I also tried pointer-events: visiblePainted and pointer-events: painted, but had no success.
.background {
width: 400px;
height: 400px;
background: red;
cursor: pointer;
}
.svg {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
<button class="background">
</button>
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg" class="svg">
<defs>
<mask id="mask">
<rect
x="0"
y="0"
width="400"
height="400"
fill="white"
/>
<rect
x="20"
y="20"
width="40"
height="40"
fill="black"
/>
<rect
x="290"
y="290"
width="40"
height="40"
fill="black"
/>
</mask>
</defs>
<rect
x="0"
y="0"
width="400"
height="400"
fill="black"
opacity="0.5"
mask="url(#mask)"
pointer-events="auto"
/>
</svg>
There are several aspects to this problem. First, you are right the behavior of masks and clip-paths is different in relation to hit-testing.
A clip path is a geometric boundary, and a given point is clearly either inside or outside that boundary; thus, pointer events must be captured normally over the rendered areas of a clipped element, but must not be captured over the clipped areas... By contrast, a mask is not a binary transition, but a pixel operation, and different behavior for fully transparent and almost-but-not-fully-transparent may be confusingly arbitrary; as a consequence, for elements with a mask applied, pointer events must still be captured even in areas where the mask goes to zero opacity.
Second, a clip-path is a geometric shape, but just like all paths, it might contain holes. Instead of three <rect>s, you can use one <path> with three subpaths, as long as the clip-rule makes sure the subpaths inside get cut out of the surrounding shape.
Third, if the pointer-events property is applied to an <svg> element in a HTML context, its behavior becomes...strange. Any other value than pointer-events: none on the <svg> element lead to the whole bounding box receiving events - a behavior proposed for HTML elements, but currently not part of any spec.
The solution here is to set pointer-events: none on the <svg> element, and then to reverse that with pointer-events: painted on the child <rect> element.
button, svg {
position:absolute;
width:400px;
height:400px
}
button {
background: #0000ff;
cursor: pointer;
}
button:hover {
background: #008800;
}
svg {
pointer-events: none;
}
.over {
fill: #000;
clip-path: url(#clip);
pointer-events: painted;
}
<button></button>
<svg xmlns="http://www.w3.org/2000/svg" height="400" width="400">
<defs>
<clipPath id="clip" clip-rule="evenodd">
<path d="M 20 20 h 360 v 360 h -360 z
M 40 40 v 40 h 40 v -40 z
M 200 290 v 40 h 40 v -40 z" />
</clipPath>
</defs>
<rect y="0" x="0" height="400" width="400" class="over" />
</svg>
Clip masks are useful for cropping parts out of complicated objects, but if you're just working with blocks of solid colour then maybe it would be just as easy to create shapes that already have holes in them.
I've added an example below. Does this help?
<svg width="400" heoght="200" viewBox="0 0 400 200">
<text x="100" y="100" text-anchor="middle"
alignment-baseline="middle" onclick="alert('Hello!')"
style="cursor:pointer">Click me</text>
<text x="300" y="100" text-anchor="middle"
alignment-baseline="middle" onclick="alert('Hello?')"
style="cursor:pointer">Not me</text>
<path d="M20 20 180 20 180 180 20 180ZM60 60 60 140 140
140 140 60Z" fill="#3a6" fill-opacity="0.7"
fill-rule="nonzero"/>
<path d="M220 20 380 20 380 180 220 180Z" fill="#f20"
fill-opacity="0.7"/>
</svg>
I am currently running into an issue relating to adding page breaks when my html file renders into a pdf.
Currently, I have a function that generates a scatterplot with the format below:
function createScatterplot(row, column, group) {
## any d3 visualization code goes here
}
By calling:
createScatterplot(feature1, feature2, 'a')
createScatterplot(feature2, feature3, 'a')
createScatterplot(feature1, feature3, 'b')
it will generate three scatterplots using the d3.js library. Is there an easy way to add page breaks so that we get the following output:
createScatterplot(feature1, feature2, 'a')
createScatterplot(feature2, feature3, 'a')
<--- Page break here --->
createScatterplot(feature1, feature3, 'b')
where each page break is determined by the group (third parameter of the function)?
I know that the function createScatterplot generates an SVG object, but when attempting to use the existing solutions for page breaks in CSS, it seems that the creation of the svg object follows after the execution of the page breaks.
Ideally, I wouldn't want to use any additional JS library. Thanks!
As far as I know, SVG does not do page breaks, but here is a link to an approach that may work for you: https://codepen.io/AmeliaBR/details/jKxJz/
The idea is "re-using the same graphic within multiple SVG elements, using the viewBox attribute to define which part of the graphic should be visible each time". It's a little complicated, but if you look at the codepen, pay attention to the css, especially the "screen styles" part, you can get it to work. Here's a somewhat abridged version - in Chrome (haven't tested with others) when you Print the page it divides it into 4 page-sized blocks...
<head>
<meta charset="utf-8">
<title>paginate</title>
<style>
figure.svg-container {
display: block;
overflow: scroll;
max-width: 90vw;
max-height: 90vh;
border:gray solid thin;
}
svg.print {
display: none;
}
#media print {
figure.svg-container {
display: inline;
overflow: auto;
border: none;
}
svg.screen {
display: none;
}
svg.print {
overflow: hidden;
border: thin lightgray solid;
padding: 0.5em;
-moz-box-sizing: border-box;
box-sizing: border-box;
page-break-inside: avoid;
break-inside: avoid;
}
}
#media print and (orientation: landscape){
svg.print.landscape {
display: block;
height: 7in;
width: 10in;
}
}
</style>
</head>
<body>
<figure class="svg-container">
<svg class="screen" width="18in" height="12in" viewBox="0 0 1800 1200">
<g id="graphic"></g>
</svg>
<!-- For printing in landscape mode, the graphic is divided into four
overlapping quadrants which will each fit on a letter/A4 page without scaling.
The 1000*700 viewBox is equivalent to 10in*7in of the onscreen dimensions. -->
<svg class="print landscape" viewBox="0 0 1000 700">
<use xlink:href="#graphic" />
<defs>
<symbol id="arrow-left" overflow="visible"
viewBox="0 0 12 12"
preserveAspectRatio="xMinYMid meet">
<!-- left-pointing block arrow pointing to 0,0 point -->
<path class="arrow" d="M0 0L5 -5, 5 -3, 12 -3, 12 3, 5 3, 5 5Z" />
</symbol>
<symbol id="arrow-right" overflow="visible"
viewBox="0 0 12 12"
preserveAspectRatio="xMinYMid meet">
<!-- right-pointing block arrow pointing to 0,0 point -->
<path class="arrow" transform="rotate(180)"
d="M0 0L5 -5, 5 -3, 12 -3, 12 3, 5 3, 5 5Z" />
</symbol>
<symbol id="arrow-top" overflow="visible"
viewBox="0 0 12 12"
preserveAspectRatio="xMinYMid meet">
<!-- top-pointing block arrow pointing to 0,0 point -->
<path class="arrow" transform="rotate(90)"
d="M0 0L5 -5, 5 -3, 12 -3, 12 3, 5 3, 5 5Z" />
</symbol>
<symbol id="arrow-bottom" overflow="visible"
viewBox="0 0 12 12"
preserveAspectRatio="xMinYMid meet">
<!-- bottom-pointing block arrow pointing to 0,0 point -->
<path class="arrow" transform="rotate(-90)"
d="M0 0L5 -5, 5 -3, 12 -3, 12 3, 5 3, 5 5Z" />
</symbol>
</defs>
<g class="labels">
<text class="label" x="50%" y="50%">A</text>
<use xlink:href="#arrow-right" x="100%" y="50%" width="100" height="100" />
<text class="pointer right" x="100%" y="50%" dx="-50">B</text>
<use xlink:href="#arrow-bottom" x="50%" y="100%" width="100" height="100" />
<text class="pointer bottom" x="50%" y="100%" dy="-50">C</text>
</g>
</svg>
<svg class="print landscape" viewBox="800 0 1000 700">
<use xlink:href="#graphic" />
<g class="labels" transform="translate(800,0)">
<text class="label" x="50%" y="50%">B</text>
<use xlink:href="#arrow-left" x="0%" y="50%" width="100" height="100" />
<text class="pointer left" x="0%" y="50%" dx="50">A</text>
<use xlink:href="#arrow-bottom" x="50%" y="100%" width="100" height="100" />
<text class="pointer bottom" x="50%" y="100%" dy="-50">D</text>
</g>
</svg>
<svg class="print landscape" viewBox="0 500 1000 700">
<use xlink:href="#graphic" />
<g class="labels" transform="translate(0,500)">
<text class="label" x="50%" y="50%">C</text>
<use xlink:href="#arrow-right" x="100%" y="50%" width="100" height="100" />
<text class="pointer right" x="100%" y="50%" dx="-50">D</text>
<use xlink:href="#arrow-top" x="50%" y="0%" width="100" height="100" />
<text class="pointer top" x="50%" y="0%" dy="50">A</text>
</g>
</svg>
<svg class="print landscape" viewBox="800 500 1000 700">
<use xlink:href="#graphic" />
<g class="labels" transform="translate(800,500)">
<text class="label" x="50%" y="50%">D</text>
<use xlink:href="#arrow-left" x="0%" y="50%" width="100" height="100" />
<text class="pointer left" x="0%" y="50%" dx="50">C</text>
<use xlink:href="#arrow-top" x="50%" y="0%" width="100" height="100" />
<text class="pointer top" x="50%" y="0%" dy="50">B</text>
</g>
</svg>
<!-- For printing in portrait mode, the graphic is scaled down slightly
to fit on two pages. Again, the content of each page will overlap slightly. -->
<svg class="print portrait" viewBox="0 0 1000 1200">
<use xlink:href="#graphic" />
<g class="labels">
<text class="label" x="50%" y="50%">A</text>
<use xlink:href="#arrow-right" x="100%" y="50%" width="100" height="100" />
<text class="pointer right" x="100%" y="50%" dx="-50">B</text>
</g>
</svg>
<svg class="print portrait" viewBox="800 0 1000 1200">
<use xlink:href="#graphic" />
<g class="labels" transform="translate(800,0)">
<text class="label" x="50%" y="50%">B</text>
<use xlink:href="#arrow-left" x="0%" y="50%" width="100" height="100" />
<text class="pointer left" x="0%" y="50%" dx="50">A</text>
</g>
</svg>
</figure>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
var doc = document;
var g = doc.getElementById("graphic");
var svgNS = g.namespaceURI;
var r, t;
for (var i=0; i<18; i++) {
for (var j=0; j<12; j++) {
r = doc.createElementNS(svgNS, "rect");
r.setAttribute("width", "80");
r.setAttribute("height", "80");
r.setAttribute("x", (i*100 + 10));
r.setAttribute("y", (j*100 + 10));
r.style.setProperty("fill-opacity", ((i*j + 1)%20)/20, null);
g.insertBefore(r, null);
t = doc.createElementNS(svgNS, "text");
t.setAttribute("x", (i*100 + 50));
t.setAttribute("y", (j*100 + 50));
t.setAttribute("class", "diagram");
t.textContent = [i,j];
g.insertBefore(t, null);
}
}
});
</script>
</body>
I am currently working on some new stuff and I have been introduced to the world of SVG objects. They are nice. I have a button that I have built and I put a filter on it. The designer I'm working with would like the filter (a drop shadow) to go from opacity 1 to 0 on hover, and return to 1 off hover.
I have tried just normal transitions on the filter, and I can get the filter to disappear but the transition is far from smooth.
Here's my code:
HTML
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 216 216" style="enable-background:new 0 0 216 216;" xml:space="preserve">
<filter id="fade" height="150%" width='150%'>
<feMerge>
<feMergeNode/>
<!-- this contains the offset blurred image -->
<feMergeNode in="SourceGraphic" />
<!-- this contains the element that the filter is applied to -->
</feMerge>
</filter>
<filter id="dropshadow" height="150%" width='150%'>
<feGaussianBlur in="SourceAlpha" stdDeviation="25" />
<!-- stdDeviation is how much to blur -->
<feOffset dx="0" dy="15vh" result="offsetblur" />
<!-- how much to offset -->
<feComponentTransfer>
<feFuncA type="linear" slope="0.4" />
</feComponentTransfer>
<feMerge>
<feMergeNode/>
<!-- this contains the offset blurred image -->
<feMergeNode in="SourceGraphic" />
<!-- this contains the element that the filter is applied to -->
</feMerge>
</filter>
<a href='' id='playvideo_button'>
<g>
<path class="st0" d="M108,24c-46.4,0-84,37.6-84,84s37.6,84,84,84s84-37.6,84-84S154.4,24,108,24z" />
<polygon class="st1" points="92,140 92,76 140,108" />
</g>
</a>
</svg>
CSS
svg {
width: 30vw;
height: 30vh;
cursor: pointer;
}
svg .st0 {
fill: #4982CF;
transition: filter.6s ease-out;
filter: url(#dropshadow);
}
svg .st1 {
fill: #ffffff;
}
svg:hover .st0{
filter: url(#fade);
}
Here is my Fiddle that I have been playing around with.
Edits
I have created a second filter, which is just a transparent overlay, but that has also failed and does the same not smooth effect. I'm pretty much at a loss here.
Using transitions on the filter is not the way to do this. Here is a more elegant way. There are a bunch of things here you should note:
You need to size both the svg and the filter regions properly to make sure the shadow isn't cut off
You can't transition filters
Support for CSS units isn't reliably supported inside an SVG filter, stick to either objectBoundingBox (%) or userSpaceOnUse (viewbox) units
Look at how I constructed the filter to allow it to be drawn on top of the shape (to capture hover) without obscuring it. That's the "operator="out" part of the filter.
Enclose your filter in a defs element. Some browsers require this.
DON'T use Illustrator exports as boilerplates. They're really not well constructed SVG.
In general, the worst way to learn SVG is by trying to decode or tweak Illustrator export code. It's just an unmitigated craptastic disaster.
svg {
width: 30vw;
height: 30vh;
cursor: pointer;
}
svg .st0 {
fill: #4982CF;
}
svg .st1 {
fill: #ffffff;
}
#usedshadow {
opacity: 1;
transition: opacity 0.6s;
}
#usedshadow:hover {
opacity: 0;
transition: opacity 0.6s;
}
<svg version="1.1" x="0px" y="0px" width="300px" height="300px" viewBox="0 0 300 300">
<defs>
<filter id="dropshadow" x="-50%" y="-50%" height="200%" width='200%'>
<feGaussianBlur in="SourceAlpha" stdDeviation="10" />
<!-- stdDeviation is how much to blur -->
<feOffset dx="0" dy="15" result="offsetblur" />
<!-- how much to offset -->
<feComponentTransfer>
<feFuncA type="linear" slope="0.4" />
</feComponentTransfer>
<feComposite operator="out" in2="SourceGraphic"/>
</filter>
<g id="myshape">
<path class="st0" d="M108,24c-46.4,0-84,37.6-84,84s37.6,84,84,84s84-37.6,84-84S154.4,24,108,24z" />
<polygon class="st1" points="92,140 92,76 140,108" />
<g>
</defs>
<use xlink:href="#myshape"/>
<use id="usedshadow" filter="url(#dropshadow)" xlink:href="#myshape"/>
</svg>
You can achieve this effect using a path with a gaussian blur to simulate the shadow instead of using a filter, the result i got is this:
In this way you can handle the "drop shadow" directly, then with just simple CSS you can make the opacity transition.
svg #shadow{
transition: all 0.65s;
opacity:1;
}
svg:hover #shadow{
opacity:0;
}
The complete SVG:
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="216"
height="216"
id="svg3013">
<defs
id="defs3015">
<filter
x="-0.14227594"
y="-0.13746469"
width="1.2845519"
height="1.2749294"
color-interpolation-filters="sRGB"
id="filter3826">
<feGaussianBlur
id="feGaussianBlur3828"
stdDeviation="8.4688065" />
</filter>
</defs>
<g
transform="translate(0,-836.36218)"
id="layer1">
<path
d="m 183.57143,107.07143 a 71.428574,73.928574 0 1 1 -142.857143,0 71.428574,73.928574 0 1 1 142.857143,0 z"
transform="matrix(1.064,0,0,1.0280193,-11.320001,836.29069)"
id="shadow"
style="fill:#1a1a1a;fill-opacity:1;stroke:none;filter:url(#filter3826)" />
<g
transform="translate(-0.14285916,0.7142867)"
id="g3806">
<path
d="m 183.57143,107.07143 a 71.428574,73.928574 0 1 1 -142.857143,0 71.428574,73.928574 0 1 1 142.857143,0 z"
transform="matrix(1.064,0,0,1.0280193,-11.177142,835.5764)"
id="path3021"
style="fill:#4982cf;fill-opacity:1;stroke:none" />
<path
d="m 86.476396,914.53271 0,58.81194 54.094674,-27.18845 z"
id="path3796"
style="fill:#ffffff;stroke:none" />
</g>
</g>
</svg>
And the working example here: https://jsfiddle.net/h3s1hp3k/