在 D3 中创建多个 DOM



我正在使用 Tableau JS API 在 D3 中制作动画图表.js。我创建了 Canvas(DOM( 元素,在其中我使用getUnderlyingData((函数绘制所需的图表。当筛选器(来自 tableau(发生更改时,将调用相同的函数。问题是当过滤器值发生变化时,正在创建新的 DOM。要求是更改过滤器时,以前的 DOM 应替换为新的 DOM。下面是我正在使用的代码。我是JS的新手,所以可能会有一些愚蠢的错误,为此道歉。

<!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>

这里发生了很多我不确定的事情。比如你混合画布和 svg 吗?无论您可能想以以下方式开始您的 d3 部分:

d3.select('#data').selectAll('*').remove()

这将在每次脚本运行时清除#data标记中的所有内容。

最新更新