通过D3_SAVE_SVG下载SVG后,React应用程序中断了
我正在原型型简单react
应用程序,其中用户能够与svg
使用d3
生成的svg
并下载从其交互中产生的SVG (尽管在原型制定阶段,React并不是特别有用,但是一旦原型扩展,最终将需要它)。
我偶然发现了d3-save-svg
库( https:// Github.com/edeno/d3-save-svg )确实很方便,我正在原型中测试它,以查看我是否可以依靠它来期待它。
从用户可以:
- 与
svg
进行交互的意义上,该原型正在“良好”,并 - 下载
svg
是由于其交互而产生的。
但是,依赖于d3-save-svg
下载svg
,似乎打破了与svg
的进一步互动,这是无意的。用户仍然能够重载svg
,但不能再与svg
进行交互。
谁能:
- 帮助我了解正在发生的事情和/或
- 提出一个修复程序,该修复程序允许用户通过第一个下载,与
svg
进一步交互并重新下载其进一步交互的结果?
这是原型代码( https://codesandbox.io/sandbox.io/goofy-hellman-quccpppyd < /a>):
import { useRef, useEffect } from "react";
import * as d3 from "d3";
import d3_save_svg from "d3-save-svg";
export default function App() {
const ref = useRef();
useEffect(() => {
const svg = d3
.select(ref.current)
.append("svg")
.attr("width", 500)
.attr("height", 500);
svg
.append("circle")
.attr("cx", 400)
.attr("cy", 300)
.attr("r", 100)
.attr("fill", "blue");
svg
.append("text")
.text("Move")
.attr("x", 100)
.attr("y", 100)
.attr("cursor", "pointer")
.on("click", function () {
svg.selectAll("circle").attr("cx", function () {
return d3.select(this).attr("cx") - 10;
});
});
svg
.append("path")
.attr(
"d",
"M896 672q119 0 203.5 84.5t84.5 203.5-84.5 203.5-203.5 84.5-203.5-84.5-84.5-203.5 84.5-203.5 203.5-84.5zm704-416q106 0 181 75t75 181v896q0 106-75 181t-181 75h-1408q-106 0-181-75t-75-181v-896q0-106 75-181t181-75h224l51-136q19-49 69.5-84.5t103.5-35.5h512q53 0 103.5 35.5t69.5 84.5l51 136h224zm-704 1152q185 0 316.5-131.5t131.5-316.5-131.5-316.5-316.5-131.5-316.5 131.5-131.5 316.5 131.5 316.5 316.5 131.5z"
)
.attr("transform", "translate(200 100) scale(0.02)")
.attr("class", "snap-button")
.attr("fill", "#1976d2")
.attr("cursor", "pointer")
/* .html(iconHtml) */
.on("click", function () {
var config = {
filename: "customFileName"
};
d3_save_svg.save(d3.select("svg").node(), config);
});
});
return <div ref={ref} />;
}
I am prototyping a simple React
App where the user is able to interact with an SVG
generated with d3
and download the SVG that results from their interaction (though React isn't especially useful at the prototyping stage, it will be required eventually once the prototype is expanded upon).
I stumbled upon the d3-save-svg
library (https://github.com/edeno/d3-save-svg) which is really handy and I am testing it in my prototype to see if I can rely on it looking forward.
The prototype is working "well" in the sense that the user is able to:
- Interact with the
SVG
, and - Download the
SVG
resulting from their interaction.
However downloading the SVG
, which relies on d3-save-svg
, appears to break further interactivity with the SVG
, which is unintended. The user is still able to redownload the SVG
but cannot interact with the SVG
anymore.
Can anyone:
- Help me understand what's going on, and/or
- Propose a fix that would allow the user to, pass the first download, interact further with the
SVG
and redownload the result of their further interactions?
Here is the prototype code (https://codesandbox.io/s/goofy-hellman-qcppyd):
import { useRef, useEffect } from "react";
import * as d3 from "d3";
import d3_save_svg from "d3-save-svg";
export default function App() {
const ref = useRef();
useEffect(() => {
const svg = d3
.select(ref.current)
.append("svg")
.attr("width", 500)
.attr("height", 500);
svg
.append("circle")
.attr("cx", 400)
.attr("cy", 300)
.attr("r", 100)
.attr("fill", "blue");
svg
.append("text")
.text("Move")
.attr("x", 100)
.attr("y", 100)
.attr("cursor", "pointer")
.on("click", function () {
svg.selectAll("circle").attr("cx", function () {
return d3.select(this).attr("cx") - 10;
});
});
svg
.append("path")
.attr(
"d",
"M896 672q119 0 203.5 84.5t84.5 203.5-84.5 203.5-203.5 84.5-203.5-84.5-84.5-203.5 84.5-203.5 203.5-84.5zm704-416q106 0 181 75t75 181v896q0 106-75 181t-181 75h-1408q-106 0-181-75t-75-181v-896q0-106 75-181t181-75h224l51-136q19-49 69.5-84.5t103.5-35.5h512q53 0 103.5 35.5t69.5 84.5l51 136h224zm-704 1152q185 0 316.5-131.5t131.5-316.5-131.5-316.5-316.5-131.5-316.5 131.5-131.5 316.5 131.5 316.5 316.5 131.5z"
)
.attr("transform", "translate(200 100) scale(0.02)")
.attr("class", "snap-button")
.attr("fill", "#1976d2")
.attr("cursor", "pointer")
/* .html(iconHtml) */
.on("click", function () {
var config = {
filename: "customFileName"
};
d3_save_svg.save(d3.select("svg").node(), config);
});
});
return <div ref={ref} />;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
事实证明,
d3_save_svg
在导出SVG之前修改了DOM,并在其中添加了许多内容,包括样式。似乎,由于这发生在React的渲染周期之外,因此React将其裁判丢失,并失去了SVG所需的隐式状态。一种解决方案是将导出基于
svg
的克隆版本,然后在导出后立即删除,从而保证用户永远不会看到复制品(如果需要的话,可以有其他其他确保用户永远不会看到副本的方法,例如在Viewbox之外找到副本)。Turns out
d3_save_svg
modifies the DOM before it exports the svg, adding a number of things to it including styles. It seems that, since this happens outside of react's rendering cycle, React looses its refs and looses track of the SVG's desired implicit state.A solution is to base the export on a clone version of the
SVG
which you can then remove right after the export, thereby guaranteeing the copy is never actually visible to the user (if desired, there can be other ways to do ensure the user never sees the copy, such as locating the copy outside of the viewbox).