React Template Literals don't work on SVG? - javascript

I have rendered an svg and morphed it using mouse position in vanilla javascript.
Here is an example(make sure to refresh the page since it doesnt start automatically for some reason): https://codesandbox.io/s/svg-shape-change-mouse-position-sjl0z
In vanilla js I did the following:
path.setAttribute("d", `M82 ${coords.y}L0 0H123V170H0L82 ${coords.y}Z`)
The problem:
I can't implement the same logic in React. Whenever I add the template literals
to the svg path it wont accept it.
Here is my code: https://codesandbox.io/s/react-svg-shape-morph-mouse-position-r7mx9?file=/src/App.js
This react code gives me an error:
let shape = useRef(null);
console.log("thiss: " + shape.current);
shape.current.setAttribute("d", `M82 ${y}L0 0H123V170H0L82 ${y}Z`);
return (
<div className="App">
<svg viewBox="0 0 100% 100%" preserveAspectRatio="xMidYMid meet">
<path ref={shape} d="M82 88L0 0H123V170H0L82 88Z" fill="lightblue" />
{/* <path d="M82 88L0 0H123V170H0L82 ${y}Z" fill="#F9B300" /> */}
</svg>
<h1>{`x: ${x}; y: ${y};`}</h1>
</div>
);
How can I link the mouse position to the svg path shape?
(ps. edited the question to include code snipets)

Related

In an SVG map, how can I keep lines from doubling up on adjacent paths?

I'm drawing a simple US map with state borders drawn. Eventually there will be hover and click events. However, anywhere the states touch, the borders appear double thickness. On the assumption that there isn't something wrong with my shapes, how can I keep these lines from getting double thickness? Is there a CSS setting?
It's written in React, but I hope that's not relevant. In the end it's just path objects in a group in an svg.
export const USMap = (props: Props) => {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 959 593">
<title>Map of US States</title>
<g id="states">
{Object.entries(states).map(([abbreviation, state]) => (
<path key={abbreviation} d={state.dimensions} fill="#fff" stroke="#000" strokeWidth="1" />
))}
</g>
</svg>
);
};

How to add color to a path element in an svg dynamically with d3 and react

I have an SVG icon:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="12" />
<path class="svg-fill"
d="M12,2A10,10,0,1,0,22,12,10,10,0,0,0,12,2Zm1,3.3,1.35-1a8,8,0,0,1,4.38,3.34L18.34,9,17,9.49,13,6.7Zm-3.35-1L11,5.3V6.7L7,9.49,5.66,9,5.27,7.69A8.1,8.1,0,0,1,9.65,4.35ZM7.08,17.11l-1.14.1A7.94,7.94,0,0,1,4,12c0-.12,0-.23,0-.35l1-.73,1.38.48,1.46,4.34Zm7.42,2.48a7.83,7.83,0,0,1-5,0L8.81,18.1,9.45,17h5.11l.64,1.11ZM14.27,15H9.73L8.38,11,12,8.44,15.63,11Zm3.79,2.21-1.14-.1-.79-1.37,1.46-4.34L19,10.93l1,.73c0,.11,0,.22,0,.34A7.94,7.94,0,0,1,18.06,17.21Z" />
</svg>
Which I'm trying to render on a D3 graph by using:
svg
.append('image')
.attr('xlink:href', MyIcon)
How can I change the color of the path in the svg dynamically, as I will be running the append code from a function something like:
const renderIcon = (iconColor) => {
svg
.append('image')
.attr('xlink:href', MyIcon)
// code to apply color param to the icon path
}
Couldn't find a nice way of actually getting the above working. The solution that I ended up finding was to instead define my icons in an defs element within an svg element in the return statement of my component:
return (
<svg>
<defs>
<MyIcon color={myColor1} id="myIcon1" />
<MyIcon color={myColor2} id="myIcon2" />
</defs>
</svg>
)
Where MyIcon would look something like:
<g fill={color} id={id}>
// other svg elements
</g>
And then use them by appending a use element to the svg element and passing in the icons id attribute:
svg.append('use').attr('href', '#myIcon1');
svg.append('use').attr('href', '#myIcon2');

How we can reduce the number of svg icons inside React project?

