简体   繁体   English

在d3.js图表​​中回显JSON

[英]Echo JSON in a d3.js chart

I have a chart created using d3.js where if you hover over the months,the weekly scores are found. 我有一个使用d3.js创建的图表,如果你将鼠标悬停在几个月,就可以找到每周的分数。

Fiddle link to the chart I am talking about here : https://jsfiddle.net/qp7L1hob/1/ 小提琴链接到我在这里谈论的图表: https//jsfiddle.net/qp7L1hob/1/

I also have a table in my DB where I maintain the record of the scores of the Employees every week.What you see here is only for four weeks - (week1 to week4) but in my DB I have record for all the weeks of the months.This is just for reference . 我的数据库中还有一张表,我每周都会记录员工的得分记录。你在这里看到的只有四周 - (第1周到第4周),但在我的数据库中我记录了所有周的记录。 months.This仅供参考。

Table pointsScored : 表pointsScored: 得分 After the user logs in,I want to display only that person's relevant scores.Lets say if Rob logs in,his score for week1 is 47 , week2 is 44, week3 is 44 and week4 is 43. 在用户登录后,我想只显示该人的相关分数。让我们说如果Rob登录,他的第1周的得分为47,第2周为44,第3周为44,第4周为43。

Issue : I am Using php to extract json from SQL server . 问题:Using php to extract jsonSQL服务器中Using php to extract json Below PHP file does that. PHP文件下面就是这样。

The problem is that how do I get the JSON into the d3.js file, ie the above fiddle. 问题是如何将JSON放入d3.js文件中,即上面的小提琴。

please help. 请帮忙。

json file (lets name it as data.php ) :I understand that I need to include this data.php in the above d3.js file.But not sure how. json文件(让我们将其命名为data.php ):我知道我需要在上面的d3.js文件中包含这个data.php 。但是不知道如何。

<?php
session_start();
$servername = "xxxxxxx";
$connectioninfo = array(
    'Database' => 'xxxxxx'
);
$conn = sqlsrv_connect($servername, $connectioninfo);

if ($conn) {
    echo 'connection established';
}
else {
    echo 'connection failure';
    die(print_r(sqlsrv_errors() , TRUE));
}

$q1 = "SELECT WeekNumber,pointsRewarded,EmployeeID FROM pointsBadgeTable WHERE EmployeeID = '" . $_SESSION['id'] . "' ";
$stmt = sqlsrv_query($conn, $q1);

if ($stmt == false) {
    echo 'error to retrieve info !! <br/>';
    die(print_r(sqlsrv_errors() , TRUE));
}

do {
    while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
        $result[] = $row;
    }
}

while (sqlsrv_next_result($stmt));
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn); //Close the connnectiokn first
echo json_encode($result); //You will get the encoded array variable

?>

1: Returning JSON 1:返回JSON

Since you want your data back in json format, then remember to set the content type in the response header, as well as remove the successful connection echo , since it'll mess up the results: 由于您希望数据以json格式json ,因此请记住在响应头中设置内容类型,以及删除成功的连接echo ,因为它会弄乱结果:

<?php
session_start();
$servername = "xxxxxxx";
$connectioninfo = array(
    'Database' => 'xxxxxx'
);
$conn = sqlsrv_connect($servername, $connectioninfo);
if (!$conn) {
    echo 'connection failure';
    die(print_r(sqlsrv_errors() , TRUE));
}

$q1 = "SELECT WeekNumber,pointsRewarded,EmployeeID FROM pointsBadgeTable WHERE EmployeeID = '" . $_SESSION['id'] . "' ";
$stmt = sqlsrv_query($conn, $q1);
if ($stmt == false) {
    echo 'error to retrieve info !! <br/>';
    die(print_r(sqlsrv_errors() , TRUE));
}
do {
    while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
        $result[] = $row;
    }
}
while (sqlsrv_next_result($stmt));
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn); //Close the connnectiokn first

//Set content type to json
header('Content-Type: application/json');

//Echo a json object to the browser
echo json_encode($result);
?>

I would also recommend using PDO to connect to your database. 我还建议使用PDO连接到您的数据库。 Basically, like this: 基本上,像这样:

<?php

session_start();

$db = new PDO("sqlsrv:Server=YouAddress;Database=YourDatabase", "Username", "Password");

$sql = "SELECT WeekNumber,pointsRewarded,EmployeeID FROM pointsBadgeTable WHERE EmployeeID = ':UserID'";

if($stmt = $db->prepare($sql)){

    //Bind the sessionID
    $stmt->bindParam('UserID', $_SESSION['id']);

    //Execute query
    $stmt->execute();

    //Fetch data
    $data = $stmt->fetch(PDO::FETCH_ASSOC);

    //Close cursor
    $stmt->closeCursor();

    //Set header type to json
    header("content-type:application/json");

    //Echo json encoded array
    echo json_encode($data);
}
?>

