Javascript 在D3中创建多个DOM

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

我正在使用Tableau JS API在D3.JS中制作动画图表。我已经创建了Canvas(DOM)元素,在该元素中,我正在使用函数getUnderlineData()绘制所需的图表。当过滤器(来自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>

仪表板
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,”);
如果(数据表[索引][“度量