I am working on a project which have around 100 icons inside the assets/icons folder. Some icons are quite similar such as trash(delete) icon with blue and red colour, and check icon with three different colour.
How we can pass the colour as props inside svg file. So that we can reduce the number of icon as much as possible.
Note : We don't want to make specific react component and pass the colour as props.
Here is an working example of my code. className="fill-red" will fill the colour in whole <svg /> . But how we can fill the colour in it's nested element like in <path/> or might be <rect/>
import { ReactComponent as Cross } from 'assets/icons/cross.svg';
import React from 'react';
const Alert = (props) => {
return (
<div>
<div className="flex items-start">
<Error className="mr-2 fill-red" />
{props.label}
</div>
</div>
);
};
export default Alert;
Here is my cross.svg
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.205 4.71967C15.4978 5.01256 15.4978 5.48744 15.205 5.78033L11.023 9.96229L15.205 14.1443C15.4979 14.4372 15.4979 14.9121 15.205 15.205C14.9121 15.4978 14.4372 15.4978 14.1443 15.205L9.96233 11.0229L5.78033 15.205C5.48744 15.4978 5.01256 15.4978 4.71967 15.205C4.42678 14.9121 4.42678 14.4372 4.71967 14.1443L8.90167 9.96229L4.71971 5.78033C4.42682 5.48744 4.42682 5.01256 4.71971 4.71967C5.0126 4.42678 5.48748 4.42678 5.78037 4.71967L9.96233 8.90163L14.1443 4.71967C14.4372 4.42678 14.9121 4.42678 15.205 4.71967Z"/>
</svg>

How can I add image on the tool-tip within SVG?

Trying to reference image on a tooltip within an SVG map. The reference is as the following:
<path
inkscape:connector-curvature="0"
id="BD"
data-info="<div>Bangladesh</div><div><img src="http://www.digi4health.org/wp-content/uploads/2018/09/bd.png" alt="Bangladesh mHealth" width="600" height="171"></div><div>Some Description</div>"
data-name="Bangladesh"
data-id="BD"
d="m 1486.5,431.9 -4.5,-10.1 -1.5,0.1 -0.2,4 -3.5,-3.3 1.1,-3.6 2.4,-0.4 1.6,-5.3 -3.4,-1.1 -5,0.1 -5.4,-0.9 -1.2,-4.4 -2.7,-0.4 -4.8,-2.7 -1.2,4.3 4.6,3.4 -3.1,2.4 -0.8,2.3 3.7,1.7 -0.4,3.8 2.6,4.8 1.6,5.2 2.2,0.6 1.7,0.7 0.6,-1.2 2.5,1.3 1.3,-3.5 -0.9,-2.6 5.1,0.2 2.8,3.7 1.5,3.1 0.8,3.2 2,3.3 -1.1,-5.1 2.1,1 -0.5,-4.6 z"
style="fill:#c1f4ff;fill-rule:evenodd" />
I have SVG world map, where I have added some descriptions in a popup info box related to my project. Currently, on the infobox I just have text. I am trying to include some pictures within the pop infobox.
Here I am sharing the full code for better understanding. Appreciate your support.
Your code is all wrong and I'm not very sure what are you asking. Take a look at the following example and tell me if this is what you need:
<svg viewbox = "1450 400 50 50">
<clipPath id="Bangladesh">
<path d="m 1486.5,431.9 l-4.5,-10.1 -1.5,0.1 -0.2,4 -3.5,-3.3 1.1,-3.6 2.4,-0.4 1.6,-5.3 -3.4,-1.1 -5,0.1 -5.4,-0.9 -1.2,-4.4 -2.7,-0.4 -4.8,-2.7 -1.2,4.3 4.6,3.4 -3.1,2.4 -0.8,2.3 3.7,1.7 -0.4,3.8 2.6,4.8 1.6,5.2 2.2,0.6 1.7,0.7 0.6,-1.2 2.5,1.3 1.3,-3.5 -0.9,-2.6 5.1,0.2 2.8,3.7 1.5,3.1 0.8,3.2 2,3.3 -1.1,-5.1 2.1,1 -0.5,-4.6 z"
/>
</clipPath>
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/darwin300.jpg" x="1450" y="400" height="50" width="50" clip-path="url(#Bangladesh)"/>
</svg>
I wasn't able to use your image since it comes from an http (not secure).

SVG rect goes to new position when wrapped in div with React

I am new to React, and I am having trouble with some formatting issues.
I have one react component, an SVG that is the background element. On it, I am trying to render several points, with annotations when you hover.
I am able to get the points to show when I simply return the point directly, but I need to wrap it in a div so I can add some text.
Working, rendering the point in the right place:
class InfoPoint extends Component {
render() {
return (
<rect x="10" y="93" width="15" height="12" rx="2" ry="2" fill="red" ></rect>
);
}
}
Not working, I cannot find the element when I wrap it in the div:
class InfoPoint extends Component {
render() {
return (
<div className="point">
<rect x="10" y="93" width="15" height="12" rx="2" ry="2" fill="red" ></rect>
</div>
);
}
}
<rect> elements must be inside an <svg> element. And <div> elements are invalid inside a <svg> element. You can't indiscriminately mix HTML and SVG elements together.

Categories

Resources