我正在使用d3.js构建Treemap布局,并面临代码的典型问题。如果提供警告声明,则代码可以正常工作。我简要解释下面的代码,
default.HTML文件和FetchData.java
步骤6正常工作我在调用wrapperFunc(str)之前放置了一个警告语句。所以d3.sjon函数不会有任何问题。当我删除警报时,它不起作用。 非常感谢任何帮助
<!-- DEFAULT.HTML -->
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Expires" content="Sat, 01 Dec 2001 00:00:00 GMT">
<script type="text/javaScript" src="d3/d3.js"></script>
<script>
var xhr = new XMLHttpRequest();
function loadNewData(){
//alert("AJAX CALL");
xhr.open("GET","FetchData?from="+document.getElementById("from").value+"&to="+document.getElementById("to").value,true);
//xhr.open("GET","FetchData",false);
xhr.onreadystatechange=process;
xhr.send(null);
}
function process(){
//alert("proces()");
if(xhr.readyState == 4 && xhr.status == 200){
str = xhr.responseText;
//alert(str);
wrapperFunc(str);
}
}
</script>
</head>
<body>
<form>
<label><input type="radio" name="mode" value="size" checked> Clicks</label>
<label><input type="radio" name="mode" value="ctr"> Ctr</label>
<label><input type="radio" name="mode" value="searches"> Searches</label>
<label>From</label>
<input type="text" id="from" name="from">
<label>to</label>
<input type="text" id="to" name="to">
<input type="button" id="bt1" value="fetch" onclick="loadNewData()">
</form>
<script>
function wrapperFunc(str){
// D3 CODE HERE
var margin = {top: 0, right: 0, bottom: 0, left: 0},
width = 1200 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom;
var color = d3.scale.category20();
var treemap = d3.layout.treemap()
.size([width, height])
.sticky(true)
.value(function(d) { return d.clicks;});
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right )
.attr("height", height + margin.top + margin.bottom)
.append("g");
d3.json('data/'+str,function(error,root){
if (error) {
console.log("Inside Error");
console.log(error);
} else {
console.log("Inside root");
console.log(root);
}
var rects = svg.datum(root)
.selectAll("rect")
.data(treemap.nodes)
.enter()
.append("rect")
.call(position);
var texts = svg.selectAll("text")
.data(treemap.nodes)
.enter()
.append("text")
.call(textPrint);
//Tooltip and highlighting starts
d3.selectAll("rect").on("mouseover",mouseover);
d3.selectAll("rect").on("mouseout",mouseout);
//Tooltip and Highlighting ends
//Transition of the Treemap.
d3.selectAll("input").on("change",change);
function change(){
var value = this.value;
if (this.value === "ctr") { value = function(d) {return d.ctr;}}
else if (this.value === "searches") { value = function(d) {return d.searches;}}
else { value = function(d) {return d.clicks;}}
//alert(value);
rects
.data(treemap.value(value).nodes)
.transition()
.duration(1500)
.call(position);
texts
.data(treemap.value(value).nodes)
.transition()
.delay(1500)
.duration(500)
.call(textPrint);
}//change
});//d3.json
function position(){
this.attr("x", function(d) {return d.x;})
.attr("y", function(d) {return d.y;})
.attr("width", function(d) {return d.dx;})
.attr("height", function(d) {return d.dy;})
.attr("stroke","white")
.attr("fill", function(d) {
if(d.children == null)
return color(d.parent.sub_group); // color(d.parent.name);
else
return null;
});
}
function textPrint(){
this.attr("x",function(d) {return d.x + 3;})
.attr("y",function(d) {return d.y + 10;})
.attr("class","node")
.text(function(d){
if(d.dx <= 10 || d.dy <= 10){ return ""; } //If the rect is too small do not display the text
else if (d.children == null){
var pxK = 6.6,txtLngth = (d.clientid).length,txtAccomadate = Math.round(d.dx/pxK);
if (txtAccomadate >= txtLngth)
return d.clientid;
else
return "";
// return (d.clientid).substr(0,txtAccomadate);
}
else
return null;
});
}
function mouseover(d){
// The below code is used for highlighting the element (i.e. rect) on mouse hover
d3.select(this)
.attr("fill", "orange");
//Get this rects x/y values, then augment for the tooltip
var xPosition = parseFloat(d3.select(this).attr("x")) + (d.dx)/2;
var yPosition = parseFloat(d3.select(this).attr("y")) + (d.dy)/2;
//Update the tooltip position and value
d3.select("#tooltip")
.style("left", xPosition + "px")
.style("top", yPosition + "px")
.select("#value")
.text(d.parent.sub_group+"--"+d.clientid);
//Show the tooltip
d3.select("#tooltip").classed("hidden", false);
}
function mouseout(d) {
d3.select(this)
.transition()
.duration(500)
.attr("fill", function(d) {
if(d.children == null)
return color(d.parent.sub_group);
else
return null;
})
//Hide the tooltip
d3.select("#tooltip").classed("hidden", true);
}
}//wrapperFunc
</script>
</body>
</html>
FetchData.java - 是一个提取数据的servlet
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.aol.poc.d3js.dbConnect.NetezzaJdbcConnection;
import com.aol.poc.d3js.properties.*;
import com.aol.poc.d3js.treemap.CsvToJson_V2;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
*
* @author M1025322
*/
@WebServlet(name = "FetchData", urlPatterns = {"/FetchData"})
public class FetchData extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String from="",to="",filetod3="";
from = request.getParameter("from");
to = request.getParameter("to");
response.setContentType("text/html");
response.getWriter().write(generateJSONDataFile(from,to));
response.getWriter().flush();
}
public String generateJSONDataFile(String from,String to){
NetezzaJdbcConnection njc = new NetezzaJdbcConnection();
CsvToJson_V2 readCsv = new CsvToJson_V2();
if(from == null || to == null){
System.out.println("Inside if null");
njc.extractData();
}
else{
System.out.println("Inside else");
njc.extractData(from,to);
}
String filetod3 = readCsv.readCsv();
return filetod3;
}
}
答案 0 :(得分:0)
我终于明白了我面临的问题。 d3.json(url,callback)
本身会进行AJAX调用。当我收到来自servlet的文件名(JSON数据)并将其传递给d3.json函数时,它正在另外调用服务器来获取文件。由于它是异步的,代码d3代码被执行并且数据未被收到。当下面的语句抛出错误(对象XMLHttpRequest)而不是json对象([Object Object])时,我理解了这个问题
if (error) {
console.log(error);
} else {
console.log(root);
所以我决定删除d3.json函数并从文件中传递一个完整的JSON字符串,并使用JS eval()
函数将其转换为JSON对象并运行d3代码。这工作,我不再需要任何警报声明问题。我正在粘贴下面代码中的零星部分。请注意,css代码不在这里,servlet代码与上面相同,只是return filetod3;
将重新调整JSON数据而不是JSON文件名的区别。我没有放在这里的CSS文件。
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javaScript" src="d3/d3.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css">
<link rel="stylesheet" type="text/css" href="CSS/mystyle.css">
<script>
$(function() {
$( "#from" ).datepicker({
defaultDate: "+1w",
dateFormat: "yy-mm-dd",
changeMonth: true,
changeYear: true,
numberOfMonths: 1,
onClose: function( selectedDate ) {
$( "#to" ).datepicker( "option", "minDate", selectedDate );
}
});
$( "#to" ).datepicker({
defaultDate: "+1w",
dateFormat: "yy-mm-dd",
changeMonth: true,
changeYear: true,
numberOfMonths: 1,
onClose: function( selectedDate ) {
$( "#from" ).datepicker( "option", "maxDate", selectedDate );
}
});
});
function openModal() {
document.getElementById('modal').style.display = 'block';
document.getElementById('fade').style.display = 'block';
}
function closeModal() {
document.getElementById('modal').style.display = 'none';
document.getElementById('fade').style.display = 'none';
}
var xhr = new XMLHttpRequest();
function loadNewData(){
openModal();
//alert("AJAX CALL");
xhr.open("GET","FetchData?from="+document.getElementById("from").value+"&to="+document.getElementById("to").value,true);
//xhr.open("GET","FetchData",false);
xhr.onreadystatechange=process;
xhr.send(null);
}
function process(){
//alert("proces()");
if(xhr.readyState == 4 && xhr.status == 200){
closeModal();
var str = xhr.responseText;
var jsondata = eval("("+str+")");
// alert("str "+str);
// alert("jsondata "+jsondata);
wrapperFunc(jsondata);
}
}
</script>
</head>
<body onload="loadNewData()">
<H3> POC for a Treemap in D3.js </h3>
<form>
<br><br><br><br>
<label><input type="radio" name="mode" value="size" checked> Clicks</label>
<label><input type="radio" name="mode" value="ctr"> Ctr</label>
<label><input type="radio" name="mode" value="searches"> Searches</label>
<br><br>
<label>From</label>
<input type="text" id="from" name="from">
<label>to</label>
<input type="text" id="to" name="to">
<input type="button" class="btn" id="bt1" value="Fetch" onclick="loadNewData()">
</form>
<div id="tooltip" class="hidden">
<!-- <p><strong>Label</strong></p> -->
<p><span id="value"></span></p>
</div>
<div id="fade"></div>
<div id="modal">
<img id="loader" src="images/ajax-loader-Flower.gif" />
</div>
<script>
function wrapperFunc(jsondata){
//alert("Inside wrapperFunc -- "+jsondata);
//var margin = {top: 40, right: 10, bottom: 10, left: 10},
// var margin = {top: 0, right: 0, bottom: 0, left: 0},
//width = 1200 - margin.left - margin.right,
//height = 450 - margin.top - margin.bottom;
var margin = {top: 0, right: 0, bottom: 0, left: 0},
width = 1200 - margin.left - margin.right,
height = 470 - margin.top - margin.bottom;
var color = d3.scale.category20();
var treemap = d3.layout.treemap()
.size([width, height])
.sticky(true)
.value(function(d) { return d.clicks;});
d3.select("svg").remove();
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right )
.attr("height", height + margin.top + margin.bottom)
.append("g");
console.log("Inside root");
console.log(jsondata);
var rects = svg.datum(jsondata)
.selectAll("rect")
.data(treemap.nodes)
.enter()
.append("rect")
.call(position);
var texts = svg.selectAll("text")
.data(treemap.nodes)
.enter()
.append("text")
.call(textPrint);
//Tooltip and highlighting starts
d3.selectAll("rect").on("mouseover",mouseover);
d3.selectAll("rect").on("mouseout",mouseout);
//Tooltip and Highlighting ends
//Transition of the Treemap.
d3.selectAll("input").on("change",change);
function change(){
var value = this.value;
if (this.value === "ctr") { value = function(d) {return d.ctr;}}
else if (this.value === "searches") { value = function(d) {return d.searches;}}
else { value = function(d) {return d.clicks;}}
//alert(value);
rects
.data(treemap.value(value).nodes)
.transition()
.duration(1500)
.call(position);
texts
.data(treemap.value(value).nodes)
.transition()
.delay(1500)
.duration(500)
.call(textPrint);
}//change
function position(){
this.attr("x", function(d) {return d.x;})
.attr("y", function(d) {return d.y;})
.attr("width", function(d) {return d.dx;})
.attr("height", function(d) {return d.dy;})
.attr("stroke","white")
.attr("fill", function(d) {
if(d.children == null)
return color(d.parent.sub_group); // color(d.parent.name);
else
return null;
});
}
function textPrint(){
this.attr("x",function(d) {return d.x + 3;})
.attr("y",function(d) {return d.y + 10;})
.attr("class","node")
.text(function(d){
if(d.dx <= 10 || d.dy <= 10){ return ""; } //If the rect is too small do not display the text
else if (d.children == null){
var pxK = 6.6,txtLngth = (d.clientid).length,txtAccomadate = Math.round(d.dx/pxK);
if (txtAccomadate >= txtLngth)
return d.clientid;
else
return "";
// return (d.clientid).substr(0,txtAccomadate);
}
else
return null;
});
}
function mouseover(d){
// The below code is used for highlighting the element (i.e. rect) on mouse hover
d3.select(this)
.attr("fill", "orange");
//Get this rects x/y values, then augment for the tooltip
var xPosition = parseFloat(d3.select(this).attr("x")) + (d.dx)/2;
var yPosition = parseFloat(d3.select(this).attr("y")) + (d.dy)/2;
//Update the tooltip position and value
d3.select("#tooltip")
.style("left", xPosition + "px")
.style("top", yPosition + "px")
.select("#value")
.text(d.parent.sub_group+"--"+d.clientid);
//Show the tooltip
d3.select("#tooltip").classed("hidden", false);
}
function mouseout(d) {
d3.select(this)
.transition()
.duration(500)
.attr("fill", function(d) {
if(d.children == null)
return color(d.parent.sub_group);
else
return null;
})
//Hide the tooltip
d3.select("#tooltip").classed("hidden", true);
}
}//wrapperFunc
</script>
</body>
</html>
答案 1 :(得分:0)
对我来说,它有助于添加jQuery-Ajax&gt; options:async:false,
function initConfig() {
console.log('initConfig:start');
$.ajax({
type: "POST",
url: "router.php",
dataType: 'json',
async: false,
data: {"ajax_mode":"init-config"},
success: function(msg){
window.storeobject = msg;
},
error: function(){
alert("failure");
}
});
}
问候 Andrzej Kmicic