D3.js - 在 json 中使用嵌套数组绘制图像

D3.js - plotting images with nested array in json

我是d3新手,下面是我输入的json文件,

    {

"y_axis_list":["A","B","C","D","E","F","G"],

"Points":[
{
    "y": "A",
    "x": 10,
    "Persona":["link1"]
},
{
    "y" : "B",
    "x": 20,
    "Persona":["link2","link1"]
},
{
    "y" : "C",
    "x": 30,
    "Persona":["link2","link3"]
},
{
    "y" : "D",
    "x": 40,
    "Persona":["link2","link3"]
},
{
    "y" : "E",
    "x" : 50,
    "Persona":["link5","link6"]
},
{
    "y" : "F",
    "x" : 60,
    "Persona":["link7","link8"]
},
{
    "y" : "G",
    "x" : 70,
    "Persona":["link9","link10"]
}
]
}

以下是我的代码:

<!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <title>D3 v4 - linechart</title>
    <style>
    #graph {
        width: 900px;
        height: 500px;
    }
    .tick line {
        stroke-dasharray: 2 2 ;
        stroke: #ccc;
    }

    .x{
        display: none;
    }


    .y path{
        fill: none;
      stroke: none;
 /* set the CSS */
    }

.line {
  fill: none;
  stroke: steelblue;
  stroke-width: 2px;
}

div.tooltip {
  position: absolute;
  text-align: center;
  width: 60px;
  height: 28px;
  padding: 2px;
  font: 12px sans-serif;
  background: lightsteelblue;
  border: 0px;
  border-radius: 8px;
  pointer-events: none;
}


    </style>
    </head>

    <body>
    <div id="graph"></div>    



    <script src="https://d3js.org/d3.v4.min.js"></script>    

    <script>
    !(function(){
        "use strict"

        var width,height
        var chartWidth, chartHeight
        var margin
        var svg = d3.select("#graph").append("svg")
        var axisLayer = svg.append("g").classed("axisLayer", true)
        var chartLayer = svg.append("g").classed("chartLayer", true)

        var xScale = d3.scaleLinear()
        var yScale = d3.scalePoint()
        var align = 0
        var i=10;


        //d3.tsv("data1.tsv", cast,  main)
        d3.json("http://localhost/newest.json",cast)

        //データの方変換
        function cast(datafull) {
            console.log("got it");
            var data=datafull["Points"];enter code here

            data.forEach(function(data) {
            console.log(data.y);
            data.y = data.y;
            data.x = +data.x;
        });
            main(data,datafull);
        }

        function main(data,datafull) {
            console.log("in main");
            setSize(data,datafull)
            drawAxis()
            drawChart(data,datafull)    
        }

        function setSize(data,datafull) {
            width = document.querySelector("#graph").clientWidth
            height = document.querySelector("#graph").clientHeight

            margin = {top:40, left:100, bottom:40, right:0 }


            chartWidth = width - (margin.left+margin.right+8)
            chartHeight = height - (margin.top+margin.bottom)

            svg.attr("width", width).attr("height", height)

            axisLayer.attr("width", width).attr("height", height)

            chartLayer
                .attr("width", chartWidth)
                .attr("height", chartHeight)
                .attr("transform", "translate("+[margin.left, margin.top]+")")


            xScale.domain([0, d3.max(data, function(d) { return d.x; })]).range([0,chartWidth])
            yScale.domain(datafull["y_axis_list"]).range([chartHeight, 0]).align(1)

        }

        function drawChart(data,datafull) {

        console.log("in drawChart");
            var t = d3.transition()
                .duration(4000)
                .ease(d3.easeLinear)
                .on("start", function(d){ console.log("transiton start") })
                .on("end", function(d){ console.log("transiton end") });

           //   var tooltip = d3.tip().attr('class', 'd3-tip').html(function(d) { return 10; });

           var div = d3.select("body").append("div")
                .attr("class", "tooltip")
                .style("opacity", 0);






            var lineGen = d3.line()
                .x(function(d) { i=i+50;console.log(i); return xScale(d.x); })
                .y(function(d) { return yScale(d.y)  })
                .curve(d3.curveStepAfter)

            var line = chartLayer.selectAll(".line")
                .data([data])

            line.enter().append("path").classed("line", true)
                .merge(line)
                .attr("d", lineGen)
                .attr("fill", "none")
                .attr("stroke", "blue")
                .attr("stroke-width","2px")
                .attr("stroke-dasharray", function(d){ return this.getTotalLength() })
                .attr("stroke-dashoffset", function(d){ return this.getTotalLength() })



            chartLayer.selectAll(".line").transition(t)
                .attr("stroke-dashoffset", 0)

        var img = chartLayer.selectAll('image')
        .data(data)
        .enter()
        .append('image')
        .attr("class","logo")
        .attr("xlink:href", "http://localhost/whatsapp-logo.jpg" )
        .attr("x", function(d,i){ return xScale(d.x+5/2) })
        .attr("y", function(d,i){ return yScale(d.y) })
        .attr("width", 16)
        .attr("height", 16)
        .style("opacity",0);

        img.transition().delay(4000).duration(500).ease(d3.easeLinear).style("opacity",1);

        img.on("mouseover", function(d) {
            div.transition()
         .duration(200)
         .style("opacity", .9);
       div.html("Persona people" + "<br/>" + d.x)
         .style("left", (d3.event.pageX) + "px")
         .style("top", (d3.event.pageY - 28) + "px");
       })
     .on("mouseout", function(d) {
       div.transition()
         .duration(500)
         .style("opacity", 0);
       });


        chartLayer.selectAll("circle").classed("circle",true)
        .data(data)
        .enter().append("circle")
        .attr("class", "circle")
        .attr("fill","none")
        .attr("stroke","black")
        .attr("cx", function(d) { return xScale(d.x); })
        .attr("cy", function(d) { return yScale(d.y); })
        .attr("r", 4)





        }

        function drawAxis(){
            var yAxis = d3.axisLeft(yScale)
                .tickSizeInner(-chartWidth)

            axisLayer.append("g")
                .attr("transform", "translate("+[margin.left, margin.top]+")")
                .attr("class", "axis y")
                .call(yAxis);

            var xAxis = d3.axisBottom(xScale)

            axisLayer.append("g")
                .attr("class", "axis x")
                .attr("transform", "translate("+[margin.left, chartHeight+margin.top]+")")
                .call(xAxis);

        }

        function update(){

        }

    }());
    </script>    
    </body>
    </html>

