mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-18 06:49:47 +02:00
Better styling for gantt diagrams and addition of critical path, active and completed tasks
This commit is contained in:
@@ -3,16 +3,18 @@ gantt.yy = require('./ganttDb');
|
||||
var d3 = require('./d3');
|
||||
|
||||
var conf = {
|
||||
titleTopMargin:25,
|
||||
barHeight:20,
|
||||
barGap:4,
|
||||
topPadding:75,
|
||||
sidePadding:75
|
||||
titleTopMargin: 25,
|
||||
barHeight: 20,
|
||||
barGap: 4,
|
||||
topPadding: 50,
|
||||
sidePadding: 75,
|
||||
gridLineStartPadding: 35,
|
||||
fontSize: 11
|
||||
};
|
||||
module.exports.setConf = function(cnf){
|
||||
module.exports.setConf = function (cnf) {
|
||||
var keys = Object.keys(cnf);
|
||||
|
||||
keys.forEach(function(key){
|
||||
keys.forEach(function (key) {
|
||||
conf[key] = cnf[key];
|
||||
});
|
||||
};
|
||||
@@ -22,18 +24,18 @@ module.exports.draw = function (text, id) {
|
||||
gantt.parse(text);
|
||||
var elem = document.getElementById(id);
|
||||
w = elem.offsetWidth;
|
||||
|
||||
if(typeof w === 'undefined'){
|
||||
|
||||
if (typeof w === 'undefined') {
|
||||
w = 800;
|
||||
}
|
||||
|
||||
var taskArray = gantt.yy.getTasks();
|
||||
|
||||
// Set height based on number of tasks
|
||||
var h = taskArray.length*(conf.barHeight+conf.barGap)+2*conf.topPadding;
|
||||
|
||||
elem.style.height = h+'px';
|
||||
var svg = d3.select('#'+id);
|
||||
var taskArray = gantt.yy.getTasks();
|
||||
|
||||
// Set height based on number of tasks
|
||||
var h = taskArray.length * (conf.barHeight + conf.barGap) + 2 * conf.topPadding;
|
||||
|
||||
elem.style.height = h + 'px';
|
||||
var svg = d3.select('#' + id);
|
||||
|
||||
// http://codepen.io/anon/pen/azLvWR
|
||||
|
||||
@@ -67,9 +69,7 @@ module.exports.draw = function (text, id) {
|
||||
.text(gantt.yy.getTitle())
|
||||
.attr("x", w / 2)
|
||||
.attr("y", conf.titleTopMargin)
|
||||
.attr("text-anchor", "middle")
|
||||
.attr("font-size", 18)
|
||||
.attr("fill", "#009FFC");
|
||||
.attr('class', 'titleText');
|
||||
|
||||
|
||||
function makeGant(tasks, pageWidth, pageHeight) {
|
||||
@@ -106,15 +106,14 @@ module.exports.draw = function (text, id) {
|
||||
return w - theSidePad / 2;
|
||||
})
|
||||
.attr("height", theGap)
|
||||
.attr("stroke", "none")
|
||||
.attr("fill", function (d) {
|
||||
.attr('class', function (d) {
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
if (d.type === categories[i]) {
|
||||
return d3.rgb(theColorScale(i));
|
||||
return 'section section' + (i % conf.numberSectionStyles);
|
||||
}
|
||||
}
|
||||
})
|
||||
.attr("opacity", 0.2);
|
||||
return 'section section0';
|
||||
});
|
||||
|
||||
|
||||
var rectangles = svg.append('g')
|
||||
@@ -124,68 +123,100 @@ module.exports.draw = function (text, id) {
|
||||
|
||||
|
||||
var innerRects = rectangles.append("rect")
|
||||
.attr("rx", 3)
|
||||
.attr("ry", 3)
|
||||
.attr("x", function (d) {
|
||||
return timeScale(d.startTime) + theSidePad;
|
||||
})
|
||||
.attr("y", function (d, i) {
|
||||
return i * theGap + theTopPad;
|
||||
})
|
||||
.attr("width", function (d) {
|
||||
return (timeScale(d.endTime) - timeScale(d.startTime));
|
||||
})
|
||||
.attr("height", theBarHeight)
|
||||
.attr("stroke", "none")
|
||||
.attr("fill", function (d) {
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
if (d.type === categories[i]) {
|
||||
return d3.rgb(theColorScale(i));
|
||||
.attr("rx", 3)
|
||||
.attr("ry", 3)
|
||||
.attr("x", function (d) {
|
||||
return timeScale(d.startTime) + theSidePad;
|
||||
})
|
||||
.attr("y", function (d, i) {
|
||||
return i * theGap + theTopPad;
|
||||
})
|
||||
.attr("width", function (d) {
|
||||
return (timeScale(d.endTime) - timeScale(d.startTime));
|
||||
})
|
||||
.attr("height", theBarHeight)
|
||||
.attr('class', function (d) {
|
||||
var res = 'task ';
|
||||
|
||||
|
||||
var secNum = 0;
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
if (d.type === categories[i]) {
|
||||
secNum = (i % conf.numberSectionStyles);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(d.active){
|
||||
if (d.crit) {
|
||||
return res + ' activeCrit'+secNum;
|
||||
}else{
|
||||
return res + ' active'+secNum;
|
||||
}
|
||||
}
|
||||
|
||||
if (d.done) {
|
||||
if (d.crit) {
|
||||
return res + ' doneCrit'+secNum;
|
||||
}else{
|
||||
return res + ' done'+secNum;
|
||||
}
|
||||
}
|
||||
|
||||
if (d.crit) {
|
||||
return res + ' crit'+secNum;
|
||||
}
|
||||
|
||||
|
||||
return res + ' task'+secNum;
|
||||
})
|
||||
;
|
||||
|
||||
|
||||
var rectText = rectangles.append("text")
|
||||
.text(function (d) {
|
||||
return d.task;
|
||||
})
|
||||
.attr("font-size", 11)
|
||||
.attr("x", function (d) {
|
||||
var startX = timeScale(d.startTime),
|
||||
endX = timeScale(d.endTime),
|
||||
textWidth = this.getBBox().width;
|
||||
|
||||
|
||||
// Check id text width > width of rectangle
|
||||
if(textWidth>(endX-startX)){
|
||||
if (endX + textWidth > w){
|
||||
if (textWidth > (endX - startX)) {
|
||||
if (endX + textWidth > w) {
|
||||
return startX + theSidePad;
|
||||
}else {
|
||||
} else {
|
||||
return endX + theSidePad;
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
return (endX - startX) / 2 + startX + theSidePad;
|
||||
}
|
||||
})
|
||||
.attr("y", function (d, i) {
|
||||
return i * theGap + 14 + theTopPad;
|
||||
return i * theGap + (conf.barHeight / 2) + (conf.fontSize / 2 - 2) + theTopPad;
|
||||
})
|
||||
//.attr("text-anchor", "middle")
|
||||
.attr("text-height", theBarHeight)
|
||||
.attr("class",function (d) {
|
||||
.attr("class", function (d) {
|
||||
var startX = timeScale(d.startTime),
|
||||
endX = timeScale(d.endTime),
|
||||
textWidth = this.getBBox().width;
|
||||
|
||||
// Check id text width > width of rectangle
|
||||
if(textWidth>(endX-startX)) {
|
||||
if (endX + textWidth > w){
|
||||
return 'taskTextOutsideLeft';
|
||||
}else {
|
||||
return 'taskTextOutsideRight';
|
||||
var secNum = 0;
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
if (d.type === categories[i]) {
|
||||
secNum = (i % conf.numberSectionStyles);
|
||||
}
|
||||
}else{
|
||||
return 'taskText';
|
||||
}
|
||||
|
||||
// Check id text width > width of rectangle
|
||||
if (textWidth > (endX - startX)) {
|
||||
if (endX + textWidth > w) {
|
||||
return 'taskTextOutsideLeft taskTextOutside' + secNum;
|
||||
} else {
|
||||
return 'taskTextOutsideRight taskTextOutsideRight' + secNum;
|
||||
}
|
||||
} else {
|
||||
return 'taskText taskText' + secNum;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -198,8 +229,8 @@ module.exports.draw = function (text, id) {
|
||||
.scale(timeScale)
|
||||
.orient('bottom')
|
||||
//.ticks(d3.time.days, 5)
|
||||
.tickSize(-h + theTopPad + 20, 0, 0)
|
||||
.tickFormat(d3.time.format('%d %b'));
|
||||
.tickSize(-h + theTopPad + conf.gridLineStartPadding, 0, 0);
|
||||
//.tickFormat(d3.time.format('%d %b'));
|
||||
|
||||
var grid = svg.append('g')
|
||||
.attr('class', 'grid')
|
||||
@@ -241,16 +272,13 @@ module.exports.draw = function (text, id) {
|
||||
return d[1] * theGap / 2 + theTopPad;
|
||||
}
|
||||
})
|
||||
.attr("font-size", 11)
|
||||
.attr("text-anchor", "start")
|
||||
.attr("text-height", 14)
|
||||
.attr("fill", function (d) {
|
||||
.attr('class', function (d) {
|
||||
for (var i = 0; i < categories.length; i++) {
|
||||
if (d[0] === categories[i]) {
|
||||
// console.log("true!");
|
||||
return d3.rgb(theColorScale(i)).darker();
|
||||
return 'sectionTitle sectionTitle' + (i % conf.numberSectionStyles);
|
||||
}
|
||||
}
|
||||
return 'sectionTitle';
|
||||
});
|
||||
|
||||
}
|
||||
@@ -271,9 +299,9 @@ module.exports.draw = function (text, id) {
|
||||
function getCounts(arr) {
|
||||
var i = arr.length, // var to loop over
|
||||
obj = {}; // obj to store results
|
||||
while (i){
|
||||
while (i) {
|
||||
obj[arr[--i]] = (obj[arr[i]] || 0) + 1; // count occurrences
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user