2014-01-30 3 views
1

Я использую Android для отправки данных на веб-просмотр d3.js в формате JSON. У меня возникла проблема. Здесь у меня есть такой код d3.js. Я приложил пример этого кода, чтобы его можно было запустить. https://drive.google.com/file/d/0B7Ztdu46v0uOZjhvTG5HRlVRRG8/edit?usp=sharingПоказать изображение в d3.js с пути для Android-планшета

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

Ваш формат данных выборки

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

А как выяснить ширину и высоту SVG с помощью CSS размера, вы используете window.getComputedStyle(), чтобы получить фактическую длину пикселя, который используется. Обратите внимание, что если есть вероятность, что ваш код также будет использоваться в Firefox, вы должны установить CSS display:block; или display:inline-block; на SVG - есть ошибка 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 
+0

background.attr ("xlink: href", graph.mapImage.path); в joinGraph() в любом случае не отображается изображение, хотя я использую статический путь. – user3170377

+1

У вас есть правильный путь к файлу изображения? Проверьте своего инспектора DOM, чтобы убедиться, что изображение создано и его атрибуты установлены правильно. Затем проверьте консоль на наличие сообщений об ошибках. Вот код выше, как простая скрипка: http://fiddle.jshell.net/Sqt3F/ – AmeliaBR

+0

Я получил его прямо сейчас. Спасибо огромное! – user3170377

Смежные вопросы