我正在尝试处理Google甘特图,并且总体上运行良好。但是,一些自定义要求使我抓狂了。
我希望任务标签在条形图内或条形图附近具有任务名称,这取决于条形图的宽度,位置。需要从y轴的左侧删除任务名称
此外,一旦图表变大,时间范围(x轴)将被放置在底部,因此将不可见,因此如果可以将其放置在顶部将非常好。
有什么方法可以实现这种自定义?
请检查下面提到的代码段以供参考。
import { Component, OnInit } from '@angular/core';
import { nightcycleDependencies } from './nightcycleData';
declare var google: any;
declare var $ :any;
@Component({
selector: 'app-chart',
templateUrl: './chart.component.html',
styleUrls: ['./chart.component.css']
})
export class ChartComponent implements OnInit {
public allTasks: any[] = [];
public nightcycleDependencies = nightcycleDependencies;
constructor() {
}
ngOnInit() {
this.renderChartForAll();
}
// Render Chart for Summarized View
renderChartForAll() {
google.charts.setOnLoadCallback(() => this.formatDataForAll());
}
// Data format for Summarized View
formatDataForAll() {
this.allTasks = [];
var resource = 'Job Cycles';
const today = new Date();
const start_day = today.getDate();
const end_day = today.getDate();
const month = today.getMonth() + 1;
const year = today.getFullYear();
nightcycleDependencies.forEach((dependency) => {
var finalStart = 9999999999999;
var finalEnd = 0;
var taskId = dependency.source.split(" ").join('');
var taskName = dependency.source;
var dependencies = dependency.parents ? dependency.parents.toString().split(" ").join("") : "null";
dependency.ids.forEach((job) => {
// Date handling
var startTime = new Date(year + '-' + month + '-' + start_day + ' ' + "12:00").getTime()
var startDate = new Date(year + '-' + month + '-' + start_day + ' ' + job.start).getTime()
var endDate = new Date(year + '-' + month + '-' + end_day + ' ' + job.end).getTime()
if (startTime > startDate) {
startDate = new Date(year + '-' + month + '-' + (start_day + 1) + ' ' + job.end).getTime()
endDate = new Date(year + '-' + month + '-' + (end_day + 1) + ' ' + job.end).getTime()
} else if (endDate < startDate) {
endDate = new Date(year + '-' + month + '-' + (end_day + 1) + ' ' + job.end).getTime()
}
if (finalStart > startDate) {
finalStart = startDate
}
if (finalEnd < endDate) {
finalEnd = endDate
}
});
var duration = finalEnd - finalStart
this.allTasks.push([taskId, taskName, taskName, new Date(finalStart), new Date(finalEnd), duration, 100, dependencies])
});
this.drawChart(this.allTasks, '');
}
// Render Chart for Selected Cycle
getCycleBasedData(source) {
google.charts.setOnLoadCallback(() => this.formatCycleBasedData(source));
}
// Data format for Selected Cycle
formatCycleBasedData(source) {
this.allTasks = [];
var resource = source;
var dependencies = [];
var chartSource = [];
var jobsFromOtherSources = [];
// Set The source to loop over
nightcycleDependencies.forEach(dependency => {
if (dependency.source === source) {
chartSource = dependency.ids;
}
});
chartSource.forEach((dependency) => {
var taskId = dependency.id.split(" ").join('');
var taskName = dependency.id;
dependencies = [];
// Date handling
var date = this.formatDate(dependency.start, dependency.end);
// Find out dependencies
dependency.parent.forEach((parent) => {
dependencies.push(parent.id.split(' ').join(''))
})
var finalDependencies = dependencies.toString();
// Get all Parent jobs and push them to task list
jobsFromOtherSources = this.getAllParentJobs(taskName, resource);
jobsFromOtherSources.forEach((otherJob) => {
var jobId = otherJob.id.split(" ").join('');
var jobName = otherJob.id;
var jobSource = otherJob.source;
var jobDate = this.formatDate(otherJob.start, otherJob.end);
this.allTasks.push([jobId, jobName, jobSource, new Date(jobDate[0]), new Date(jobDate[0] + 800000), (jobDate[0] + 800000 - jobDate[0]), 100, null])
})
// Get all Children jobs
// this.getAllChildJobs(taskName, resource);
// Push to the task list
this.allTasks.push([taskId, taskName, resource, new Date(date[0]), new Date(date[1]), (date[1] - date[0]), 100, finalDependencies])
});
this.drawChart(this.allTasks, source);
}
// Function to handle date
formatDate(start, end) {
const today = new Date();
var startTime = 0;
var startDate = 0;
var endDate = 0;
const start_day = today.getDate();
const end_day = today.getDate();
const month = today.getMonth() + 1;
const year = today.getFullYear();
startTime = new Date(year + '-' + month + '-' + start_day + ' ' + "12:00").getTime()
startDate = new Date(year + '-' + month + '-' + start_day + ' ' + start).getTime()
endDate = new Date(year + '-' + month + '-' + end_day + ' ' + end).getTime()
if (startTime > startDate) {
startDate = new Date(year + '-' + month + '-' + (start_day + 1) + ' ' + start).getTime()
endDate = new Date(year + '-' + month + '-' + (end_day + 1) + ' ' + end).getTime()
} else if (endDate < startDate) {
endDate = new Date(year + '-' + month + '-' + (end_day + 1) + ' ' + end).getTime()
}
return [startDate, endDate]
}
// Get all Parent Jobs
getAllParentJobs(name, source) {
var job = {};
var jobSource = '';
var jobsFromOtherSources = [];
nightcycleDependencies.forEach((dependency) => {
if (dependency.source != source) {
jobSource = dependency.source;
dependency.ids.forEach((job) => {
job = job;
job.source = jobSource
job.children.forEach((child) => {
if (child.id === name) {
jobsFromOtherSources.push(job);
}
});
});
}
});
return jobsFromOtherSources;
}
// Get all children jobs
// getAllChildJobs(name, source) {
// }
// Chart configuration
drawChart(allTasks, source) {
var nightcycleData = new google.visualization.DataTable();
nightcycleData.addColumn('string', 'Task ID');
nightcycleData.addColumn('string', 'Task Name');
nightcycleData.addColumn('string', 'Resource');
nightcycleData.addColumn('date', 'Start');
nightcycleData.addColumn('date', 'End');
nightcycleData.addColumn('number', 'Duration');
nightcycleData.addColumn('number', 'Percent Complete');
nightcycleData.addColumn('string', 'Dependencies');
nightcycleData.addRows(this.allTasks);
var trackHeight = 50;
var options = {
height: nightcycleData.getNumberOfRows() * trackHeight + 200,
gantt: {
labelStyle: {
fontName: ["RobotoCondensedRegular"],
fontSize: 15
},
textPosition: 'none',
innerGridTrack: { fill: '#fff3e0' },
innerGridDarkTrack: { fill: '#ffcc80' },
trackHeight: trackHeight
}
};
var chart = new google.visualization.Gantt(source ? document.getElementById(source.split(' ').join('')) : document.getElementById('chart_div'));
chart.draw(nightcycleData, options);
// Event listener which will fire on bar selection
google.visualization.events.addListener(chart, 'select', () => this.getSelectedBarInfo(nightcycleData, chart));
}
// Change chart tab programmatically
getSelectedBarInfo(nightcycleData, chart) {
var selection = chart.getSelection();
if (selection.length) {
var cycle = nightcycleData.getValue(selection[0].row, 2);
this.getCycleBasedData(cycle);
var cycleId = cycle.split(" ").join("");
document.querySelector('.tab-pane.fade.active.show').classList.remove('active', 'show');
document.querySelector('.nav-link.active').classList.remove('active');
document.getElementById(cycleId).classList.add('active', 'show');
document.getElementById('id'+cycleId).classList.add('active', 'show');
}
}
//For Responsiveness on resizing
onResize(event) {
this.drawChart(this.allTasks, event.target.id);
}
}
.btn-holders{
padding:10px;
}
.chart-tabs{
padding: 20px 0px;
}
.chart-btn{
margin: 5px;
}
.chart-item{
float:left;
padding:20px 20px 20px 0px;
list-style: none;
}
.chart-list{
padding: 0px;
}
.chart-anchor{
background-color: #c0b5d0;
padding: 20px;
border-radius: 10px;
color: #0c5460;
}
.chart-anchor.active {
background-color: dodgerblue;
color:#fff;
}
.tab-content>.tab-pane {
height: 1px;
overflow: hidden;
display: block;
visibility: hidden;
}
.tab-content>.active {
height: auto;
overflow: hidden;
visibility: visible;
}
<div class="container-fluid">
<!-- Tabs -->
<div class="chart-tabs">
<ul class="nav nav-pills" role="tablist">
<li class="nav-item">
<a [attr.id]="'idall'" class="nav-link active" data-toggle="pill" href="#all" role="tab">All</a>
</li>
<li class="nav-item" *ngFor="let dependency of nightcycleDependencies" (click)="getCycleBasedData(dependency.source)">
<a [attr.id]="'id'+dependency.source.split(' ').join('')" class="nav-link" data-toggle="pill" [attr.href]="'#'+dependency.source.split(' ').join('')" role="tab">{{dependency.source}}</a>
</li>
</ul>
</div>
<!-- Tab Content -->
<div class="tab-content">
<div id="all" class="tab-pane fade in active show" role="tabpanel">
<div id="chart_div" style="width:100%;" (window:resize)="onResize($event)"></div>
</div>
<div id="DailyProcessing" style="width:100%;" class="tab-pane fade" role="tabpanel">
<div (window:resize)="onResize($event)"></div>
</div>
<div id="TradeMgmtandProcessing" style="width:100%;" class="tab-pane fade" role="tabpanel">
<div (window:resize)="onResize($event)"></div>
</div>
<div id="DailyAnalyticsCycle" style="width:100%;" class="tab-pane fade" role="tabpanel">
<div (window:resize)="onResize($event)"></div>
</div>
<div id="EuropeCycle" style="width:100%;" class="tab-pane fade" role="tabpanel">
<div (window:resize)="onResize($event)"></div>
</div>
<div id="USCycle" style="width:100%;" class="tab-pane fade" role="tabpanel">
<div (window:resize)="onResize($event)"></div>
</div>
</div>
</div>
答案 0 :(得分:0)
没关系,我通过一点DOM操作就得到了答案:
添加事件监听器,该监听器应在图表准备就绪后触发
google.visualization.events.addListener(chart, 'ready', () => this.addLabelText(chartId, this.allTasks));
函数的主体应如下所示,
addLabelText(chartId, allTasks) {
var toContainer = $('#' + chartId + ' > div > div');
$("#" + chartId + " g:eq(5) rect").each(function ($index) {
if($(this).attr('width') < (allTasks[$index][1].length * 7)) {
if((Number($(this).attr('x')) + Number($(this).attr('width')) + 100) > document.body.clientWidth) {
toContainer.append("<div style='top:" + $(this).attr('y') + "px; left: " + (Number($(this).attr('x')) - (allTasks[$index][1].length * 7)) +
"px; text-align: left;position:absolute;line-height:2; padding-left: 5px; color:#111; font-size:14px;'>" + allTasks[$index][1] + "</div>");
} else {
toContainer.append("<div style='top:" + $(this).attr('y') + "px; left: " + (Number($(this).attr('x')) + Number($(this).attr('width'))) +
"px; text-align: left;position:absolute;line-height:2; padding-left: 5px; color:#111; font-size:14px;'>" + allTasks[$index][1] + "</div>");
}
} else {
toContainer.append("<div style='top:" + $(this).attr('y') + "px; left: " + Number($(this).attr('x')) +
"px; text-align: left;position:absolute;line-height:2; padding-left: 5px; color:#fff; font-size:14px;'>" + allTasks[$index][1] + "</div>");
}
});
}
根据您的需要进行一些自定义,它应该可以正常工作。