我希望角色列表中给出的图像与 json 中的 y 坐标显示在同一行,x 轴每分钟都在变化。链接是指向要加载的图像的链接。

我经历了很多问题,但我无法弄清楚这样做的方法。

我的当前输出如下。

现在每一行有一张图片,我希望角色列表(输入json)中的图片数量出现在每一行中。

用这种方式重写你的 img 变量(注意注释):

var img = chartLayer
  .selectAll('g')
  .data(data)
  .enter()
  .append('g') // append g element, here we will be append image as child
  .attr("transform", function(d, i) {
    var x = xScale(d.x + 5 / 2);
    var y = yScale(d.y);
    return 'translate(' + x + ', ' + y + ')'
  })
  .selectAll('image')
  .data(function(d) { // here we format data as we need
    return d.Persona.map(function(icon, index) {
        return {
        icon: icon,
        tooltipText: d.Text[index] // set tooltip text
      }
    })
  })
  .enter()
  .append('image') // append image element
  .attr("class", "logo")
  .attr("xlink:href", function(d) { // set appropriate href attribute
    return d.icon;
  })
  .attr("x", function(d, i) { // move image by index
    return 20 * i;
  })
  .attr("width", 16)
  .attr("height", 16)
  .style("opacity", 0);

...
img.on("mouseover", function(d) {
  div.transition()
  .duration(200)
  .style("opacity", .9);

  div.html("Persona people" + "<br/>" + d.tooltipText) // get tooltip text
  .style("left", (d3.event.pageX) + "px")
  .style("top", (d3.event.pageY - 28) + "px");
})
...

查看工作示例 - https://jsfiddle.net/levsha/og92k0gv/