I have a situation where I am trying to get x-axis category values to show up in the HighCharts chart lined up with the ticks rather than on center of each 'bin' on the x-axis. It seems using text "categories" in the x-axis is part of the issue. Is there an easy way to do this?
Here is a sample of the json.stringified version of my options and a screen shot:
Highcharts.chart('container', {
"chart":{
"renderTo":"",
"zoomType":"xy",
"alignTicks":false,
"animation":false,
"height":600,
"type":"line",
"backgroundColor":"#fff",
"resetZoomButton":{
"theme":{
"fill":"white",
"stroke":"silver",
"r":0,
"states":{
"hover":{
"fill":"#7ac142",
"style":{
"color":"white"
}
}
}
}
},
"options3d":"",
"panning":true,
"panKey":"shift"
},
title: {
text: 'Step line types, with null values in the series'
},
xAxis:{
"align":"left",
"categories":[
"0:00",
"1:00",
"2:00",
"3:00",
"4:00",
"5:00",
"6:00",
"7:00",
"8:00",
"9:00",
"10:00",
"11:00",
"12:00",
"13:00",
"14:00",
"15:00",
"16:00",
"17:00",
"18:00",
"19:00",
"20:00",
"21:00",
"22:00",
"23:00"
],
"title":{
"text":"",
"style":{
"color":"#3E576F",
"font-family":"Verdana",
"font-size":"12px"
}
}
},
"series":[
{
"data":[
72.2,
71.5,
71.7,
71.2,
73.6,
73.5,
72,
71.4,
69.7,
70.8,
70.9,
71.3,
72,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
"name":"The Data",
"color":"#1AC8ED"
},
],
});
Example
This can be set using the tickmarkPlacement option. For categorized axis it defaults to between, while other axis have it on. You need to set it on.
For example (JSFiddle):
xAxis:{
tickmarkPlacement: 'on'
// ...
}
Related
I have 2 spline charts that I want to compare on a singe graph. The first should take up the top 25% of the plot area and the second should take up the bottom 75% of the plot area. To achieve this, I tried the following:
"yAxis": [{
"height": "25%",
"id": "blue",
"labels": {
"enabled": false
},
"title": {
"text": ""
},
"min": 267.15,
"max": 289.15,
"index": 0
},{
"id": "red",
"height":"75%",
"top": "25%",
"min": 265,
"max": 290,
"plotLines": [{
"color": "#fff8df",
"value": 285.15
}, {
"color": "#fff8df",
"value": 279.15
}, {
"color": "#c5eded",
"value": 273.15
}],
"index": 1
}],
The problem with this is that I have a min/max set (the graph is showing temperatures and we only care about a certain range). Because of these combined things, the graph is drawing right over the xAxis and outside of the expected plot area.
see: https://jsfiddle.net/06f9huam/
What I would like to see is the red line to be cut off if it goes below 265, just like it gets cut off when it goes over 290.
You can cut the unnecessary parts of lines by using clip-path attribute, example:
chart: {
animation: false,
events: {
load: function() {
const series1 = this.series[0];
const series2 = this.series[1];
const clipRect1 = this.renderer.clipRect(
series1.yAxis.left - series1.group.translateX,
series1.yAxis.top - series1.group.translateY,
series1.yAxis.width,
series1.yAxis.height
);
const clipRect2 = this.renderer.clipRect(
series2.yAxis.left - series2.group.translateX,
series2.yAxis.top - series2.group.translateY,
series2.yAxis.width,
series2.yAxis.height
);
series1.graph.clip(clipRect1);
series2.graph.clip(clipRect2);
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/15e3g78w/
API Reference:
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#clipRect
https://api.highcharts.com/class-reference/Highcharts.SVGElement#clip
I have highchart series data like this to have multiple dot on a column:
series: [{
"marker": {
"fillColor": "#69B0E0",
"symbol": "circle"
},
"type": "line",
"data": [
6000,
5500,
]
},
{
"marker": {
"fillColor": "#333f48",
"symbol": "circle"
},
"type": "line",
"data": [
1000,
4000,
]
},
{
"marker": {
"fillColor": "#b61f47",
"symbol": "circle"
},
"type": "line",
"data": [
11000,
3000,
]
}
]
but when I hover it, the red radius color is green instead of red, but other 2 colors are fine, I wonder is this a bug on highcharts.
demo: https://jsfiddle.net/a0e9bz8k/1/
The hover color is inherited from point.color or series.color, so you need to set one of them.
series: [...,
{
"marker": {
"symbol": "circle"
},
color: "#b61f47",
...
}
]
Live demo: https://jsfiddle.net/BlackLabel/p0h6eqk3/
API Reference: https://api.highcharts.com/highcharts/series.scatter.color
We have a chart that plots multiple series at once.
There are the main y-series (line type) that will have the main data readings.
There is the option to set two different 'levels' (line types) on the y-axis as well.
There are also options to have multiple additional y-axis bars (bar types).
With the x-axis being the datetime
Here is what a typical example of a chart looks like with valid date for the given range
This is working as expected.
We have the main y-series as the average air temp (left y-axis)
Then we have two bars, one for rainfall and one for irrigation (right y-axis)
And then the two 'levels', one red and one blue.
This is all great.
However, when we go to a date range in the future, where there is no air temp data, we get the following
Note that the start date is 2 days before the date range, and the end date looks equal distance from the end of the 'levels'
Interestingly if we remove the bars we get the following
This now shows the 'levels' to span the full width of the chart
If we remove the lines and just have the bars then we get the following (which is how it should look, but with the 'levels')
There seems to be something in here that is causing the conflict when there are multiple y-series without the main y-series.
I am setting the xAxis.setExtremes to the start and end dates of the date range we are looking at, but that seems to be doing nothing.
Here is the config;
{
"chart": {
"type":"line",
"animation": {
"duration":150
},
"events":{}
},
"credits":{
"enabled":false
},
"title":{
"text":""
},
"subtitle":{
"text":""
},
"tooltip":{
"shared":true,
"crosshairs":true,
"borderWidth":0,
"followPointer":true,
"useHTML":true,
"headerFormat":"<span style=\"font-size: 10px;\">{point.key}</span><br><br>"
},
"xAxis":[
{
"id":"x-axis",
"type":"datetime",
"crosshair":{
"snap":false
},
"title":{
"text":"25th Sep 2019 - 1st Oct 2019",
"margin":15
}
}
],
"yAxis":[
{
"id":"y-axis-sensors",
"title":{
"text":"ºC"
},
"reversed":false,
"visible":true,
"endOnTick":false,
"startOnTick":false,
"alignTicks":false
},
{
"id":"y-axis-moisture",
"title":{
"text":"mm"
},
"opposite":true,
"min":0,
"endOnTick":false,
"startOnTick":false,
"alignTicks":false,
"tickWidth":0,
"gridLineWidth":0
}
],
"series":[
{
"type":"line",
"yAxis":"y-axis-sensors",
"marker":{
"enabled":false
},
"lineWidth":1,
"animation":false,
"name":"Full",
"seriesGroup":"levelSeries",
"id":"series-level-range-full",
"color":"#31B5E0",
"showInLegend":false,
"states":{
"hover":{
"enabled":false
}
},
"enableMouseTracking":false,
"zIndex":5,
"step":true,
"data":[
[1569369600000,5],
[1569974400000,5]
]
},
{
"type":"line",
"yAxis":"y-axis-sensors",
"marker":{
"enabled":false
},
"lineWidth":1,
"animation":false,
"name":"Refill",
"seriesGroup":"levelSeries",
"id":"series-level-range-refill",
"color":"#D23333",
"showInLegend":false,
"states":{
"hover":{
"enabled":false
}
},
"enableMouseTracking":false,
"zIndex":5,
"step":true,
"data":[
[1569369600000,17],
[1569974400000,17]
]
},
{
"type":"column",
"yAxis":"y-axis-moisture",
"marker":{
"enabled":false
},
"name":"Rainfall",
"seriesGroup":"rainfallSeries",
"states":{
"hover":{
"enabled":false
}
},
"id":"series-rainfall",
"pointWidth":6,
"borderWidth":0,
"color":"rgba(41, 182, 246, 0.3)",
"data":[
[1569488400000,5]
],
"zIndex":10,
"stacking":"normal",
"stack":"moisture"
},
{
"type":"column",
"yAxis":"y-axis-moisture",
"marker":{
"enabled":false
},
"states":{
"hover":{
"enabled":false
}
},
"name":"Irrigation",
"seriesGroup":"irrigationSeries",
"id":"series-irrigation",
"pointWidth":6,
"borderWidth":0,
"color":"rgba(205,220,57, 0.3)",
"data":[[1569574800000,3]],
"zIndex":10,
"stacking":"normal",
"stack":"moisture"
}
]
}
I am at a bit of a loss here as to why this is happening.
Can anyone shed some light on this?
One of the solutions can be to add additional x-axis and bind line series to it. Then it looks like your expected result. Check demo and code posted below.
Code:
Highcharts.chart('container', {
"chart": {
"type": "line",
"animation": {
"duration": 150
},
"events": {}
},
"credits": {
"enabled": false
},
"title": {
"text": ""
},
"subtitle": {
"text": ""
},
"tooltip": {
"shared": true,
"crosshairs": true,
"borderWidth": 0,
"followPointer": true,
"useHTML": true,
"headerFormat": "<span style=\"font-size: 10px;\">{point.key}</span><br><br>"
},
"xAxis": [{
"id": "x-axis1",
"type": "datetime",
"crosshair": {
"snap": false
},
"title": {
"text": "25th Sep 2019 - 1st Oct 2019",
"margin": 15
}
}, {
"id": "x-axis2",
visible: false,
"type": "datetime"
}],
"yAxis": [{
"id": "y-axis-sensors",
"title": {
"text": "ºC"
},
"reversed": false,
"visible": true,
"endOnTick": false,
"startOnTick": false,
"alignTicks": false
},
{
"id": "y-axis-moisture",
"title": {
"text": "mm"
},
"opposite": true,
"min": 0,
"endOnTick": false,
"startOnTick": false,
"alignTicks": false,
"tickWidth": 0,
"gridLineWidth": 0
}
],
"series": [
{
"type": "line",
xAxis: 'x-axis2',
"yAxis": "y-axis-sensors",
"marker": {
"enabled": false
},
"lineWidth": 1,
"animation": false,
"name": "Full",
"seriesGroup": "levelSeries",
"id": "series-level-range-full",
"color": "#31B5E0",
"showInLegend": false,
"states": {
"hover": {
"enabled": false
}
},
"enableMouseTracking": false,
"zIndex": 5,
"step": true,
"data": [
[1569369600000, 5],
[1569974400000, 5]
]
},
{
"type": "line",
xAxis: 'x-axis2',
"yAxis": "y-axis-sensors",
"marker": {
"enabled": false
},
"lineWidth": 1,
"animation": false,
"name": "Refill",
"seriesGroup": "levelSeries",
"id": "series-level-range-refill",
"color": "#D23333",
"showInLegend": false,
"states": {
"hover": {
"enabled": false
}
},
"enableMouseTracking": false,
"zIndex": 5,
"step": true,
"data": [
[1569369600000, 17],
[1569974400000, 17]
]
},
{
"type": "column",
xAxis: 'x-axis1',
"yAxis": "y-axis-moisture",
"marker": {
"enabled": false
},
"name": "Rainfall",
"seriesGroup": "rainfallSeries",
"states": {
"hover": {
"enabled": false
}
},
"id": "series-rainfall",
"pointWidth": 6,
"borderWidth": 0,
"color": "rgba(41, 182, 246, 0.3)",
"data": [
[1569488400000, 5]
],
"zIndex": 10,
"stacking": "normal",
"stack": "moisture"
},
{
"type": "column",
xAxis: 'x-axis1',
"yAxis": "y-axis-moisture",
"marker": {
"enabled": false
},
"states": {
"hover": {
"enabled": false
}
},
"name": "Irrigation",
"seriesGroup": "irrigationSeries",
"id": "series-irrigation",
"pointWidth": 6,
"borderWidth": 0,
"color": "rgba(205,220,57, 0.3)",
"data": [
[1569574800000, 3]
],
"zIndex": 10,
"stacking": "normal",
"stack": "moisture"
}
]
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container"></div>
Demo:
https://jsfiddle.net/BlackLabel/juwc8f37/
I am using odata api, now I have an attribute on an entity that is an option select like :
attribute name is : status
values are: 1, 2, 3
names: done, progress, new
the thing is when I am using postman to fetch metadata and all I get for the fields 'status' its that its type integer.
Question how do I fetchj option names and values from metadata so I get values and names in response ?
Currently I get this:
<Property Name="status" Type="Edm.Int32">
<Annotation Term="Org.OData.Core.V1.Description" String="" />
</Property>
But I want to get the value and names on response ?
This could be vastly simplified, assuming all you want are the int values, and names for a particular option set attribute of an entity:
GET [Organization URI]/api/data/v8.2/EntityDefinitions(LogicalName='contact')/Attributes(LogicalName='status')/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?$select=LogicalName&$expand=OptionSet($select=Options),GlobalOptionSet($select=Options)
The $select=LogicalName is just so it doesn't return all the other metadata for the attribute, and the $expand=OptionSet($select=Options) is for local option sets, and the GlobalOptionSet($select=Options) is for Global. If you know what type it is, you can skip it the other, but if you are putting this logic in a shared library (you are aren't you?) then adding both won't hurt:
{
"#odata.context":"http://YourOrg.com/YourInstance/api/data/v8.2/$metadata#EntityDefinitions('new_entity')/Attributes/Microsoft.Dynamics.CRM.PicklistAttributeMetadata(LogicalName,OptionSet,GlobalOptionSet,OptionSet(Options),GlobalOptionSet(Options))/$entity",
"LogicalName":"new_familyshortname",
"MetadataId":"dc11c01f-b6bd-4664-82d0-3a521841c1f5",
"OptionSet#odata.context":"http://YourOrg.com/YourInstance/api/data/v8.2/$metadata#EntityDefinitions('new_entity')/Attributes(dc11c01f-b6bd-4664-82d0-3a521841c1f5)/Microsoft.Dynamics.CRM.PicklistAttributeMetadata/OptionSet(Options)/$entity",
"OptionSet":null,
"GlobalOptionSet":{
"#odata.type":"#Microsoft.Dynamics.CRM.OptionSetMetadata",
"Options":[
{
"Value":117280000,
"Label":{
"LocalizedLabels":[
{
"Label":"English Value 1",
"LanguageCode":1033,
"IsManaged":true,
"MetadataId":"3cb6bbd5-796f-e111-8cf3-3cd92b023782",
"HasChanged":null
},
{
"Label":"French Value 1",
"LanguageCode":1036,
"IsManaged":false,
"MetadataId":"d88be67d-4a7d-e411-8890-0050569f1654",
"HasChanged":null
}
],
"UserLocalizedLabel":{
"Label":"English Value 1",
"LanguageCode":1033,
"IsManaged":true,
"MetadataId":"3cb6bbd5-796f-e111-8cf3-3cd92b023782",
"HasChanged":null
}
},
"Description":{
"LocalizedLabels":[
{
"Label":"",
"LanguageCode":1033,
"IsManaged":true,
"MetadataId":"3db6bbd5-796f-e111-8cf3-3cd92b023782",
"HasChanged":null
}
],
"UserLocalizedLabel":{
"Label":"",
"LanguageCode":1033,
"IsManaged":true,
"MetadataId":"3db6bbd5-796f-e111-8cf3-3cd92b023782",
"HasChanged":null
}
},
"Color":null,
"IsManaged":true,
"MetadataId":null,
"HasChanged":null
},
... MORE ...
],
"MetadataId":"dcbbe460-bedb-4985-9a17-2f3dbc637594"
}
}
According to this article this is a multi-step process.
Please note that all the examples use HTTP GET.
First retrieve the entity's MetaData Id (for this example we're using the entity 'account'):
https://myOrg.crm.dynamics.com/api/data/v8.2/EntityDefinitions?$select=LogicalName,MetadataId&$filter=LogicalName eq 'account'
Returns:
{
"#odata.context": "https://myOrg.crm.dynamics.com/api/data/v8.2/$metadata#EntityDefinitions(LogicalName,MetadataId)",
"value": [{
"LogicalName": "account",
"MetadataId": "70816501-edb9-4740-a16c-6a5efbc05d84"
}]
}
Then retrieve the attribute's MetaDataId (in this example we're using the option set 'customertypecode'):
https://myOrg.crm.dynamics.com/api/data/v8.2/EntityDefinitions(70816501-edb9-4740-a16c-6a5efbc05d84)?$select=LogicalName&$expand=Attributes($select=LogicalName;$filter=LogicalName eq 'customertypecode')
Returns:
{
"#odata.context": "https://myOrg.crm.dynamics.com/api/data/v8.2/$metadata#EntityDefinitions(LogicalName,Attributes(LogicalName))/$entity",
"LogicalName": "account",
"MetadataId": "70816501-edb9-4740-a16c-6a5efbc05d84",
"Attributes#odata.context": "https://myOrg.crm.dynamics.com/api/data/v8.2/$metadata#EntityDefinitions(70816501-edb9-4740-a16c-6a5efbc05d84)/Attributes(LogicalName)",
"Attributes": [{
"#odata.type": "#Microsoft.Dynamics.CRM.PicklistAttributeMetadata",
"LogicalName": "customertypecode",
"MetadataId": "4e33af09-ba43-4365-a747-c7e4f9992172"
}]
}
Then query with the entity's and attribute's MetadataIds to get the option set values:
https://myOrg.crm.dynamics.com/api/data/v8.2/EntityDefinitions(70816501-edb9-4740-a16c-6a5efbc05d84)/Attributes(4e33af09-ba43-4365-a747-c7e4f9992172)/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?$select=LogicalName&$expand=OptionSet
Returns (truncated at 2 values):
{
"#odata.context": "https://myOrg.crm.dynamics.com/api/data/v8.2/$metadata#EntityDefinitions(70816501-edb9-4740-a16c-6a5efbc05d84)/Attributes/Microsoft.Dynamics.CRM.PicklistAttributeMetadata(LogicalName,OptionSet)/$entity",
"LogicalName": "customertypecode",
"MetadataId": "4e33af09-ba43-4365-a747-c7e4f9992172",
"OptionSet#odata.context": "https://myOrg.crm.dynamics.com/api/data/v8.2/$metadata#EntityDefinitions(70816501-edb9-4740-a16c-6a5efbc05d84)/Attributes(4e33af09-ba43-4365-a747-c7e4f9992172)/Microsoft.Dynamics.CRM.PicklistAttributeMetadata/OptionSet/$entity",
"OptionSet": {
"MetadataId": "3629e642-b895-41ab-8f1d-ea5bfa30e992",
"HasChanged": null,
"IsCustomOptionSet": false,
"IsGlobal": false,
"IsManaged": true,
"Name": "account_customertypecode",
"ExternalTypeName": null,
"OptionSetType": "Picklist",
"IntroducedVersion": "5.0.0.0",
"Description": {
"LocalizedLabels": [{
"Label": "Type of the account.",
"LanguageCode": 1033,
"IsManaged": true,
"MetadataId": "73f68e38-c78d-48a5-80cb-bee895baab2b",
"HasChanged": null
}],
"UserLocalizedLabel": {
"Label": "Type of the account.",
"LanguageCode": 1033,
"IsManaged": true,
"MetadataId": "73f68e38-c78d-48a5-80cb-bee895baab2b",
"HasChanged": null
}
},
"DisplayName": {
"LocalizedLabels": [{
"Label": "Relationship Type",
"LanguageCode": 1033,
"IsManaged": true,
"MetadataId": "e5d47366-fd09-41e6-96a1-cbfdd113b932",
"HasChanged": null
}],
"UserLocalizedLabel": {
"Label": "Relationship Type",
"LanguageCode": 1033,
"IsManaged": true,
"MetadataId": "e5d47366-fd09-41e6-96a1-cbfdd113b932",
"HasChanged": null
}
},
"IsCustomizable": {
"Value": true,
"CanBeChanged": false,
"ManagedPropertyLogicalName": "iscustomizable"
},
"Options": [{
"Value": 1,
"Color": null,
"IsManaged": true,
"ExternalValue": null,
"MetadataId": null,
"HasChanged": null,
"Label": {
"LocalizedLabels": [{
"Label": "Competitor",
"LanguageCode": 1033,
"IsManaged": true,
"MetadataId": "6c54c2fa-2241-db11-898a-0007e9e17ebd",
"HasChanged": null
}],
"UserLocalizedLabel": {
"Label": "Competitor",
"LanguageCode": 1033,
"IsManaged": true,
"MetadataId": "6c54c2fa-2241-db11-898a-0007e9e17ebd",
"HasChanged": null
}
},
"Description": {
"LocalizedLabels": [],
"UserLocalizedLabel": null
}
},
{
"Value": 2,
"Color": null,
"IsManaged": true,
"ExternalValue": null,
"MetadataId": null,
"HasChanged": null,
"Label": {
"LocalizedLabels": [{
"Label": "Consultant",
"LanguageCode": 1033,
"IsManaged": true,
"MetadataId": "6e54c2fa-2241-db11-898a-0007e9e17ebd",
"HasChanged": null
}],
"UserLocalizedLabel": {
"Label": "Consultant",
"LanguageCode": 1033,
"IsManaged": true,
"MetadataId": "6e54c2fa-2241-db11-898a-0007e9e17ebd",
"HasChanged": null
}
},
"Description": {
"LocalizedLabels": [],
"UserLocalizedLabel": null
}
}
}
}
I'm trying to set a secondary axis with a min/max value, and the primary axis often overwrites the max on the secondary axis.
I know that I could use alignTicks:false, but I don't like the way that makes the ticks look. I also know that I can hide the ticks for one of the axes, but again, I don't like they it looks.
I would like to either force the right side to use min/max and figure out the proper tick intervals, or I'd like to force the left side to have a specific number of ticks.
I need some ideas, here's a jsfiddle with my code and some mock data.
http://jsfiddle.net/2s6kK/
$(function () {
$('#container').highcharts({
"title": {
"text": ""
},
"subtitle": {
"text": ""
},
"xAxis": {
"type": "datetime",
"dateTimeLabelFormats": {
"day": "%b %e"
}
},
"yAxis": [{
"min": 0,
"startOnTick": false,
"labels": {
"style": {
"color": "#4074C3"
}
},
"title": {
"text": "Revenue",
"style": {
"color": "#4074C3"
},
"margin": 5
},
"index": 0
}, {
"allowDecimals": false,
"min": 0,
"max": 100,
"maxPadding": 0.2,
"startOnTick": false,
"labels": {
"style": {
"color": "#8DAD36"
}
},
"title": {
"text": "Win Rate",
"style": {
"color": "#8DAD36"
},
"margin": 2
},
"opposite": true,
"index": 1,
// "alignTicks": false
}],
"legend": {
"enabled": true,
"align": "center",
"verticalAlign": "top",
"x": 0,
"y": -5,
"borderWidth": 0
},
"series": [{
"name": "Revenue",
"type": "line",
"yAxis": 0,
"data": [5.4,27,27,27,58,0, 0, 0, 0
],"pointStart":1377993600000,"pointInterval":86400000
}, {
"name": "Win Rate",
"type": "line",
"color": "#8DAD36",
"yAxis": 1,
"data": [60,48,48,48,48,60, 0, 0, 0, 0
],"pointStart":1377993600000,"pointInterval":86400000
}]
});
});
Thanks,
Josh
You could try setting your tickInterval to 10 in your y-axis definition:
"tickInterval": 10
http://jsfiddle.net/2s6kK/1/