问题描述
我已经在salesforce中实现了条形图,如下所示。现在,我想显示/隐藏子数据,如果有任何使用手风琴/加号图标的孩子。我尝试使用d3.hierarchy函数,但没有运气。
我想获得上面的图表,当单击+(加号)图标时,该图标应展开并显示子项(如果有),然后再次单击以隐藏子项。
//function to create Gantt Chart
d3gantchart: function(component,event,helper,items) {
let exp_label = $A.get("$Label.c.Legend_expected");
let act_label = $A.get("$Label.c.Legend_Actual");
let chart_title = $A.get("$Label.c.Gannt_Chart_Title");
function formatDate(dt) {
var year,mon,day;
year = dt.getFullYear();
mon = dt.getMonth() + 1;
day = dt.getDate();
return year + '-' + mon + '-' + day;
}
function createDate(year,day) {
return new Date(year,day);
}
var min_domain = formatDate(createDate(component.get('v.curr_year'),component.get('v.first_month'),1));
var max_domain = formatDate(createDate(component.get('v.curr_year'),component.get('v.last_month'),0));
const slicedData = getSlicedDates(items);
var svg_width = 670;
var svg_height = window.innerHeight;
var title_x_height = 16;
d3.selectAll(".chart").selectAll("svg").remove();
var svg = d3.selectAll(".chart")
.append("svg")
.attr("width",svg_width)
.attr("height",svg_height)
.attr("preserveAspectRatio","xMinYMax meet")
.attr("viewBox",[0,svg_width,svg_height].join(' '))
.attr("class","svg");
var dateFormat = d3.timeParse("%Y-%m-%d");
var timeScale = d3.scaleTime()
.domain([d3.min(slicedData,function(d) {
return dateFormat(min_domain);
}),d3.max(slicedData,function(d) {
return dateFormat(max_domain);
})
])
.range([0,svg_width - 180])
var categories = [];
for (var i = 0; i < slicedData.length; i++) {
categories.push({
Name: slicedData[i].Name,Id: slicedData[i].Id
});
}
var catsUnfiltered = categories;
makeGant(slicedData,svg_height);
function makeGant(slicedData,pageWidth,pageHeight) {
var barHeight = 15;
var gap = barHeight + 22;
var topPadding = 40;
var sidePadding = 172;
var colorScale = d3.scaleLinear()
.domain([0,categories.length])
.range(["#00B9FA","#F95002"])
.interpolate(d3.interpolateHcl);
makeGrid(sidePadding,topPadding,pageHeight);
drawRects(slicedData,gap,sidePadding,barHeight,colorScale,pageHeight);
vertLabels(gap,colorScale);
}
function drawRects(slicedData,theGap,thetopPad,theSidePad,theBarHeight,theColorScale,width,height) {
var rectangles = svg.append('g')
.selectAll("rect")
.data(slicedData)
.enter();
// draw legend group
var legend = svg.selectAll("g")
.data(slicedData)
.enter().append("g")
.attr("class","legend");
// draw legend rect
legend.append("rect")
.attr("x",width - 200)
.attr("y",title_x_height + 18)
.attr("rx",8)
.attr("ry",8)
.attr("width",30)
.attr("height",theBarHeight)
.style("fill","#78ADD2");
// draw legend text
legend.append("text")
.attr("x",width - 106)
.attr("y",title_x_height + 26)
.attr("dy",".35em")
.style("text-anchor","end")
.attr("font-size",14)
.text(exp_label);
// draw legend colored rectangles
legend.append("rect")
.attr("x",width - 95)
.attr("y",theBarHeight)
//.attr("background","#0d053d")
.style("fill","#0072AA");
// draw legend text
legend.append("text")
.attr("x",width - 21)
.attr("y",14)
.text(act_label);
//draw rectangles for expected date range
var expRects = rectangles.append("rect")
.attr("rx",8)
.attr("x",function(d) {
return timeScale(dateFormat(d.expStartTime)) + theSidePad;
})
.attr("y",function(d,i) {
return i * theGap + thetopPad + title_x_height + 50;
})
.attr("width",function(d) {
return (timeScale(dateFormat(d.expEndTime)) - timeScale(dateFormat(d.expStartTime)));
})
.attr("height",theBarHeight)
.attr("stroke","none")
.attr("fill","#78ADD2")
//draw rectangles for Actual date range
var actualRects = rectangles.append("rect")
.attr("rx",function(d) {
return timeScale(dateFormat(d.actualStartTime)) + theSidePad;
})
.attr("y",function(d) {
return (timeScale(dateFormat(d.actualEndTime)) - timeScale(dateFormat(d.actualStartTime)));
})
.attr("height","#0072AA")
rectangles.append("rect")
.attr("rx",0)
.attr("ry",0)
.attr("x",-0)
.attr("y",title_x_height + 10)
.attr("width",670)
.attr("height",30)
.attr("fill","#f2f0ed")
//display Current year
svg.append("text")
.attr('transform','translate(360' + ',' + (title_x_height + 30) + ')')
.attr("font-size",16)
.attr("font-weight","bold")
.style("text-anchor","middle")
.text(component.get('v.curr_year'));
rectangles.append("rect")
.attr("rx",title_x_height + 40)
.attr("width",40)
.attr("fill","#d6d2ce")
.attr("opacity",0.1);
//decrement Current year
d3.select("svg").append("g").append("foreignObject")
.attr("width",30)
.attr('transform','translate(250' + ',' + (title_x_height + 10) + ')')
.append("xhtml:a")
.append('xhtml:i').attr('class','arrow left').on("click",function() {
component.set('v.curr_year',component.get('v.curr_year') - 1);
component.set('v.first_month',0);
component.set('v.last_month',6);
helper.d3gantchart(component,items);
})
.attr("height","12px")
.attr("width","12px");
//Increment Current year
d3.select("svg").append("g").append("foreignObject")
.attr("width",'translate(420' + ','arrow right').on("click",component.get('v.curr_year') + 1);
component.set('v.first_month',"12px");
//decrement the month
d3.select("svg").append("g").append("foreignObject")
.attr("width",40)
.attr("height",40)
.attr('transform','translate(20' + ',' + (title_x_height + 45) + ')')
.append("xhtml:a")
.append('xhtml:i').attr('class','arrow_mon left_mon').on("click",component.get('v.first_month') === 0 ? component.get('v.curr_year') - 1 : component.get('v.curr_year'));
component.set('v.first_month',component.get('v.first_month') === 0 ? 6 : 0);
component.set('v.last_month',component.get('v.last_month') === 6 ? 12 : 6);
helper.d3gantchart(component,"12px");
//Increment the month
d3.select("svg").append("g").append("foreignObject")
.attr("width",'translate(610' + ',' + (title_x_height + 43) + ')')
.append("xhtml:a")
.append('xhtml:i').attr('class','arrow_mon right_mon').on("click",component.get('v.last_month') === 12 ? component.get('v.curr_year') + 1 : component.get('v.curr_year'));
component.set('v.first_month',component.get('v.first_month') == 0 ? 6 : 12);
helper.d3gantchart(component,items);
})
// Actual rect mouSEOver tool-tip
actualRects.on('mouSEOver',function(e) {
var tag = "";
if (e != undefined) {
tag = "<b>Project Title</b> :" + e.Name + "<br/>" +
"<b>Act Start Date</b> :" + e.actualStartTime + "<br/>" +
"<b>Act End Date</b> :" + e.actualEndTime;
}
var output = document.getElementById("tag");
var i;
for (i = 0; i < output.length; i++) {
output[i].style.display = 'none';
}
var x = (this.x.animVal.value + this.width.animVal.value / 4) + "px";
var y = this.y.animVal.value + 25 + "px";
output.innerHTML = tag;
output.style.top = d3.event.layerY + "px";
output.style.left = d3.event.layerX + "px";
output.style.display = "block";
}).on('mouSEOut',function() {
var output = document.getElementById("tag");
output.style.display = "none";
});
// Expected rect mouSEOver tool-tip
expRects.on('mouSEOver',function(e) {
var tag_exp = "";
if (e != undefined) {
tag_exp = "<b>Project Title</b> :" + e.Name + "<br/>" +
"<b>Exp Start Date</b> :" + e.expStartTime + "<br/>" +
"<b>Exp End Date</b> :" + e.expEndTime;
}
var output = document.getElementById("tag");
var i;
for (i = 0; i < output.length; i++) {
output[i].style.display = 'none';
}
var x = (this.x.animVal.value + this.width.animVal.value / 4) + "px";
var y = this.y.animVal.value + 25 + "px";
output.innerHTML = tag_exp;
output.style.top = d3.event.layerY + "px";
output.style.left = d3.event.layerX + "px";
output.style.display = "block";
}).on('mouSEOut',function() {
var output = document.getElementById("tag");
output.style.display = "none";
});
}
function makeGrid(theSidePad,height) {
var xAxis = d3.axisBottom(timeScale)
.ticks(d3.timeMonth)
.tickFormat(d3.timeFormat("%b"));
var grid = svg.append('g')
.attr('class','grid')
.attr('transform','translate(' + theSidePad + ',' + (title_x_height + 40) + ')')
.call(xAxis)
.selectAll("text")
.style("text-anchor","middle")
.attr("fill","#FF0000")
.attr("font-size","bold")
.attr("dy","1em");
}
function vertLabels(theGap,theColorScale) {
var numOccurances = [];
var prevGap = 0;
for (var i = 0; i < categories.length; i++) {
numOccurances[i] = [categories[i],getCount(categories[i],catsUnfiltered)];
}
// Titles of the Projects
var axisText = svg.append("g").attr("class","entityLink")
.selectAll("text")
.data(slicedData)
.enter()
.append("text")
.text(function(d) {
let name = d["Name"].length > 10 ? d["Name"].substring(0,10) + '...' : d["Name"];
return name;
})
.attr("x",31)
.attr("y",i) {
console.log('theGap :',' thetopPad :',' title_x_height :',title_x_height);
return i * theGap + thetopPad + title_x_height + 63;
})
.attr("font-size",20)
.attr("font-weight","bold")
.attr("text-anchor","start")
.attr("fill","#006dcc")
.style("cursor","pointer").style("text-decoration","underline");
*****// (+) Accordion for the projects
svg.append("g")
.selectAll("text")
.data(slicedData)
.enter()
.append("foreignObject").attr("width",20).attr("height",20).attr("x",10).attr("y",i) {
return i * theGap + thetopPad + title_x_height + 45;
}).append('xhtml:button').attr('class','accordion').on("click",function() {})*****
// Fire salesforce event on mouse click
d3.selectAll(".entityLink text")
.on("click",$A.getCallback(function(d,i) {
var clickevt = $A.get('e.c:GanttChartAppEvent');
console.log('click 2 => ',d);
clickevt.setParams({
"projects": d.Id,"projectdata": component.get("v.projectsData")
});
clickevt.fire();
}));
// Project title mouSEOver tool-tip
d3.selectAll(".entityLink text")
.on('mouSEOver',function(e) {
d3.select(this).style("stroke","#006dcc");
var tag_exp = "";
if (e != undefined) {
tag_exp = "<b>Project Title</b> :" + e.Name + "<br/>" +
"<b>Exp Start Date</b> :" + e.expStartTime + "<br/>" +
"<b>Exp End Date</b> :" + e.expEndTime;
}
var element = document.getElementById("tag");
var i;
for (i = 0; i < element.length; i++) {
element[i].style.display = 'none';
}
element.innerHTML = tag_exp;
element.style.top = d3.event.layerY + "px";
element.style.left = d3.event.layerX + "px";
element.style.display = "block";
}).on('mouSEOut',function() {
var element = document.getElementById("tag");
element.style.display = "none";
d3.select(this).style("stroke","none");
})
}
function checkUnique(arr) {
var hash = {},result = [];
for (var i = 0,l = arr.length; i < l; ++i) {
if (!hash.hasOwnProperty(arr[i])) { //it works with objects! in FF,at least
hash[arr[i]] = true;
result.push(arr[i]);
}
}
return result;
}
function getCounts(arr) {
var i = arr.length,// var to loop over
obj = {}; // obj to store results
while (i) obj[arr[--i]] = (obj[arr[i]] || 0) + 1; // count occurrences
return obj;
}
// get specific from everything
function getCount(word,arr) {
return getCounts(arr)[word] || 0;
}
//Slicing the dates for the 6 months range; When month or year changed (i.e.,Paginated) will show next set of six months data
function getSlicedDates(data) {
const adjustedData = data.map(item => {
let temp_obj = {
"Id": item.Id,"Name": item.Name,"expStartTime": item.expStartTime,"expEndTime": item.expEndTime,"actualStartTime": item.actualStartTime,"actualEndTime": item.actualEndTime
};
if (new Date(item.expStartTime) <= new Date(min_domain)) {
if (new Date(item.expEndTime) >= new Date(min_domain)) {
temp_obj['expStartTime'] = min_domain;
}
}
if (new Date(item.expStartTime) <= new Date(min_domain)) {
if (new Date(item.expEndTime) >= new Date(max_domain)) {
temp_obj['expStartTime'] = min_domain;
temp_obj['expEndTime'] = max_domain;
}
if (new Date(item.expEndTime) <= new Date(max_domain)) {
temp_obj['expStartTime'] = min_domain;
}
}
if (new Date(item.expStartTime) <= new Date(max_domain)) {
if (new Date(item.expEndTime) >= new Date(max_domain)) {
temp_obj['expEndTime'] = max_domain;
}
}
if (new Date(item.actualStartTime) <= new Date(min_domain)) {
if (new Date(item.actualEndTime) >= new Date(min_domain)) {
temp_obj['actualStartTime'] = min_domain;
}
}
if (new Date(item.actualStartTime) <= new Date(min_domain)) {
if (new Date(item.actualEndTime) >= new Date(max_domain)) {
temp_obj['actualStartTime'] = min_domain;
temp_obj['actualEndTime'] = max_domain;
}
if (new Date(item.actualEndTime) <= new Date(max_domain)) {
temp_obj['actualStartTime'] = min_domain;
}
}
if (new Date(item.actualStartTime) <= new Date(max_domain)) {
if (new Date(item.actualEndTime) >= new Date(max_domain)) {
temp_obj['actualEndTime'] = max_domain;
}
}
return temp_obj;
})
return adjustedData;
}
}
<div class="slds-grid">
<div class="container">
<div class="chart"></div>
<div Id="tag"></div>
</div>
</div>
感谢您的帮助!
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)