Javascript 在D3中创建多个DOM
我正在使用Tableau JS API在D3.JS中制作动画图表。我已经创建了Canvas(DOM)元素,在该元素中,我正在使用函数getUnderlineData()绘制所需的图表。当过滤器(来自tableau)发生变化时,调用相同的函数。问题是当过滤器值发生更改时,将创建一个新的DOM。要求更改过滤器,以前的DOM应替换为新的DOM。下面是我正在使用的代码。我是JS的新手,所以可能会有一些愚蠢的错误,对此表示歉意Javascript 在D3中创建多个DOM,javascript,jquery,html,d3.js,tableau-api,Javascript,Jquery,Html,D3.js,Tableau Api,我正在使用Tableau JS API在D3.JS中制作动画图表。我已经创建了Canvas(DOM)元素,在该元素中,我正在使用函数getUnderlineData()绘制所需的图表。当过滤器(来自tableau)发生变化时,调用相同的函数。问题是当过滤器值发生更改时,将创建一个新的DOM。要求更改过滤器,以前的DOM应替换为新的DOM。下面是我正在使用的代码。我是JS的新手,所以可能会有一些愚蠢的错误,对此表示歉意 <!DOCTYPE html> <html lang="en
<!DOCTYPE html>
<html lang="en">
<!-- <meta http-equiv="cache-control" content="no-cache"> -->
<script type="text/javascript" src="https://d3js.org/d3.v4.min.js"></script>
<!-- <script type="text/javascript" src="https://code.jquery.com/jquery-1.10.2.js"></script> -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://servername.com/javascripts/api/tableau-2.min.js"></script>
<head>
<title>Dashboard</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
<script>
currentViz = '';
actA = 0, pyA = 0, budA = 0, actB = 0, budB = 0, pyB = 0, actC = 0, budC = 0, pyC = 0, actD = 0, budD = 0, pyD = 0, actE = 0, budE = 0, pyE = 0, actF = 0, budF = 0, pyF = 0, actG = 0, budG = 0, pyG = 0, actH = 0, budH = 0, pyH = 0, actI = 0, budI = 0, pyI = 0;
/**
* Instantiate our vizualization.
*/
$(function() {
var url = 'https://servername.com/#/site/Playground/views/IncomeData/sheet?:embed=y&:toolbar=n&:apiID=host0#navType=0&navSrc=Parse&5';
var vizOptions = {
showTabs : true,
hideToolbar : true,
width : "1300px",
height : "1300px",
onFirstInteractive: function () {
onFilterChange();
}};
currentViz = new tableauSoftware.Viz(document.getElementById('viz'), url, vizOptions);
currentViz.addEventListener(tableauSoftware.TableauEventName.FILTER_CHANGE, onFilterChange);
});
/**
* Catches the tableau event fired when a filter is changed.
*/
function onFilterChange(e)
{
getUnderlyingData();
}
function getUnderlyingData() {
sheet = currentViz.getWorkbook()
.getActiveSheet()
.getWorksheets()
.get("Datasheet");
var option = {
maxRows: 0,
ignoreAliases: false,
ignoreSelection: false,
includeAllColumns: false
};
sheet.getSummaryDataAsync(option)
.then(function (t) {
table = t;
var data = table.getData();
var columns = table.getColumns();
function reduceToObjects(cols, data) {
var fieldNameMap = $.map(cols, function (col) {
return col.$0.$1;
});
var dataToReturn = $.map(data, function (d) {
return d.reduce(function (memo, value, idx) {
memo[fieldNameMap[idx]] = value.formattedValue;
return memo;
}, {});
});
return dataToReturn;
}
dataTable = reduceToObjects(columns, data);
for(index in dataTable){
if(dataTable[index]["Segment"] == "Revenue")
{ if(dataTable[index]["Measure Names"] == "Actual") actA = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "Budget") budA = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "PY") pyA = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));};
if(dataTable[index]["Segment"] == "Expense")
{ if(dataTable[index]["Measure Names"] == "Actual") actB = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "Budget") budB = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "PY") pyB = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));};
if(dataTable[index]["Segment"] == "Profit")
{ if(dataTable[index]["Measure Names"] == "Actual") actC = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "Budget") budC = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "PY") pyC = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));};
if(dataTable[index]["Segment"] == "Other Expenses")
{ if(dataTable[index]["Measure Names"] == "Actual") actD = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "Budget") budD = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "PY") pyD = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));};
if(dataTable[index]["IS Segment"] == "EBIT")
{ if(dataTable[index]["Measure Names"] == "Actual") actE = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "Budget") budE = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "PY") pyE = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));};
if(dataTable[index]["IS Segment"] == "Total Income")
{ if(dataTable[index]["Measure Names"] == "Actual") actF = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "Budget") budF = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "PY") pyF = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));};
if(dataTable[index]["IS Segment"] == "Amortization")
{ if(dataTable[index]["Measure Names"] == "Actual") actG = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "Budget") budG = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "PY") pyG = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));};
if(dataTable[index]["IS Segment"] == "Amortized Total Income")
{ if(dataTable[index]["Measure Names"] == "Actual") actH = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "Budget") budH = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "PY") pyH = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));};
if(dataTable[index]["IS Segment"] == "EBITDA")
{ if(dataTable[index]["Measure Names"] == "Actual") actI = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "Budget") budI = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));
if(dataTable[index]["Measure Names"] == "PY") pyI = parseFloat(dataTable[index]["Measure Values"].replace(/,/g, ""));};
};
var pic = [{
"act" : actA,
"bud" : budA,
"PY" : pyA,
"revBudVar" : actA - budA,
"revPYVar" : actA - pyA,
"pctBudVar" : (actA - budA)*100/budA,
"pctPYVar" : (actA - pyA)*100/pyA,
"max" : Math.max(actA, budA, pyA)
},
{
"act" : actB,
"bud" : budB,
"PY" : pyB,
"revBudVar" : actB - budB,
"revPYVar" : actB - pyB,
"pctBudVar" : (actB - budB)*100/budB,
"pctPYVar" : (actB - pyB)*100/pyB,
"max" : Math.max(actB, budB, pyB)
},
{
"act" : actC,
"bud" : budC,
"PY" : pyC,
"revBudVar" : actC-budC,
"revPYVar" : actC-pyC,
"pctBudVar" : (actC-budC)*100/budC,
"pctPYVar" : (actC-pyC)*100/pyC,
"max" : Math.max(actC, budC, pyC)
},
{
"act" : actD,
"bud" : budD,
"PY" : pyD,
"revBudVar" : actD-budD,
"revPYVar" : actD-pyD,
"pctBudVar" : (actD-budD)*100/budD,
"pctPYVar" : (actD-pyD)*100/pyD,
"max" : Math.max(actD, budD, pyD)
},
{
"act" : actE,
"bud" : budE,
"PY" : pyE,
"revBudVar" : actE-budE,
"revPYVar" : actE-pyE,
"pctBudVar" : (actE-budE)*100/budE,
"pctPYVar" : (actE-pyE)*100/pyE,
"max" : Math.max(actE, budE, pyE)
},
{
"act" : actF,
"bud" : budF,
"PY" : pyF,
"revBudVar" : actF-budF,
"revPYVar" : actF-pyF,
"pctBudVar" : (actF-budF)*100/budF,
"pctPYVar" : (actF-pyF)*100/pyF,
"max" : Math.max(actF, budF, pyF)
},
{
"act" : actG,
"bud" : budG,
"PY" : pyG,
"revBudVar" : actG-budG,
"revPYVar" : actG-pyG,
"pctBudVar" : (actG-budG)*100/budG,
"pctPYVar" : (actG-pyG)*100/pyG,
"max" : Math.max(actG, budG, pyG)
},
{
"act" : actH,
"bud" : budH,
"PY" : pyH,
"revBudVar" : actH-budH,
"revPYVar" : actH-pyH,
"pctBudVar" : (actH-budH)*100/budH,
"pctPYVar" : (actH-pyH)*100/pyH,
"max" : Math.max(actH, budH, pyH)
},
{
"act" : actI,
"bud" : budI,
"PY" : pyI,
"revBudVar" : actI-budI,
"revPYVar" : actI-pyI,
"pctBudVar" : (actI-budI)*100/budI,
"pctPYVar" : (actI-pyI)*100/pyI,
"max" : Math.max(actI, budI, pyI)
}];
var margin = {top: 20, right: 20, bottom: 20, left: 20},
width = window.innerWidth - margin.right - margin.left,
height = window.innerHeight - margin.top - margin.bottom,
iwidth = (width/9);
d3.select("canvas").exit().remove();
var canvas = d3.select("#data")
.append("svg")
.attr("width", width)
.attr("height", height)
.selectAll("svg")
.data(pic)
.enter();
d3.select("canvas").exit().remove();
canvas.append("svg:image")
.attr('xlink:href',function (d) {return d.image;})
.attr('x', function (d,i) {return (i*iwidth);})
.attr('y',-100)
.transition()
.ease(d3.easeLinear)
.delay(function(d,i){return i*100 + 500;})
.duration(function(d,i){return i*100 + 500;})
.attr("x",function(d,i){ return i*iwidth;})
.attr("y",0);
canvas.append("text")
.style("font", "18px sans-serif")
.attr("x", function (d,i) {return (i*iwidth);})
.attr("y", 122)
.text(function(d,i){ return "$" + d3.format(",.0f")(d.act/1000)+" K";});
canvas.append("text")
.style("font", "12px sans-serif")
.attr("x", function (d,i) {return (i*iwidth);})
.attr("y", 140)
.text("vs Target")
.style("font", "12px sans-serif");
canvas.append("text")
.style("font", "14px sans-serif")
.attr("x", function (d,i) {return (i*iwidth);})
.attr("y", 159)
.attr("class","rev")
.text(function(d,i){return "$" + d3.format(",.0f")(d.bud/1000)+" K";})
canvas.append("rect")
.style("font", "12px sans-serif")
.attr("x",function(d,i){ return (i*iwidth);})
.attr("y",169)
.attr("height",25)
.attr("width", 0)
.transition()
.ease(d3.easeLinear)
.delay(function(d,i){return i*50 +1000;})
.duration(function(d,i){return i*100 + 500;})
.attr("width",function(d){return d3.scaleLinear().domain([0,1.1*(d.max)]).rangeRound([0,iwidth])(d.act);})
.attr("fill", function(d) {if(d.act>d.bud) return "#2AA876"; else return "#E8554E";})
.attr("x",function(d,i){ return i*iwidth;})
.attr("y",169);
canvas.append("rect")
.style("font", "12px sans-serif")
.attr("x", function(d,i){ return (i*iwidth)+d3.scaleLinear().domain([0,1.1*(d.max)]).rangeRound([0,iwidth])(d.bud);})
.attr("y",164)
.attr("height",35)
.attr("width",1.5);
canvas.append("text")
.attr('x',function (d,i) {return 5+(i*iwidth);})
.attr("y", 210)
.text("Variance")
.style("font", "12px sans-serif")
canvas.append("text")
.style("font", "12px sans-serif")
.attr("x", function (d,i) {return 5+(i*iwidth);})
.attr("y", 226)
.attr("fill",function(d){if (d.pctBudVar>0) return "green"; else return "red";})
.text(function(d){if (d.pctBudVar>0) return "▲"+ (d.pctBudVar).toFixed(2).toString() +"%";
else return "▼"+(d.pctBudVar).toFixed(2).toString() +"%";})
canvas.append("text")
.style("font", "12px sans-serif")
.attr("x", function (d,i) {return 75+(i*iwidth);})
.attr("y", 225)
.text(function(d) {return "$" + d3.format(",.0f")(d.revBudVar/1000)+" K";})
canvas.append("text")
.style("font", "12px sans-serif")
.attr("x", function (d,i) {return (i*iwidth);})
.attr("y", 242)
.text("vs PY")
.style("font", "12px sans-serif")
canvas.append("text")
.style("font", "14px sans-serif")
.attr("x", function (d,i) {return 5+(i*iwidth);})
.attr("y", 258)
.text(function(d) { return "$" + d3.format(",.0f")(d.PY/1000)+" K"; });
canvas.append("rect")
.style("font", "12px sans-serif")
.attr("x",function(d,i){ return (i*iwidth);})
.attr("y",265)
.attr("height",25)
.attr("width",0)
.transition()
.ease(d3.easeLinear)
.delay(function(d,i){return i*50 +1000;})
.duration(function(d,i){return i*100 + 500;})
.attr("width",function(d){return d3.scaleLinear().domain([0,1.1*(d.max)]).rangeRound([0,iwidth])(d.act);})
.attr("fill", function(d) {if(d.act>d.PY) return "#2AA876"; else return "#E8554E";})
.attr("x",function(d,i){ return (i)*iwidth;})
.attr("y",265);
canvas.append("rect")
.style("font", "12px sans-serif")
.attr("x", function(d,i){ return (i*iwidth)+d3.scaleLinear().domain([0,1.1*(d.max)]).rangeRound([0,iwidth])(d.PY);})
.attr("y",260)
.attr("height",35)
.attr("width",1.5);
canvas.append("text")
.style("font", "12px sans-serif")
.attr('x',function (d,i) {return 5+(i*iwidth);})
.attr("y", 309)
.text("Variance");
canvas.append("text")
.style("font", "12px sans-serif")
.attr("x", function(d,i){ return 5+i*iwidth;})
.attr("y",325)
.attr("fill",function(d){if (d.pctPYVar>0) return "green"; else return "red";})
.text(function(d){if (d.pctPYVar>0) return "▲"+ (d.pctPYVar).toFixed(2).toString() +"%";
else return "▼"+(d.pctPYVar).toFixed(2).toString() +"%";})
canvas.append("text")
.style("font", "12px sans-serif")
.attr("x", function (d,i) {return 75+(i*iwidth);})
.attr("y",325)
.text(function(d) {return "$" + d3.format(",.0f")(d.revPYVar/1000)+" K";});
});
}
</script>
</head>
<body>
<!-- <input type="button" value="Apply" onClick="javascript:location.reload(true)"> -->
<div id="viz"></div>
<div id="data"></div>
</body>
</html>
仪表板
currentViz='';
actA=0,pyA=0,budA=0,actB=0,budB=0,pyB=0,actC=0,budC=0,pyC=0,actD=0,budD=0,pyD=0,actE=0,budE=0,pyE=0,actF=0,budF=0,pyG=0,actH=0,budH=0,pyH=0,actI=0,budI=0;
/**
*实例化我们的可视化。
*/
$(函数(){
var url='1〕https://servername.com/#/site/Playground/views/IncomeData/sheet?:embed=y&:toolbar=n&:apiID=host0#navType=0&navSrc=Parse&5';
var VIZ选项={
展示:没错,
是的,
宽度:“1300px”,
高度:“1300px”,
onFirstInteractive:函数(){
onFilterChange();
}};
currentViz=newtableausoftware.Viz(document.getElementById('Viz'),url,vizOptions);
currentViz.addEventListener(tableauSoftware.TableauEventName.FILTER\u CHANGE,onFilterChange);
});
/**
*捕获更改筛选器时激发的tableau事件。
*/
过滤器更改功能(e)
{
getUnderlyingData();
}
函数getUnderlineData(){
sheet=currentViz.getWorkbook()
.getActiveSheet()
.getWorksheets()文件
.获取(“数据表”);
var选项={
maxRows:0,
忽略别名:false,
忽略选择:false,
includealcolumns:false
};
sheet.getSummaryDataAsync(选项)
.然后(函数(t){
表=t;
var data=table.getData();
var columns=table.getColumns();
函数约简对象(列、数据){
var fieldNameMap=$.map(cols,函数(col){
返回列$0.$1;
});
var dataToReturn=$.map(数据,函数(d){
返回d.reduce(函数(备注、值、idx){
备注[fieldNameMap[idx]]=value.formattedValue;
返回备忘录;
}, {});
});
返回数据返回;
}
dataTable=简化对象(列、数据);
对于(数据表中的索引){
如果(数据表[索引][“段”]=“收入”)
{if(dataTable[index][“度量名称”]=“实际”)actA=parseFloat(dataTable[index][“度量值”]。替换(/,/g,”);
如果(数据表[索引][“度量名称”]=“预算”)budA=parseFloat(数据表[索引][“度量值”]。替换(/,/g,”);
如果(数据表[索引][“度量值名称”]=“PY”)pyA=parseFloat(数据表[索引][“度量值”])。替换(/,/g,”);};
if(数据表[索引][“段”]=“费用”)
{if(dataTable[index][“度量名称”]=“实际”)actB=parseFloat(dataTable[index][“度量值”]”。替换(/,/g,“”);
如果(数据表[索引][“度量值名称”]=“预算”)budB=parseFloat(数据表[索引][“度量值”]。替换(/,/g,”);
如果(dataTable[index][“measurenames”][=“PY”)pyB=parseFloat(dataTable[index][“measurevalues”]”。替换(/,/g,“”););
if(数据表[索引][“段”]=“利润”)
{if(dataTable[index][“度量名称”]=“实际”)actC=parseFloat(dataTable[index][“度量值”]。替换(/,/g,”);
如果(数据表[索引][“度量名称”]=“预算”)budC=parseFloat(数据表[索引][“度量值”]”。替换(/,/g,“”);
如果(dataTable[index][“measurenames”][=“PY”)pyC=parseFloat(dataTable[index][“measurevalues”]”。替换(/,/g,“”););
if(数据表[索引][“段”]=“其他费用”)
{if(dataTable[index][“度量名称”]=“实际”)actD=parseFloat(dataTable[index][“度量值”]。替换(/,/g,”);
如果(数据表[索引][“度量名称”]=“预算”)budD=parseFloat(数据表[索引][“度量值”])。替换(/,/g,”);
如果(dataTable[index][“measurenames”][=“PY”)pyD=parseFloat(dataTable[index][“measurevalues”]”。替换(/,/g,“”););
如果(数据表[索引][“是段”]=“息税前利润”)
{if(dataTable[index][“度量名称”]=“实际”)actE=parseFloat(dataTable[index][“度量值”]。替换(/,/g,”);
如果(数据表[索引][“度量名称”]=“预算”)budE=parseFloat(数据表[索引][“度量值”]。替换(/,/g,”);
如果(dataTable[index][“度量名称”]==“PY”)pyE=parseFloat(dataTable[index][“度量值”])。替换(/,/g,”);
如果(数据表[索引][“是段”]=“总收入”)
{if(dataTable[index][“度量名称”]=“实际”)actF=parseFloat(dataTable[index][“度量值”]”。替换(/,/g,“”);
如果(数据表[索引][“度量值名称”]=“预算”)budF=parseFloat(数据表[索引][“度量值”])。替换(/,/g,”);
如果(数据表[索引][“度量