In React I have a svg file such as mySVG.svg
<svg width="50" height="50" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<rect id="Unit1" class="class1" x="0" y="0" width="10" height="10" fill="blue"/>
<rect id="Unit2" class="class1" x="10" y="10" width="10" height="10" fill="blue"/>
<rect id="Unit3" class="class2" x="20" y="20" width="10" height="10" fill="blue"/>
</svg>
Then, in the component file Example.tsx
, I would like to dynamically set the svg's colors based on passed in props
import { ReactComponent as mySvg} from 'assets/mySVG.svg';
export function Example(props:{highlighted:string}):ReactElement {
if (props.highlighted === 'Unit1') {
return (
<mySvg
//set unit 1 fill color to red
/>
);
}
return (
<mySvg />
);
}
How would I accomplish dynamically setting the fill color of the svg based on id and className of the svg paths?
Importing a static css file with the colors defined won't work because I need this to work dynamically.
Given the svg file mySVG.svg
<svg width="50" height="50" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<rect id="Unit1" class="class1" x="0" y="0" width="10" height="10" fill="blue"/>
<rect id="Unit2" class="class1" x="10" y="10" width="10" height="10" fill="blue"/>
<rect id="Unit3" class="class2" x="20" y="20" width="10" height="10" fill="blue"/>
</svg>
I created a helper function to get the DOM of a given Ref getDOMNodeById.ts
export type DOMNode = Element | ChildNode | Text | null;
export function getDOMNodeById(componentDOMNode:DOMNode, id:string): DOMNode | void {
if (componentDOMNode?.nodeType === Node.ELEMENT_NODE) {
const element = componentDOMNode as Element;
if (element.id === id) {
return element;
}
else if (element.hasChildNodes()) {
for (let i=0; i<element.childNodes.length; i++) {
const childNode = element.childNodes[i];
const result = getDOMNodeById(childNode, id);
if (result) {
return result;
}
}
}
}
}
export const isHTMLElement = (v:any): v is HTMLElement => {
return v instanceof Element || v instanceof HTMLElement;
}
Tying it all together, add a Ref to the svg react component, call the helper function to grab the DOM of Ref, then mutate the returned Element Example.tsx
import { ReactComponent as mySvg} from 'assets/mySVG.svg';
import { DOMNode, getDOMNodeById, isHTMLElement } from './getDOMNodeById';
export function Example(props:{highlighted:string}):ReactElement {
const svgRef = useRef(null);
const svgDOM = ReactDOM.findDOMNode(svgRef.current);
if (props.highlighted === 'Unit1') {
const unit = getDOMNodeById(svgDOM, 'Unit1');
if (isHTMLElement(unit)) {
unit.style.fill = 'red';
}
}
return (
<mySvg ref={svgRef} />
);
}