how can I get the text around whatsapp fa icon? - css

I'm trying to put the svg text around the whatsapp fa icon, something like this
but unable to achieve desired result. this is what I'm getting so far.
I tried with the below code.
<a id='whatsapp'
style={{
bottom: '162px', right: '32px', fontSize: '3.3rem',
padding: '0.6rem', backgroundColor: '#70d470',
color: '#fff'
}}
href="https://wa.me/1232365326"
target="_blank" rel="noopener noreferrer"
className={`${visible ? "block whatsapp" : "none"}`}
>
<svg viewBox="0 0 100 100" width="100" height="100">
<defs>
<path id="circle"
d="
M 50, 50
m -37, 0
a 37,37 0 1,1 74,0
a 37,37 0 1,1 -74,0"/>
</defs>
<text font-size="8">
<textPath xlinkHref="#circle">
Need Appointment? Click me!
</textPath>
</text>
</svg>
<RiWhatsappFill/>
</a>

You could try using position: 'absolute' on the text, then aligning it manually.
Here's something that might work, give it a shot.
<a id='whatsapp'
style={{
bottom: '162px', right: '32px', fontSize: '3.3rem',
padding: '0.6rem', backgroundColor: '#70d470',
color: '#fff'
}}
href="https://wa.me/1232365326"
target="_blank" rel="noopener noreferrer"
className={`${visible ? "block whatsapp" : "none"}`}
>
<svg viewBox="0 0 100 100" width="100" height="100">
<defs>
<path id="circle"
d="
M 50, 50
m -37, 0
a 37,37 0 1,1 74,0
a 37,37 0 1,1 -74,0"/>
</defs>
<text style={{position: 'absolute', right: '32px', top: '2px'}} font-size="8">
<textPath xlinkHref="#circle">
Need Appointment? Click me!
</textPath>
</text>
</svg>
<RiWhatsappFill/>
</a>

Related

How to override a SVG color coming from backend?

