1:返回 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);
?>
我还建议使用PDO 连接到您的数据库。基本上是这样的:
<?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);
}
?>
请注意,如果您想使用 PDO,您可能需要下载 Microsoft 服务器 PDO 驱动程序。
Microsoft 有一个演示页面 here,它解释了如何将 PDO 与 SQL Server 一起使用。
2:与服务器通信
您需要能够从您的 PHP 页面中获取数据。最好的方法是通过Ajax。
您需要向data.php 文件发送一个Ajax 请求(为简单起见,使用jQuery 的.get()):
$.get("path/to/data.php", function(data){
//`data` is the JSON that the server echoed
});
或者,在原版 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:使用数据
所以现在我们有来自服务器的数据,但它不是图表可用的格式,我们该怎么办?
根据您的 cmets,Ajax 请求以如下格式返回数据:
[{
"WeekNumber": "week49",
"pointsRewarded": 50,
"EmployeeID": 100739
}, {
"WeekNumber": "week51",
"pointsRewarded": 50,
"EmployeeID": 100739
}, {
"WeekNumber": "week50",
"pointsRewarded": 50,
"EmployeeID": 100739
}]
但是,查看您的 JSFiddle,它需要采用完全不同的格式,因此很明显我们需要更改格式。
首先,我们需要解析对象,所以我们拥有所有正确的数据:
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);
}
我们在这里所做的只是循环遍历结果,并使用相关信息构建一个对象。接下来,我们需要格式化数据,使其与图表一起使用。由于我们已经有了解析的数据,这很简单:
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;
}
现在,当您致电 ParseData(ajaxData) 时,它会返回图表所需的所有信息。
A working demo can be seen here,带有虚假数据。
现在我们需要做的就是等待以正确的数据呈现图表。在这种情况下,我将图表的所有代码包装在它自己的函数中,并使其使用在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);
};
}
现在,只需将它们放在一起并使用数据呈现图表:
$.get("path/to/data.php", function(data){
//Get data
var parsedData = ParseData(data);
//Render chart
InitChart(parsedData);
});
别忘了设置正确的 ajax URL。