Note that you might have to download the Microsoft server PDO drivers if you want to use PDO. 请注意,如果要使用PDO,可能必须下载Microsoft服务器PDO驱动程序。

Microsoft has a demo page here , that explains how to use PDO with SQL Server. Microsoft 在此处有一个演示页面,它解释了如何将PDO与SQL Server一起使用。

2: Communicating with the server 2:与服务器通信

You need to be able to fetch the data from your PHP page. 您需要能够从PHP页面获取数据。 The best way to do this is via Ajax . 最好的方法是通过Ajax

You need to send an Ajax request to the data.php file (Using jQuery's .get() for simplicity): 您需要向data.php文件发送Ajax请求.get()为简单起见,使用jQuery的.get() ):

$.get("path/to/data.php", function(data){
  //`data` is the JSON that the server echoed 
});

Or, in vanilla JS: 或者,在香草JS中:

httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() {
  if (httpRequest.readyState === XMLHttpRequest.DONE) {
    if (httpRequest.status === 200) {
      var data = httpRequest.responseText;

      //Do stuff with data here
    } 
  }
};
httpRequest.open('GET', "path/to/data.php");
httpRequest.send();

3: Using the data 3:使用数据

So now we have the data from the server, but it isn't in a useable format for the graph, what do we do? 所以现在我们有来自服务器的数据,但它不是图表的可用格式,我们该怎么办?

According to your comments, the Ajax request returns data in a format like: 根据您的评论,Ajax请求以如下格式返回数据:

[{
    "WeekNumber": "week49",
    "pointsRewarded": 50,
    "EmployeeID": 100739
}, {
    "WeekNumber": "week51",
    "pointsRewarded": 50,
    "EmployeeID": 100739
}, {
    "WeekNumber": "week50",
    "pointsR‌​ewarded": 50,
    "EmployeeID": 100739
}]

However, looking over your JSFiddle, it's needed in a completely different format, so it's pretty obvious we need to change the format. 但是,查看你的JSFiddle,它需要一个完全不同的格式,所以很明显我们需要改变格式。

First of all, we'll need to parse the object, so we have all the correct data: 首先,我们需要解析对象,因此我们拥有所有正确的数据:

function ParseData(data) {

  var parsed = {};

  var months = ['January - 2016', 'February - 2016', 'March - 2016', 'April - 2016', 'May - 2016', 'June - 2016', 'July - 2016', 'August - 2016', 'September - 2016', 'October - 2016', 'November - 2016', 'December - 2016'];

  data.forEach(function(item) {
    var week = parseInt(item.WeekNumber.slice(4)),
      month = Math.floor((week - 1) / 4);

    if (!parsed[month]) parsed[month] = {
      weeks: [],
      points: 0,
      month: months[month - 1]
    }

    var weekLabel = "Week " + week + ": " + item.pointsRewarded;

    parsed[month].weeks.push(weekLabel);
    parsed[month].points += item.pointsRewarded;

  });

  return FormatData(parsed);
}

All we're doing there is looping through the results, and building an object with the relevant info. 我们所做的就是遍历结果,并使用相关信息构建对象。 Next, we need to format the data so it works with the charts. 接下来,我们需要格式化数据,以便它与图表一起使用。 Since we already have the parsed data, this is simple: 由于我们已经有了解析数据,这很简单:

function FormatData(data) {

  var formatted = {
    points: [],
    weeks: [],
    months: []
  };

  for (var month in data) {

    var now = data[month];

    formatted.points.push(now.points);
    formatted.months.push(now.month);
    formatted.weeks.push(now.weeks.join("<br>"));
  }

  return formatted;
}

Now when you call ParseData(ajaxData) , it will return all the info you need for your charts. 现在,当您调用ParseData(ajaxData) ,它将返回图表所需的所有信息。

A working demo can be seen here , with fake data. 这里可以看到一个有假数据的工作演示

Now all we need to do is wait to render the chart with the correct data. 现在我们需要做的就是等待使用正确的数据渲染图表。 In this case, I wrapped all the code for the chart in it's own function, and make it so it uses the data passed to it in the formattedData parameter: 在这种情况下,我将图表的所有代码包装在它自己的函数中,并使其使用在formattedData参数中传递给它的数据:

function InitChart(formattedData) {
  let colors = ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#e0e0e0', '#bababa', '#878787', '#4d4d4d', '#1a1a1a', 'white', 'white'];


  var width = document.querySelector('.chart-wrapper').offsetWidth,
    height = document.querySelector('.chart-wrapper').offsetHeight,
    minOfWH = Math.min(width, height) / 2,
    initialAnimDelay = 300,
    arcAnimDelay = 150,
    arcAnimDur = 3000,
    secDur = 1000,
    secIndividualdelay = 150;

  var radius = undefined;

  // calculate minimum of width and height to set chart radius
  if (minOfWH > 200) {
    radius = 200;
  } else {
    radius = minOfWH;
  }

  // append svg
  var svg = d3.select('.chart-wrapper').append('svg').attr({
    'width': width,
    'height': height,
    'class': 'pieChart'
  }).append('g');

  svg.attr({
    'transform': 'translate(' + width / 2 + ', ' + height / 2 + ')'
  });

  // for drawing slices
  var arc = d3.svg.arc().outerRadius(radius * 0.6).innerRadius(radius * 0.45);

  // for labels and polylines
  var outerArc = d3.svg.arc().innerRadius(radius * 0.85).outerRadius(radius * 0.85);

  // d3 color generator
  // let c10 = d3.scale.category10();

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

  var pie = d3.layout.pie().value(function(d) {
    return d;
  }).sort(null);

  var draw = function draw() {

    svg.append("g").attr("class", "lines");
    svg.append("g").attr("class", "slices");
    svg.append("g").attr("class", "labels");

    // define slice
    var slice = svg.select('.slices').datum(formattedData.points).selectAll('path').data(pie);
    slice.enter().append('path').attr({
      'fill': function fill(d, i) {
        return colors[i];
      },
      'd': arc,
      'stroke-width': '25px'
    }).attr('transform', function(d, i) {
      return 'rotate(-180, 0, 0)';
    }).style('opacity', 0).transition().delay(function(d, i) {
      return i * arcAnimDelay + initialAnimDelay;
    }).duration(arcAnimDur).ease('elastic').style('opacity', 1).attr('transform', 'rotate(0,0,0)');

    slice.transition().delay(function(d, i) {
      return arcAnimDur + i * secIndividualdelay;
    }).duration(secDur).attr('stroke-width', '5px');

    var midAngle = function midAngle(d) {
      return d.startAngle + (d.endAngle - d.startAngle) / 2;
    };

    var text = svg.select(".labels").selectAll("text").data(pie(formattedData.points));

    text.enter().append('text').attr('dy', '0.35em').style("opacity", 0).attr("cursor", "default").style('fill', function(d, i) {
      return colors[i];
    }).text(function(d, i) {
      return formattedData.months[i];
    }).attr('transform', function(d) {
      // calculate outerArc centroid for 'this' slice
      var pos = outerArc.centroid(d);
      // define left and right alignment of text labels
      pos[0] = radius * (midAngle(d) < Math.PI ? 1 : -1);
      return 'translate(' + pos + ')';
    }).style('text-anchor', function(d) {
      return midAngle(d) < Math.PI ? "start" : "end";
    }).transition().delay(function(d, i) {
      return arcAnimDur + i * secIndividualdelay;
    }).duration(secDur).style('opacity', 1);

    text.on("mousemove", function(d, i) {
      tooltip.html(formattedData.weeks[i])
        .style('top', d3.event.pageY - 6 + 'px')
        .style('left', d3.event.pageX + 14 + 'px')
        .style("opacity", 1);
    }).on("mouseout", function(d) {
      tooltip.style("opacity", 0);
    });


    var polyline = svg.select(".lines").selectAll("polyline").data(pie(formattedData.points));

    polyline.enter().append("polyline").style("opacity", 0.5).attr('points', function(d) {
      var pos = outerArc.centroid(d);
      pos[0] = radius * 0.95 * (midAngle(d) < Math.PI ? 1 : -1);
      return [arc.centroid(d), arc.centroid(d), arc.centroid(d)];
    }).transition().duration(secDur).delay(function(d, i) {
      return arcAnimDur + i * secIndividualdelay;
    }).attr('points', function(d) {
      var pos = outerArc.centroid(d);
      pos[0] = radius * 0.95 * (midAngle(d) < Math.PI ? 1 : -1);
      return [arc.centroid(d), outerArc.centroid(d), pos];
    });
  };

  draw();

  var button = document.querySelector('button');

  var replay = function replay() {

    d3.selectAll('.slices').transition().ease('back').duration(500).delay(0).style('opacity', 0).attr('transform', 'translate(0, 250)').remove();
    d3.selectAll('.lines').transition().ease('back').duration(500).delay(100).style('opacity', 0).attr('transform', 'translate(0, 250)').remove();
    d3.selectAll('.labels').transition().ease('back').duration(500).delay(200).style('opacity', 0).attr('transform', 'translate(0, 250)').remove();

    setTimeout(draw, 800);
  };
}

Now, just put it all together and render the chart with the data: 现在,将它们放在一起并使用数据呈现图表:

$.get("path/to/data.php", function(data){
  //Get data
  var parsedData = ParseData(data);
  //Render chart
  InitChart(parsedData);
});

You can see the fully updated JS file here. 您可以在此处查看完整更新的JS文件。

Don't forget to set the correct ajax URL. 不要忘记设置正确的ajax URL。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM