我使用Android以JSON格式将数据发送到d3.js webview。 我遇到了一个问题。在这里,我有一个像这样的d3.js代码。 我已附加此代码的示例,以便它可以运行。 https://drive.google.com/file/d/0B7Ztdu46v0uOZjhvTG5HRlVRRG8/edit?usp=sharing
var RADIUS = 5;
var moved = false;
var graph = {};
var nodes, links;
var svg = d3.select("svg");
// Retreive SVG element's width and height
// TODO: This needs to be fixed. This code terribly fails when width and
// height attributes are not specified in pixels.
var SVG_WIDTH = svg.attr('width');
var SVG_HEIGHT = svg.attr('height');
svg.append("image")
.attr("x", 0)
.attr("y", 0)
.attr("xlink:href", "Map.jpg")
.attr("width", SVG_WIDTH)
.attr("height", SVG_HEIGHT);
svg.append("defs")
.append("marker")
.attr("id", "head")
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", 0)
.attr("markerWidth", 2)
.attr("markerHeight", 2)
.attr("orient", "auto")
.attr("class", "link")
.append("path")
.attr("d", "M0,-5L10,0L0,5");
var drag = d3.behavior.drag()
.origin(Object)
.on("drag", dragMove)
.on("dragend", dragEnd)
;
// Prepare a group to draw links
svg.append("g").attr("class", "links");
// Prepare a group to draw nodes
svg.append("g").attr("class", "nodes");
///////////////////////////////////////////////////////////////////
// Function to update SVG contents with current nodes and links
// info attached to each SVG element (including the newly added
// ones). Animation effects are performed if anim is true.
///////////////////////////////////////////////////////////////////
function update(anim) {
nodes.select(".node")
.classed("gw", function(d)
{
return graph.nodes[d].type == 'gw';
});
if (anim)
{
updatedNodes = nodes.transition().duration(300).ease("linear");
updatedLinks = links.transition().duration(300).ease("linear")
.attr("opacity", "1");
}
else
{
updatedNodes = nodes;
updatedLinks = links;
}
updatedLinkShadow = linkShadow;
updatedNodes.attr("transform", function(d) {
return "translate(" + graph.nodes[d].pos + ")";
});
updatedLinks.attr("d", drawLink);
updatedLinkShadow.attr("d", drawLink);
}
function drawLink(pair) {
console.log(pair);
var dx = graph.nodes[pair[0]].pos[0] - graph.nodes[pair[1]].pos[0];
var dy = graph.nodes[pair[0]].pos[1] - graph.nodes[pair[1]].pos[1];
var dist = Math.sqrt(dx*dx+dy*dy);
return "M" + graph.nodes[pair[0]].pos
+ "A" + dist + "," + dist + " 0 0,0 " +
graph.nodes[pair[1]].pos;
}
///////////////////////////////////////////////////////////////////
// Function to perform data join between the graph model ('graph')
// and SVG elements
///////////////////////////////////////////////////////////////////
function joinGraph() {
//////////////////////
// Link data join
//////////////////////
links = svg.select("g.links").selectAll("path.link")
.data(graph.links, function(d) { return d;});
linkShadow = svg.select("g.links").selectAll("path.linkshadow")
.data(graph.links, function(d) { return d;});
linkShadow.enter()
.append("path")
.classed("linkshadow", true)
.attr("marker-end", "url(#head)")
.attr("d", drawLink)
.attr("opacity","1")
links.enter()
.append("path")
.classed("link", true)
//.attr("marker-end", "url(#head)")
.attr("d", drawLink)
.attr("opacity","0")
var goneLinks = links.exit();
linkShadow.exit().remove();
// Node data join
// *Notes* Set key to be value rather than index
nodes = svg.select("g.nodes").selectAll("g")
.data(d3.keys(graph.nodes), Number);
// Nodes just appearing
var newNodes = nodes.enter().append("g").call(drag);
// Nodes no longer exist
var goneNodes = nodes.exit();
newNodes
.append("circle")
.attr("r", RADIUS)
.classed("node", true)
;
newNodes
.append("text")
.attr("x", RADIUS+2)
.attr("y", RADIUS+2)
.attr("class", "shadow")
.text(String)
;
newNodes
.append("text")
.attr("x", RADIUS+2)
.attr("y", RADIUS+2)
.attr("fill", "blue")
.text(String)
;
// Update SVG elements with animation
update(true);
// Remove nodes and links that no longer exist
goneNodes
.transition().duration(300).ease("linear")
.attr("transform", "translate(0,0)")
.remove();
goneLinks
.attr("opacity", "1")
.transition().duration(300).ease("linear")
.attr("opacity", "0")
.remove();
}
///////////////////////////////////////////////////////////////////
// Function to be called by D3 when a node SVG element is dragged.
// The new position is updated to the 'graph' variable and then the
// corresponding SVG elements.
///////////////////////////////////////////////////////////////////
function dragMove(d) {
// Update position of the dragged node in the graph model
var newpos = graph.nodes[d].pos;
newpos[0] += d3.event.dx;
newpos[1] += d3.event.dy;
newpos[0] = Math.max(0, Math.min(newpos[0], SVG_WIDTH));
newpos[1] = Math.max(0, Math.min(newpos[1], SVG_HEIGHT));
// Update SVG elements without animation
update(false);
moved = true;
}
///////////////////////////////////////////////////////////////////
// Function to be called by D3 when a node SVG element is dropped.
///////////////////////////////////////////////////////////////////
function dragEnd(d) {
if (moved)
{
d3.select("#msg").text("Updating node " + d + " to database");
moved = false;
}
else
d3.select("#msg").text("Showing " + d + " details");
}
///////////////////////////////////////////////////////////////////
// *FOR TESTING* Function to be called when test buttons are clicked.
// It reloads a graph from the given name in form of JSON
///////////////////////////////////////////////////////////////////
function reload(g) {
d3.json("./" + g + ".json.php", function(json)
{
graph = json;
joinGraph();
});
}
我的JSON数据位于graph1.json.php文件中。 我想在Android平板电脑中添加路径图片,例如/mnt/sdcard/DCIM/Camera/Map.jpg,但我不知道如何提取元素,选择(“g”),selectAll , 等等。我也不知道如何将该路径引入xlink:href。我只是将图像放入Android资产/根本不是多功能的。我想使用任何路径将图片作为屏幕背景插入。
此外,我想使用graph1.json.php中获得的宽度和高度在update-anim.html中设置。我想知道这是否可行,或者我是否必须通过JavaScript设置它。
有人可以帮我吗?
答案 0 :(得分:2)
您的样本数据格式为
{
"nodes": {
"1": {"pos":[100,200], "type":"gw" },
"2": {"pos":[330,150], "type":"node" },
"3": {"pos":[130,150], "type":"node" },
"5": {"pos":[230,100], "type":"gw" },
"10": {"pos":[430,200], "type":"node" }
},
"links": [[3,5],[1,2],[10,1],[1,3],[3,1]]
"mapimage": {"path":"/mnt/sdcard/DCIM/Camera/Map.jpg",
"width":"1280", "height"":"720"}
}
因此,当您读入数据时,您将拥有数据对象中的路径。您只需在数据处理函数(xlink:href
)中设置<image>
元素的joinGraph()
即可。您仍然可以在初始化时创建图像元素,而不使用源路径,然后将其保存在变量中或稍后重新选择。
/* Initialization */
var background = svg.append("image")
.attr("x", 0)
.attr("y", 0)
.attr("preserveAspectRatio", "xMidYMid slice")
// This prevents the aspect ratio from being distorted;
// skip if the image can be stretched to fit.
// xMidYMid will center the image in the SVG;
// slice means that it will be sized big enough to cover
// the background, even if some of the image is cut off.
// Use "xMidYMid meet" if you want the whole image shown
// even if that leaves empty space on the sides
.attr("width", SVG_WIDTH)
.attr("height", SVG_HEIGHT);
/* Link to data */
function joinGraph() {
background.attr("xlink:href", graph.mapImage.path);
/* The rest of the joinGraph method is the same */
}
至于如何计算CSS大小的SVG的宽度和高度,可以使用window.getComputedStyle()
来获取正在使用的实际像素长度。但请注意,如果您的代码也有可能在Firefox上使用,则必须在SVG上设置CSS display:block;
或display:inline-block;
- 这是一个firefox错误在内联SVG上提供未处理的宽度和高度值。
var svg = d3.select("svg")
var SVG_WIDTH = parseFloat( getComputedStyle(svg.node())['width'] );
var SVG_HEIGHT = parseFloat( getComputedStyle(svg.node())['height'] );
//selection.node() extracts the first (and only) svg DOM element
//from the selection, so it can be used by Javascript functions
//getComputedStyle returns height and width as pixel lengths
//parseFloat strips off the "px" to return a number