I have links with their own SVGs coming from my backend via my API.
I want to overwrite the color when i'm in dark mode and set it to white.
Here is my component that display the SVG :
[...]
<button className="flex items-center fill">
{value.pictogram &&
pictogram(value.pictogram, {
fill: value.pictoFill,
})}
{!props.isMinimized && (
<span className="ml-3">{value.label}</span>
)}
</button>
[...]
export const pictogram: any = (key: string, props: any) => {
return pictogramToComponent[key] ? React.createElement(pictogramToComponent[key], props) : null;
};
And the SVG is like this in the DOM :
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20" viewBox="0 0 20 20" fill="#C1C1C1"><defs><clipPath id="clip-path-picto-hektor"><rect id="Bold_hyperlink-3" data-name="Bold / hyperlink-3" width="20" height="20" transform="translate(-1862 -1482)" fill="none"></rect></clipPath><clipPath id="clip-path-picto-hektor-2"><rect id="Rectangle_2" data-name="Rectangle 2" width="16" height="16" fill="#525254"></rect></clipPath></defs><g id="ico_Hektor" transform="translate(1862 1482)" opacity="0.3" clip-path="url(#clip-path-picto-hektor)"><g id="Groupe_4" data-name="Groupe 4" transform="translate(-1860 -1480)"><g id="Groupe_3" data-name="Groupe 3" transform="translate(0 0)" clip-path="url(#clip-path-picto-hektor-2)"><path id="Trac\xE9_2" data-name="Trac\xE9 2" d="M13.82,1.071Q12.046,0,8.019,0,4.064,0,2.4.961,0,2.289,0,5.8v4.434q0,3.474,2.4,4.8Q4.064,16,8.019,16a11.986,11.986,0,0,0,5.8-1.072Q16,13.635,16,10.235V5.8q0-3.436-2.18-4.73m.964,6.164a3.75,3.75,0,0,1-3.855,2.889A4.707,4.707,0,0,1,8,8.985a4.707,4.707,0,0,1-2.929,1.139A3.75,3.75,0,0,1,1.216,7.235a.059.059,0,0,1,.107-.049,2.291,2.291,0,0,0,2.022.957A7.284,7.284,0,0,0,6.45,6.8a.548.548,0,0,1,.46-.072L8,7.051l1.09-.319a.548.548,0,0,1,.46.072,7.283,7.283,0,0,0,3.105,1.34,2.292,2.292,0,0,0,2.022-.957.059.059,0,0,1,.106.049" transform="translate(0 0)" fill="#525254"></path></g></g></g></svg>
Any idea what should I change to change the color ?
I tried to add fill class and do this in my CSS :
.fill~svg,
.fill svg,
.fill~path,
.fill path,
.fill~circle,
.fill circle,
.fill~rect,
.fill rect,
.fill~line,
.fill line,
.fill~polyline,
.fill polyline,
.fill~polygon,
.fill polygon,
.fill~text,
.fill text,
.fill~tspan,
.fill tspan,
.fill~g,
.fill g {
fill: #ffffff !important;
}
But nothing change.
Try this:
svg #ico_Hektor {
opacity: 1 !important;
}
svg path {
fill: #000000 !important;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20" viewBox="0 0 20 20" fill="#C1C1C1"><defs><clipPath id="clip-path-picto-hektor"><rect id="Bold_hyperlink-3" data-name="Bold / hyperlink-3" width="20" height="20" transform="translate(-1862 -1482)" fill="none"></rect></clipPath><clipPath id="clip-path-picto-hektor-2"><rect id="Rectangle_2" data-name="Rectangle 2" width="16" height="16" fill="#525254"></rect></clipPath></defs><g id="ico_Hektor" transform="translate(1862 1482)" opacity="0.3" clip-path="url(#clip-path-picto-hektor)"><g id="Groupe_4" data-name="Groupe 4" transform="translate(-1860 -1480)"><g id="Groupe_3" data-name="Groupe 3" transform="translate(0 0)" clip-path="url(#clip-path-picto-hektor-2)"><path id="Trac\xE9_2" data-name="Trac\xE9 2" d="M13.82,1.071Q12.046,0,8.019,0,4.064,0,2.4.961,0,2.289,0,5.8v4.434q0,3.474,2.4,4.8Q4.064,16,8.019,16a11.986,11.986,0,0,0,5.8-1.072Q16,13.635,16,10.235V5.8q0-3.436-2.18-4.73m.964,6.164a3.75,3.75,0,0,1-3.855,2.889A4.707,4.707,0,0,1,8,8.985a4.707,4.707,0,0,1-2.929,1.139A3.75,3.75,0,0,1,1.216,7.235a.059.059,0,0,1,.107-.049,2.291,2.291,0,0,0,2.022.957A7.284,7.284,0,0,0,6.45,6.8a.548.548,0,0,1,.46-.072L8,7.051l1.09-.319a.548.548,0,0,1,.46.072,7.283,7.283,0,0,0,3.105,1.34,2.292,2.292,0,0,0,2.022-.957.059.059,0,0,1,.106.049" transform="translate(0 0)" fill="#525254"></path></g></g></g></svg>

Create Magnifying glass for image with overlay react

I have a image and svg rect as overlay. when i try the react-image-magnifiyer and it working normally. but when i try to overlay with svg the magnifier didn't work. please guide me how to create magnifier on image hover with svg rect as overlay
JSX:
<div class="img-overlay-wrap" style={{ marginLeft: "27%" }}>
<img src={object.base64} style={{ height:`512` , width:`512`}} alt="" />
<svg style={{ display: (this.state.isHide ? 'block' : 'none') }} width="512" height="512" >
{
object.bbox.map((val,index)=>
<g>
<rect x={object.bbox[index][0]} y={object.bbox[index][1]} width={object.bbox[index][2]} height={object.bbox[index][3] }
style={{stroke:"red",paddingTop:"50px",strokeWidthTop:"20px"}} fill-opacity="0.0" />
</g>
)
}
</svg>
</div>
my attempt:
<div class="img-overlay-wrap" style={{ marginLeft: "27%" }}>
<GlassMagnifier className='img-overlay-wraps' imageSrc={object.name} />
<svg style={{ display: (this.state.isHide ? 'block' : 'none') }} width="512" height="512" >
{
object.bbox.map((val,index)=>
<g>
<rect x={object.bbox[index][0]} y={object.bbox[index][1]} width={object.bbox[index][2]} height={object.bbox[index][3] }
style={{stroke:"red",paddingTop:"50px",strokeWidthTop:"20px"}} fill-opacity="0.0" />
</g>
)
}
</svg>
</div>

flip an element inside SVG horizontally but keeps it's original position

I want to flip SVG elements (path, line, polyline, text ...) without changing the original position. For example
<div id="canvas" style="width: 550px; height: 550px">
<svg version="1.2" baseProfile="tiny" id="Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 250 250" xml:space="preserve">
<text id="text" transform="matrix(1 0 0 1 31.1271 199.1222)" fill="#561010" font-family="'Roboto-Regular'" font-size="25.3945px">Nom d’entreprise</text>
<g>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="76.157" y1="87.0921" x2="70.9488" y2="44.8529"> <stop offset="0.0233" style="stop-color:#E92460"></stop> <stop offset="0.4636" style="stop-color:#F05C4B"></stop> <stop offset="0.9517" style="stop-color:#F36D38"></stop> </linearGradient>
<path transform="matrix(1 0 0 1 0 0)" fill="url(#SVGID_2_)" d="M51.75,55.77c-0.27-0.39,3.97-5.2,10.38-7.74c1.79-0.71,11.97-4.75,21.31,0.8
c8.61,5.12,11.99,15.71,10.53,24.27c-2.38,13.95-17.76,23.37-22.24,20.72c-0.97-0.57-1.32-2.75-1.99-7.09
c-1.81-11.84-1.68-20.54-1.68-20.54c0.05-3.05,0.19-4.38-0.61-6.25c-1.42-3.32-4.9-6.23-8.62-6.47
C54.84,53.21,51.97,56.08,51.75,55.77z"></path>
</g>
</svg>
</div>
I tried various solution such as changing transform to matrix(-1 0 0 1 -100 0). Also I have tried to add attribute transform-origin="center".
All I reached is a missplaced element. I have been trying the following:
flipHorizontal(){
let viewBox_array = this.getViewBox(); // this returns ['0', '0', '250', '250']
let canvas_width = $("#canvas").width();
this.selectedElements.forEach(element =>{
let element_width = element.getBoundingClientRect().width
element.setAttribute("transform-origin", "center")
var matrix = element.transform.baseVal[0].matrix;
matrix.a = (-1) * matrix.a
let diff = (element_width / (canvas_width / Number(viewBox_array[2])) )* Math.sign(matrix.a);
matrix.e += diff;
});
this.edit_done();
}
Also tried the following
flipHorizontal(){
this.selectedElements.forEach(element =>{
element.setAttribute("transform-origin", "center")
let bbox = element.getBBox();
var matrix = element.transform.baseVal[0].matrix;
matrix.a = (-1) * matrix.a
matrix.e += Math.sign(matrix.a) * (bbox.width + bbox.x);
});
this.edit_done();
}
As detailed in my answer here, the transform functions needed to flip in place are:
translate(<minX+maxX>,0) scale(-1, 1)
So, a working version of your code, might look something like this:
function flipHorizontal(selectedElements) {
selectedElements.forEach(element => {
// Get the bounds of the element
let bbox = element.getBBox();
// Get the current transform attribute (if any) of the element
let currentTransform = element.getAttribute("transform") || "";
// Append translate and scale functions to the transform that will flip the element in place
element.setAttribute("transform", currentTransform + ' translate('+(bbox.x + bbox.x + bbox.width) + ',0) scale(-1, 1)');
});
}
let elementsToFlip = document.querySelectorAll("path, text");
flipHorizontal( elementsToFlip );
<div id="canvas" style="width: 550px; height: 550px">
<svg version="1.2" baseProfile="tiny" id="Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 250 250" xml:space="preserve">
<text id="text" transform="matrix(1 0 0 1 31.1271 199.1222)" fill="#561010" font-family="'Roboto-Regular'" font-size="25.3945px">Nom d’entreprise</text>
<g>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="76.157" y1="87.0921" x2="70.9488" y2="44.8529"> <stop offset="0.0233" style="stop-color:#E92460"></stop> <stop offset="0.4636" style="stop-color:#F05C4B"></stop> <stop offset="0.9517" style="stop-color:#F36D38"></stop> </linearGradient>
<path transform="matrix(1 0 0 1 0 0)" fill="url(#SVGID_2_)" d="M51.75,55.77c-0.27-0.39,3.97-5.2,10.38-7.74c1.79-0.71,11.97-4.75,21.31,0.8
c8.61,5.12,11.99,15.71,10.53,24.27c-2.38,13.95-17.76,23.37-22.24,20.72c-0.97-0.57-1.32-2.75-1.99-7.09
c-1.81-11.84-1.68-20.54-1.68-20.54c0.05-3.05,0.19-4.38-0.61-6.25c-1.42-3.32-4.9-6.23-8.62-6.47
C54.84,53.21,51.97,56.08,51.75,55.77z"></path>
</g>
</svg>
</div>
You can do this with the only CSS, for example:
.logo_text--flipped, .logo_image--flipped {
transform-origin: center center;
transform: scaleX(-1);
}
<div id="canvas" style="width: 550px; height: 550px">
<svg version="1.2" baseProfile="tiny" id="Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 250 250" xml:space="preserve">
<g class="logo_text logo_text--flipped">
<text id="text" transform="matrix(1 0 0 1 31.1271 199.1222)" fill="#561010" font-family="'Roboto-Regular'" font-size="25.3945px">Nom d’entreprise</text>
</g>
<g class="logo_image logo_image--flipped">
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="76.157" y1="87.0921" x2="70.9488" y2="44.8529">
<stop offset="0.0233" style="stop-color:#E92460"></stop>
<stop offset="0.4636" style="stop-color:#F05C4B"></stop>
<stop offset="0.9517" style="stop-color:#F36D38"></stop>
</linearGradient>
<path transform="matrix(1 0 0 1 0 0)" fill="url(#SVGID_2_)" d="M51.75,55.77c-0.27-0.39,3.97-5.2,10.38-7.74c1.79-0.71,11.97-4.75,21.31,0.8
c8.61,5.12,11.99,15.71,10.53,24.27c-2.38,13.95-17.76,23.37-22.24,20.72c-0.97-0.57-1.32-2.75-1.99-7.09
c-1.81-11.84-1.68-20.54-1.68-20.54c0.05-3.05,0.19-4.38-0.61-6.25c-1.42-3.32-4.9-6.23-8.62-6.47
C54.84,53.21,51.97,56.08,51.75,55.77z"></path>
</g>
</svg>
</div>
So you can create a specific class and toggle it via JS

How to make svg RTL

I want to make svg RTL, meaning i want to change the origin from 'Top Left' to 'Top Right' in a way that when i say draw a path M 0 0 L 100 100, it creates a line that starts with top: 0, right: 0 and goes to top: 100, right: 100
I tried most common solution for changing origin but none of them work as i want it to
My code:
<svg
style={{ width: "100%", height: "100%", textAlign: "right" }}
//preserveAspectRatio="xMaxYMin meet"
>
<path stroke="green" strokeWidth="3" fill="none" d="M 0 0 L 100 100" />
</svg>
And here is a working example of the code
Translate and scale the canvas, though be warned any text will display RTL too.
<svg width="200" height="200">
<g transform="translate(200, 0) scale(-1, 1)">
<path stroke="green" strokeWidth="3" fill="none" d="M 0 0 L 100 100" />
</g>
</svg>

Create SVG components with scoped CSS

I am creating React components that will render out various SVGs:
const Close = ({
fill, width, height, float,
}) => (
<svg width={ `${width}px` } height={ `${height}px` } viewBox="0 0 14.48 14.48" style={ { float: `${float}`, cursor: 'pointer' } }>
<title>x</title>
<g id="Layer_2" data-name="Layer 2">
<g id="Background">
<line style={ { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 } } x1="14.13" y1="0.35" x2="0.35" y2="14.13" />
<line style={ { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 } } x1="14.13" y1="14.13" x2="0.35" y2="0.35" />
</g>
</g>
</svg>
);
It's very convenient to be able to supply various attributed to this component to control dimensions, colour, etc...
What I don't have a good solution for, however, is handling the styles in a DRY manner. Note the line elements have the same value for style. I presently have them written inline because if I added an embedded stylesheet, then I would get class name collisions with other SVGs I render elsewhere on the page (our SVG software uses the same classes over and over).
<style scoped> has been removed from the spec: https://github.com/whatwg/html/issues/552
Shadow DOM is not yet supported by Edge: https://caniuse.com/#feat=shadowdomv1
Is there any other alternative for scoping styles?
To combine the best of both worlds, you could create an external styles file, as you would for CSS, but with exported style objects. You could then import it into any file that needs it.
As example, main file:
import React, { Component } from 'react';
import { render } from 'react-dom';
import * as Styles from './svgstyles';
class App extends Component {
render() {
return (
<div>
<svg width="100" height="200" viewBox="0 0 100 200">
<rect x="0" y="0" width="10" height="10" style={Styles.style1} />
<rect x="15" y="0" width="10" height="10" style={Styles.style2} />
<rect x="30" y="0" width="10" height="10" style={Styles.style3} />
<rect x="45" y="0" width="10" height="10" style={Styles.style4} />
<rect x="0" y="15" width="10" height="10" style={Styles.style4} />
<rect x="15" y="15" width="10" height="10" style={Styles.style3} />
<rect x="30" y="15" width="10" height="10" style={Styles.style2} />
<rect x="45" y="15" width="10" height="10" style={Styles.style1} />
</svg>
</div>
);
}
}
render(<App />, document.getElementById('root'));
And an external styles file:
export const style1 = {
stroke: 'red',
strokeWidth: "1",
fill: "blue",
}
export const style2 = {
stroke: 'red',
strokeWidth: "1",
fill: "green",
}
export const style3 = {
stroke: 'red',
strokeWidth: "1",
fill: "yellow",
}
export const style4 = {
...style3,
fill: "pink",
}
Live example here
If you just want to DRY up the code, you could create one style-object and reuse it:
const Close = ({
fill, width, height, float,
}) => {
const style = { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 }
return (
<svg width={ `${width}px` } height={ `${height}px` } viewBox="0 0 14.48 14.48" style={ { float: `${float}`, cursor: 'pointer' } }>
<title>x</title>
<g id="Layer_2" data-name="Layer 2">
<g id="Background">
<line style={ style } x1="14.13" y1="0.35" x2="0.35" y2="14.13" />
<line style={ style } x1="14.13" y1="14.13" x2="0.35" y2="0.35" />
</g>
</g>
</svg>
);
}
This would also result in a small performance improvement since fewer objects would be created in each render cycle.
Actually, if I was in your place, Surely I use fonts instead of SVGs, but for your exact question, I prefer to use constant variables inside of my arrow function, just like below:
import React from 'react';
const Close = ({ fill, width, height, float }) => {
const constStyle = { fill: 'none', stroke: `${fill}`, strokeMiterlimit: 10 };
return (
<svg
width={`${width}px`}
height={`${height}px`}
viewBox="0 0 14.48 14.48"
style={{ float: `${float}`, cursor: 'pointer' }}
>
<title>x</title>
<g id="Layer_2" data-name="Layer 2">
<g id="Background">
<line style={constStyle} x1="14.13" y1="0.35" x2="0.35" y2="14.13" />
<line style={constStyle} x1="14.13" y1="14.13" x2="0.35" y2="0.35" />
</g>
</g>
</svg>
);
};
export default Close;
Even, I make the line dimension variables as props, but I don't know what is your case exactly.
Hope this answer helps you.

Resources