【问题标题】:Display image in d3.js from Android tablet image path从 Android 平板电脑图像路径在 d3.js 中显示图像
【发布时间】:2014-01-30 18:18:21
【问题描述】:

我正在使用 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,但我不知道如何提取元素,select("g"), selectAll , 等等。我也不知道如何将该路径带入 xlink:href。我只是将图像放入 Android 资产 / 这根本不是通用的。我想使用任何路径插入图片作为屏幕背景。

此外,我想使用graph1.json.php中获得的宽度和高度在update-anim.html中设置。我想知道这是否可能,或者我是否必须仅通过 JavaScript 进行设置。

有人可以帮我吗?

【问题讨论】:

    标签: javascript android json image d3.js


    【解决方案1】:

    你的样本数据格式是

    {
      "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"}
    }
    

    因此,当您读入数据时,您的数据对象中有路径。您只需在数据处理函数 (joinGraph()) 中设置 <image> 元素的 xlink:href。您仍然可以在初始化时创建图像元素,无需源路径,然后将其保存在变量中或稍后重新选择它。

    /* 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
    

    【讨论】:

    • background.attr("xlink:href", graph.mapImage.path);在 joinGraph() 中无论如何都不会显示任何图片,即使我使用的是静态路径。
    • 你确定你有一个有效的图像文件路径吗?检查您的 DOM 检查器以验证是否正在创建图像并且其属性设置正确。然后检查您的控制台是否有错误消息。这是上面的代码作为一个简单的小提琴:fiddle.jshell.net/Sqt3F
    猜你喜欢
    • 2018-12-07
    • 1970-01-01
    • 2013-08-01
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多