I need visualize the deference in plan and actual progress like any simple comparison line chart.
I wrote (Dojo Demo):
var plan = [
{ depth: 00, day: 0 },
{ depth: 50, day: 4 },
{ depth: 45, day: 11},
{ depth: 55, day: 16},
];
var actual = [
{ depth: 00, day: 0 },
{ depth: 55, day: 7 },
{ depth: 50, day: 11},
{ depth: 50, day: 13},
];
function createChart() {
$("#chart").kendoChart({
title: {
text: "Progress Comparision"
},
series: [{
name:"Plan",
type: "line",
data:plan,
field: "depth",
categoryField: "day"
},
{
name:"Actual",
type: "line",
data:actual,
field: "depth",
categoryField: "day"
}],
categoryAxis: {
justified: true,
categories: [0,5,10,15,20]
}
});
}
I got this:
But I expect something similar to this:
Any Idea?
The type of series should be scatterLine not line: (Final Demo)
var plan = [
{ depth: 00, day: 0 },
{ depth: 50, day: 4 },
{ depth: 45, day: 11},
{ depth: 55, day: 16},
];
var actual = [
{ depth: 00, day: 0 },
{ depth: 55, day: 7 },
{ depth: 50, day: 11},
{ depth: 50, day: 13},
];
function createChart() {
$("#chart").kendoChart({
title: {
text: "Progress Comparision"
},
series: [{
name:"Plan",
type: "scatterLine",
data:plan,
yField: "depth",
xField: "day"
},
{
name:"Actual",
type: "scatterLine",
data:actual,
yField: "depth",
xField: "day"
}],
xAxis: {
justified: true,
max: 20,
}
});
}
Related
I've got a Gantt chart:
And I want to use the series.gantt.custom object to set specific properties for each series on the yAxis.
From these properties I want to construct the yAxis labels.
My code:
Highcharts.ganttChart('container', {
yAxis: {
categories: ['1', '2'],
labels: {
formatter() {
return this.value
/* + this.chart.series[this.pos].custom.size */
},
}
},
series: [{
groupPadding: 1,
custom: {
size: "small",
},
type: 'line',
zoneAxis: 'x',
data: [{
y: 0,
x: Date.UTC(2022, 10, 18),
custom: {
label: 1,
}
}, {
y: 0,
x: Date.UTC(2022, 10, 25, 12),
custom: {
label: 2
}
}]
}, {
type: 'line',
zoneAxis: 'x',
custom: {
size: "large",
},
data: [{
y: 1,
x: Date.UTC(2022, 10, 18),
custom: {
label: 1
}
}, {
y: 1,
x: Date.UTC(2022, 10, 25, 12),
custom: {
label: 2
}
}]
}]
});
this.chart.series[this.pos].custom.size it's the bit that is not working.
The labels should be 1 small and 2 large.
A fiddle
You can reach this property through the series.options:
this.chart.series[this.pos].options.custom.size
Demo:
https://jsfiddle.net/BlackLabel/gLkn9uqf/
I'm using Highcharts Gantt to display my data. But I've stacked with one problem: I cannot rotate X-Axis labels. Sometime I have to display long time period on the small screen and it looks like on this pic:
It's almost 4 year on this pic and some moths are missed. The best solution (in my opinion) is to rotate labels. I've tried this:
xAxis: { labels: { rotation: 90 } }, but it seems that this not working for Gantt. The full working example is here: (code copied from Highchart documentation)
Highcharts.ganttChart('container', {
title: {
text: 'Left Axis as Table'
},
xAxis: {
tickPixelInterval: 70,
dateTimeLabelFormats: {
week: "%w"
},
labels: {
rotation: 90
}
},
yAxis: {
type: 'category',
grid: {
enabled: true,
borderColor: 'rgba(0,0,0,0.3)',
borderWidth: 1,
columns: [{
title: {
text: 'Project'
},
labels: {
format: '{point.name}'
}
}, {
title: {
text: 'Assignee'
},
labels: {
format: '{point.assignee}'
}
}, {
title: {
text: 'Est. days'
},
labels: {
formatter: function () {
var point = this.point,
days = (1000 * 60 * 60 * 24),
number = (point.x2 - point.x) / days;
return Math.round(number * 100) / 100;
}
}
}, {
labels: {
format: '{point.start:%e. %b}'
},
title: {
text: 'Start date'
}
}, {
title: {
text: 'End date'
},
offset: 30,
labels: {
format: '{point.end:%e. %b}'
}
}]
}
},
tooltip: {
xDateFormat: '%e %b %Y, %H:%M'
},
series: [{
name: 'Project 1',
data: [{
start: Date.UTC(2017, 10, 18, 8),
end: Date.UTC(2017, 10, 25, 16),
name: 'Start prototype',
assignee: 'Richards',
y: 0
}, {
start: Date.UTC(2017, 10, 20, 8),
end: Date.UTC(2017, 10, 24, 16),
name: 'Develop',
assignee: 'Michaels',
y: 1
}, {
start: Date.UTC(2017, 10, 25, 16),
end: Date.UTC(2017, 10, 25, 16),
name: 'Prototype done',
assignee: 'Richards',
y: 2
}, {
start: Date.UTC(2017, 10, 27, 8),
end: Date.UTC(2017, 11, 3, 16),
name: 'Test prototype',
assignee: 'Richards',
y: 3
}, {
start: Date.UTC(2017, 10, 23, 8),
end: Date.UTC(2017, 11, 15, 16),
name: 'Run acceptance tests',
assignee: 'Halliburton',
y: 4
}]
}],
exporting: {
sourceWidth: 1000
}
});
#container {
max-width: 1200px;
min-width: 800px;
height: 400px;
margin: 1em auto;
}
.scrolling-container {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
<script src="https://code.highcharts.com/gantt/highcharts-gantt.js"></script>
<script src="https://code.highcharts.com/gantt/modules/exporting.js"></script>
<div class="scrolling-container">
<div id="container"></div>
</div>
Is some other way to rotate X-Axis labels?
It looks that the rotation feature is not supported if grid is enabled for an axis. You can disable grid (example: http://jsfiddle.net/BlackLabel/Ltnhu739/) or write a piece of code to operate directly on svg elements:
chart: {
events: {
render: function() {
const ticks = this.xAxis[0].ticks;
for (let tickPos in ticks) {
ticks[tickPos].label.attr({
rotate: -90,
translateX: 10
});
}
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/y9kqf1xu/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGElement#attr
(Highcharts version 6)
Is it possible to have a time line looking chart in addition to data points like in this example:
https://jsfiddle.net/s1eL30Lh/97/
<script src="https://code.highcharts.com/stock/highstock.js"></script>
but without using highstock and instead only use highcharts ?
I know it's possible to use xrange module but it's not quite the same:
https://jsfiddle.net/deep3015/q18yvy75/
If the ranges are long enough to simulate a line then you lack the ability to add "data points" on top of the line, and if you make the ranges small enough to look like data points then you don't have a line.
NOTE
I'm aware of the new chart type 'timeline' in version 7 but I need to work with version 6.1
Yes, it is possible. However, you can't use flags series because it is only supported by Highstock. Check the demo and code posted below.
Code:
function toMs(yeah, month) {
return Date.UTC(yeah, month, 1);
}
var series = [{
// First series
name: 'Running',
color: 'green',
id: 'green',
dataRaw: [{
y: 1,
xRanges: [
// first value: from; second value: to
[toMs(2000, 1), toMs(2002, 8)],
[toMs(2006, 10), toMs(2006, 11)]
]
}]
}, {
// Second series
name: 'Filed',
color: 'yellow',
id: 'yellow',
dataRaw: [{
y: 1,
xRanges: [
// first value: from; second value: to
[toMs(2002, 8), toMs(2006, 10)]
]
}]
},
{
// Second series
name: 'Granted',
color: 'blue',
id: 'blue',
dataRaw: [{
y: 1,
xRanges: [
// first value: from; second value: to
[toMs(2006, 11), toMs(2021, 8)]
]
}]
}
].map(function(series) {
series.data = [];
series.dataRaw.forEach(function(dataRaw) {
dataRaw.xRanges.forEach(function(xRange) {
series.data.push([xRange[0], dataRaw.y], [xRange[1], dataRaw.y], [xRange[1], null]); // null breakes the line
}); // forEach
}); // forEach
return series;
});
console.log(series);
var chart = Highcharts.chart('container', {
chart: {
type: 'scatter'
},
title: {
text: 'Example'
},
plotOptions: {
scatter: {
lineWidth: 5,
marker: {
enabled: true,
symbol: 'circle',
fillColor: '#FFFFFF',
lineWidth: 2,
lineColor: null,
radius: 5
},
dataLabels: {
enabled: true,
align: 'right',
rotation: -30,
x: -2,
y: 15,
formatter: function() {
return Highcharts.dateFormat('%Y-%m', this.x);
}
},
tooltip: {
pointFormatter: function() {
return Highcharts.dateFormat('%Y-%m', this.x);
}
}
},
flags: {
lineWidth: 1
}
},
xAxis: {
title: {
text: 'Time'
},
type: 'datetime',
minTickInterval: 365 * 24 * 36e5,
labels: {
align: 'left'
},
plotBands: [{
from: Date.UTC(2000, 10, 27),
to: Date.UTC(2004, 11, 1),
color: '#EFFFFF',
label: {
text: 'Office 1',
style: {
color: '#999999'
},
y: 30
}
}, {
from: Date.UTC(2004, 11, 1),
to: Date.UTC(2012, 9, 1),
color: '#FFFFEF',
label: {
text: 'Office 2',
style: {
color: '#999999'
},
y: 30
}
}, {
from: Date.UTC(2012, 9, 1),
to: Date.UTC(2020, 10, 27),
color: '#FFEFFF',
label: {
text: 'Office 3',
style: {
color: '#999999'
},
y: 30
}
}]
},
yAxis: {
tickInterval: 1
},
series: series,
annotations: [{
labelOptions: {
backgroundColor: 'rgba(255,255,255,0.5)'
},
labels: [{
distance: 10,
point: {
xAxis: 0,
yAxis: 0,
x: toMs(2002, 8),
y: 1
},
text: 'Filled Date'
}]
}]
});
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/6.1/highcharts.js"></script>
<script src="https://code.highcharts.com/6.1/modules/annotations.js"></script>
<div id="container" style="height: 400px"></div>
Demo:
https://jsfiddle.net/BlackLabel/6eahoxjv/
I'm using jqxPiveGrid, but it doesn't work, and the problems showed on console: Uncaught TypeError: $.jqx.pivot is not a constructor.
enter image description here
I'm using Visual Studio 2015, (ASP.Net MVC) for the website.
There's my code below:
var dataList = new Array();
dataList= [
{ Style: 'Top', RangeStart: 0, RangeEnd: 10, Day: 1, Value: 0 },
{ Style: 'Top', RangeStart: 0, RangeEnd: 10, Day: 2, Value: 2 },
{ Style: 'Top', RangeStart: 0, RangeEnd: 10, Day: 3, Value: 3 },
{ Style: 'Top', RangeStart: 10.1, RangeEnd: 15, Day: 1, Value: 4 },
{ Style: 'Top', RangeStart: 10.1, RangeEnd: 15, Day: 2, Value: 8 },
{ Style: 'Top', RangeStart: 10.1, RangeEnd: 15, Day: 3, Value: 12 },
{ Style: 'Pants ', RangeStart: 0, RangeEnd: 10, Day: 1, Value: 0 },
{ Style: 'Pants ', RangeStart: 0, RangeEnd: 10, Day: 2, Value: 1 },
{ Style: 'Pants ', RangeStart: 0, RangeEnd: 10, Day: 3, Value: 2 },
{ Style: 'Pants ', RangeStart: 10.1, RangeEnd: 15, Day: 1, Value: 3 },
{ Style: 'Pants ', RangeStart: 10.1, RangeEnd: 15, Day: 2, Value: 5 },
{ Style: 'Pants ', RangeStart: 10.1, RangeEnd: 15, Day: 3, Value: 7 },
];
var source =
{
localdata: dataList,
datatype: "array",
datafields:
[
{ name: 'Style', type: 'string' },
{ name: 'RangeStart', type: 'number' },
{ name: 'RangeEnd', type: 'number' },
{ name: 'Day', type: 'number' },
{ name: 'Value', type: 'number' },
]
};
var dataAdapter = new $.jqx.dataAdapter(source);
// create a pivot adapter from the dataAdapter
var pivotAdapter = new $.jqx.pivot(
dataAdapter,
{
pivotValuesOnRows: false,
rows: [ { dataField: 'Style' }, {dataField: 'RangeStart'}, {dataField: 'RangeEnd'}],
columns: [
{ dataField: 'Day'},
],
values: [
{ dataField: 'Value', 'function': '', text: '',formatSettings: { decimalPlaces: 2, align: 'right', }},
]
});
$('#divPivotGrid').jqxPivotGrid(
{
source: pivotAdapter,
treeStyleRows: true,
autoResize: false,
multipleSelectionEnabled: true
});
setTimeout(_ =>
{
var myPivotGridRows = $('#divPivotGrid').jqxPivotGrid('getPivotRows');
var myPivotGridColumns = $('#divPivotGrid').jqxPivotGrid('getPivotColumns');
var items = myPivotGridColumns.items;
var firstItem = items[0];
var firstItemValueItems = firstItem.valueItems[0];
var otherHierarchy = firstItem.hierarchy.getHierarchyDepth();
myPivotGridRows.sortBy(firstItemValueItems, 'desc');
}, 1500);
But it works perfectly on here:
https://jseditor.io/?key=pivotgrid-demonstration-of-sortby-method
I have an array of objects that need to be filtered through, and displayed depending on which checkbox is selected. I can get it to work with a one dimension array, when I nest deeper I don't understand how to get everything working again.
This is the initial function that filters the array:
computed: {
selectedFilters: function() {
let filters = [];
let checkedFilters = this.shopFilters.filter(obj => obj.checked);
checkedFilters.forEach(element => {
filters.push(element.value);
});
return filters;
}
}
Tis is the data it pulls from:
shopFilters: [
{
name: 'price',
categories: [
{
checked: false,
value: 'Under $50'
},
{
checked: false,
value: '$50 to $100'
},
{
checked: false,
value: '$100 to $150'
},
{
checked: false,
value: '$150 to $200'
},
{
checked: false,
value: 'Over $200'
},
]
},
{
name: 'sports',
categories: [
{
checked: false,
value: 'lifestyle'
},
{
checked: false,
value: 'running'
},
{
checked: false,
value: 'basketball'
},
{
checked: false,
value: 'football'
},
{
checked: false,
value: 'soccer'
},
{
checked: false,
value: 'training & gym'
},
{
checked: false,
value: 'skateboarding'
},
{
checked: false,
value: 'baseball / softball'
},
{
checked: false,
value: 'golf'
}
]
}
]
This is the function that filters through the product data in another file to display on the page:
methods: {
getfilteredData: function() {
this.filteredData = data;
let filteredDataByfilters = [];
// first check if filters where selected
if (this.selectedFilters.length > 0) {
filteredDataByfilters= this.filteredData.filter(obj => this.selectedFilters.every(val => obj.indexOf(val) >= 0));
this.filteredData = filteredDataByfilters;
}
}
}
What the data looks like:
const data = [
{
name: 'SNKR 001',
gender: 'Men',
price: 100,
sport: 'running',
width: 'Wide',
colors: ['black', 'white', 'green', 'pink'],
sizes: [3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.5, 13, 14, 15],
image: '../assets/images/shoe-1.png'
},
{
name: 'SNKR 002',
gender: 'Men',
price: 100,
sport: 'running',
width: 'Wide',
colors: ['black', 'white', 'green', 'pink'],
sizes: [3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.5, 13, 14, 15],
image: '../assets/images/shoe-1.png'
},
{
name: 'SNKR 003',
gender: 'Men',
price: 100,
sport: 'training & gym',
width: 'Wide',
colors: ['black', 'white', 'green', 'pink'],
sizes: [3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.5, 13, 14, 15],
image: '../assets/images/shoe-1.png'
},
{
name: 'SNKR 004',
gender: 'Men',
price: 100,
sport: 'lifestyle',
width: 'Wide',
colors: ['black', 'white', 'green', 'pink'],
sizes: [3, 3.5, 4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.5, 13, 14, 15],
image: '../assets/images/shoe-1.png'
}
];
export default data;
You can merge all filter into 1 array:
const categories = this.shopFilters.map(item => item.categories)
const flatFilters = [].concat.apply([], categories)
then the filter will become flat:
flatFilters: [{
checked: false,
value: 'Under $50'
},
{
checked: false,
value: '$50 to $100'
},
{
checked: false,
value: '$100 to $150'
},
{
checked: false,
value: '$150 to $200'
},
{
checked: false,
value: 'Over $200'
},
{
checked: false,
value: 'lifestyle'
},
{
checked: false,
value: 'running'
},
{
checked: false,
value: 'basketball'
},
{
checked: false,
value: 'football'
},
{
checked: false,
value: 'soccer'
},
{
checked: false,
value: 'training & gym'
},
{
checked: false,
value: 'skateboarding'
},
{
checked: false,
value: 'baseball / softball'
},
{
checked: false,
value: 'golf'
}
]
then use can apply old logic
computed: {
selectedFilters: function() {
let filters = [];
const categories = this.shopFilters.map(item => item.categories)
const flatFilters = [].concat.apply([], categories)
let checkedFilters = flatFilters.filter(obj => obj.checked);
checkedFilters.forEach(element => {
filters.push(element.value);
});
return filters;
}