问题
I am experiencing issues when rendering a d3 svg graph with polylines. It does work on chrome Version 70.0.3538.67 (Official Build) (64-bit) but not on my current version Version 78.0.3904.108 (Official Build) (64-bit). I am using d3 version v5.9.2.
The issue does not occur when I remove the polylines connecting my d3 rendered foreign objects.
The "shadows", moves around depending on how I move the picture around/zooming, sometimes all of them are gone but a few shadows are most often shown.
I read that dashed lines might cause this, but I have the same issue even if the polylines are normal.
The code I have for rendering the SVG graph looks as follows:
// Function to generate entire d3 tree structure
function graphFoundObjects(response) {
currentFlowchartView = "graphMode";
var graphWidth = jQuery("#outputWrapperFlowchart").width();
var graphHeight = jQuery("#outputWrapperFlowchart").height();
var nodeWidth = 320;
var nodeHeight = 90;
var outputContainerFlowchart = createOutputContainerFlowchart("outputContainerFlowchartChart");
appendElementToDom("outputWrapperFlowchart", outputContainerFlowchart);
var graphWrapper = jQuery("#outputContainerFlowchartChart").append("<svg id='graphWrapper'></svg>");
var graphSvg = d3.select("#graphWrapper").attr("width", graphWidth).attr("height", graphHeight);
var simulation = d3.forceSimulation(response.nodes)
.force("charge", d3.forceManyBody().strength(-78000))
.force("center", d3.forceCenter(graphWidth / 2, graphHeight / 2))
.force("link", d3.forceLink(response.links).id(function(d) {return d.uuid; }).distance(250).strength(1))
.force("x", d3.forceX(graphWidth / 2).strength(1))
.force("y", d3.forceY(graphHeight / 2).strength(1))
.stop();
// Fix setting instead so you can choose if you want to center root node by calling the function
response.nodes[0].firstNode = true;
function centerFirstNode() {
graph.nodes[0].fixed = true;
graph.nodes[0].fx = width / 2;
graph.nodes[0].fy = height / 2;
}
d3.timeout(function() {
for (var i = 0, n = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())); i < n; ++i) {
simulation.tick();
}
var g = graphSvg.append("g")
.attr("class", "everything");
var arrow = g.append("defs").append("marker")
.attr("id", "arrow")
.attr("viewBox", "0 -5 10 10")
.attr("refX", 0)
.attr("refY", 0)
.attr("markerWidth", 7)
.attr("markerHeight", 7)
.attr("orient", "auto")
.attr("fill", "#7e7878")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
var links = g.append("g")
.attr("stroke", "#ebebeb")
.attr("stroke-width", 2)
.selectAll("polyline")
.data(response.links)
.enter().append("polyline")
.attr("points", function(d) {
return [
d.source.x, d.source.y,
d.source.x/2+d.target.x/2, d.source.y/2+d.target.y/2,
d.target.x, d.target.y
].join(',');
})
.style("marker-mid", "url(#arrow)");
var nodes = g.selectAll("foreignObject")
.data(response.nodes)
.enter()
.append("foreignObject")
.attr("x", function(d) {
return d.x - nodeWidth / 2;
})
.attr("y", function(d) {
return d.y - nodeHeight / 2;
})
.attr("width", nodeWidth)
.attr("height", nodeHeight)
.attr("class", function(d) {
return ("graphNode "+d.group)
})
.style("background-color", function(d) {
return "#fffefe";
})
.append("xhtml:div")
.attr("class", function(d) {
if (d.firstNode !== undefined) {
return "graphNodeDiv graphFirstNode";
} else {
return "graphNodeDiv";
}
})
.html(function(d) {
var nodeHtml = createNodeElement(d);
var firstNodeClass = "";
return nodeHtml.outerHTML;
})
.on("click", function(d) {
renderPopupWindow(d, "#outputWrapperFlowchart");
})
.append("img")
.attr("class", "optionsImg")
.attr("src","/images/options-squares.svg")
.on("click", function(d) {
currentTooltipObject = d;
renderTooltipDiv();
});
// Define the div for the tooltip
var toolTip = d3.select("#outputWrapperFlowchart").append("div")
.attr("class", "tooltip")
.attr("id", "tooltip")
.style("display", "none")
.style("opacity", 1);
// Add drag capabilities
var drag_handler = d3.drag()
.on("start", drag_start)
.on("drag", drag_drag)
.on("end", drag_end);
drag_handler(nodes);
// Add zoom capabilities
var zoom_handler = d3.zoom()
.on("zoom", zoom_actions);
zoom_handler(graphSvg);
// Drag functions
function drag_start(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
// Make sure you can't drag the circle outside the box
function drag_drag(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function drag_end(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
//Zoom functions
function zoom_actions(){
g.attr("transform", d3.event.transform)
}
function renderTooltipDiv() {
event.stopPropagation();
toolTip.transition()
.duration(200)
.style("opacity", .9);
toolTip
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
jQuery(".tooltip").empty();
toolTip.append("div").attr("class", "optionsActionWrapper").attr("id", "optionActionWrapperRedraw").append("div").attr("class", "optionText").text("Redraw");
toolTip.append("div").attr("class", "optionsActionWrapper").attr("id", "optionActionWrapperModify").append("div").attr("class", "optionText").text("Modify");
toolTip.append("div").attr("class", "optionsActionWrapper").attr("id", "optionActionWrapperRemove").append("div").attr("class", "optionText").text("Remove");
jQuery("#optionActionWrapperRedraw").prepend("<img class=\"optionsIcon\" src=\"/images/redraw-icon.svg\">");
jQuery("#optionActionWrapperModify").prepend("<img class=\"optionsIcon\" src=\"/images/modify-icon.svg\">");
jQuery("#optionActionWrapperRemove").prepend("<img class=\"optionsIcon\" src=\"/images/remove-icon.svg\">");
tooltipState = true;
jQuery(".tooltip").css("display", "block");
}
});
}
Am I doing something wrong, or can I bypass this (most likely) bug somehow?
回答1:
the bug is resulted by chrome hardware acceleration. When i disabled the feature, it works fine. But, it is not good idea. Even my case doesn't use d3 forceSimulation, you can try to give the line "fill" style with value "transparent". It works for my case.
来源:https://stackoverflow.com/questions/58997729/chrome-svg-rendering-issues-d3-polylines