我正在开始我的第一个 React/Next.js 项目,我需要导入一个 SVG 文件并在渲染之前对其进行修改。 我试图找到一些可以让我做到这一点的模块,然后我选择了react-svg https://github.com/tanem/react-svg/ 在开发过程中,一切都按需要进行。 当我试图抑制来自 ESLINT 尝试部署的警告和错误时,问题就出现了。
我像这样使用ReactSVG:
'use client'
import { ReactSVG } from "react-svg";
...
const Page = () => {
...
const attachTurnsToSvg = (elements = []) => {
elements.forEach((element: SVGRectElement) => {
//insert text inside SVGelements
});
};
const attachCallsToSvg = (elements = []) => {
elements.forEach((element: SVGCircleElement) => {
element.addEventListener('click', (e) => {
console.debug('clicked', e);
});
});
};
return(
<>
...
<ReactSVG
src="/mysvg.svg"
beforeInjection={(svg) => {
const svgWidth = (width !== undefined ? 0.625 * width : 1200);
const svgHeight = (height !== undefined ? 0.88 * height : 800);
svg.setAttribute('style', `width: ${svgWidth}px; height: ${svgHeight}px;`);
}}
afterInjection={(svg: { querySelectorAll: (arg0: string) => never[]; }) => {
const rects = svg?.querySelectorAll('rect.turnRect') || [];
attachTurnsToSvg(rects);
const circles = svg?.querySelectorAll('circle.callCircle') || [];
attachCallsToSvg(circles);
}}
className={styles.map}
/>
</>)
}
export default Page;
开发中一切似乎都工作正常,但是我收到了错误:
“JSX 元素类不支持属性,因为它没有 'props' 属性。”,
“ReactSVG”不能用作 JSX 组件。
其类型“typeof ReactSVG”不是有效的 JSX 元素类型。
类型“typeof ReactSVG”不可分配给类型“new (props:any, deprecatedLegacyContext?:any) => Component
并且无法构建应用程序。
其他一切都按我的预期工作,但我似乎找不到其他解决方案来使其工作......
我建议定义您自己的 SVG 组件,因为这将使将来的自定义变得更加容易。从 SVG 中提取内容(如果可能,将重复元素转换为地图循环)。
例如:
const circles = [{ cy: 20, cx: 20, fill: "red", ... }, ...]
const rects = [{ y: 0, x: 0, textToInsert: "Hello", ... }, ...]
export default function MySVG() {
return <svg width={1200} height={800}>
{circles.map(circleProps => <circle {...circleProps} className="callCircle" onClick={(e) => console.log("clicked", e)} />)}
{rect.map(({ textToInsert, ...rectProps }) => <>
<rect {...rectProps} className="turnRect" onClick={(e) => console.log("clicked", e)} />
{ /* You cannot insert a SVG text inside a rect, but you can overlay it */ }
<text x={rectProps.x} y={rectProps.y}>{textToInsert}</text>
</>)}
<svg/>
}
import MySVG from "./MySVG.tsx";
const Page = () => {
return <MySVG />;
}
export default Page;
对于您的用例来说,这可能不是一个理想的解决方案,但这种方法将允许您对 SVG 进行更多自定义,同时具有更多“React-y”方法,而不是使用在初始渲染后计算的本机 JS 查询选择器。
但是,如果您需要修改用例中预先存在的 SVG,则可以在
useEffect
中使用本机 JS 来完成此操作。例如:
import { useEffect, useRef } from 'react';
import MySvg from "/mysvg.svg"; // use SVGR or babel-plugin-inline-react-svg to directly render an inline SVG
export default function Page() {
const svgRef = useRef(null);
useEffect(() => {
if (svgRef.current) {
const rects = svg?.querySelectorAll('rect.turnRect') || [];
// do stuff with rects
const circles = svg?.querySelectorAll('circle.callCircle') || [];
// do stuff with circles
}
}, [svgRef.current])
return <MySvg height={800} width={1200} />
}
您可以在线找到教程,将 SVGR 或类似的 SVG 解析器设置到您的 NextJS 项目中。
我希望这有帮助。请随时发表评论以提出进一步的问题:)!