在Android平板电脑图片路径中显示d3.js中的图片

时间:2014-01-30 18:18:21

标签: javascript android json image d3.js

我使用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设置它。

有人可以帮我吗?

1 个答案:

答案 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