I am currently working with Highcharts in combination with the pattern fill module. When I set a pattern for a series in the chart, the pattern is shown but it has a transparent background. I need to set an additional background because the pattern is overlapping with another series which I don't want to see behind it. You can check this fiddle. So basically I don't want to see those three columns on the left behind the pattern. Any ideas how I can do that? I haven't seen any options to set an additional background, but maybe you know some trick. This is the code I am using for the pattern:
"color": {
"pattern": {
"path": {
"d": "M 0 0 L 10 10 M 9 -1 L 11 1 M -1 9 L 1 11"
},
"width": 10,
"height": 10,
"opacity": 1,
"color": "rgb(84,198,232)"
}
}
You need to set fill attribute as a path property:
"color": {
"pattern": {
"path": {
"d": "M 0 0 L 10 10 M 9 -1 L 11 1 M -1 9 L 1 11",
fill: 'red'
},
"width": 10,
"height": 10,
"opacity": 1,
"color": 'rgb(84,198,232)'
}
}
Live demo: https://jsfiddle.net/BlackLabel/m9rxwej5/
I guess there's been an update. backgroundColor should be set at pattern's root level:
"color": {
"pattern": {
"backgroundColor": 'red',
"path": {
"d": "M 0 0 L 10 10 M 9 -1 L 11 1 M -1 9 L 1 11",
},
"width": 10,
"height": 10,
"opacity": 1,
"color": 'rgb(84,198,232)',
}
}
https://jsfiddle.net/vL4fqhao/
Related
we are trying to create 3 X header lines, one containing the years, other the quarters and the last one containing months... something similar to this:
As you can see in the image above, we have 2 lines, one with years, the other one is quarters (3 months), we would like to add an additional line below each quarter with the months, our code looks like:
NOTE: As 3 months (quarter) is not something that has its label automatically, we created a label using the formatter.
Now when we try to add a third row like this:
What we get is something unexpected... years work right, while quarters are now extended like years, and the list of months is correct as follow:
The following image should give you a better idea of what we would like to achieve:
Thank you for any help you may bring. My code link is below.
Note this line in header it's called the x-axis, is an array of configuration objects. You can use xAxis.tickInterval to set the tick interval in axis units for each object.
In dateTimeLabelFormats, you can change the unit name to the required one.
xAxis: [{
tickInterval: 1000 * 60 * 60 * 24, // Days
labels: {
format: '{value:%e. %b.}',
style: {
fontSize: '8px'
}
},
units: [
[
'day',
[2]
]
]
}, {
tickInterval: 1000 * 60 * 60 * 24 * 30, // Month
/* labels: {
format: '{value:%b}',
}, */
min: Date.UTC(2014, 3, 17),
max: Date.UTC(2015, 11, 0),
currentDateIndicator: true,
units: [
[
'month',
[3]
]
],
dateTimeLabelFormats: {
month: {
list: ['Quater']
}
}
}, {
tickInterval: 1000 * 60 * 60 * 24 * 365, // Year
labels: {
format: '{value:%Y}',
style: {
fontSize: '15px'
}
},
linkedTo: 1
}],
Live demo: https://jsfiddle.net/BlackLabel/w3nb4oqj/
I have a project I'm working on that involves rendering 3D models in WebGL, GitHub here. In pulling together several different resources, I've found two different formats for the model data: one with JSON entries like so:
var houseIFS =
{
"vertices": [
[ 2, -1, 2 ],
[ 2, -1, -2 ],
[ 2, 1, -2 ],
[ 2, 1, 2 ],
[ 1.5, 1.5, 0 ],
[ -1.5, 1.5, 0 ],
[ -2, -1, 2 ],
[ -2, 1, 2 ],
[ -2, 1, -2 ],
[ -2, -1, -2 ]
],
"faces": [
[ 0, 1, 2, 3 ],
[ 3, 2, 4 ],
[ 7, 3, 4, 5 ],
[ 2, 8, 5, 4 ],
[ 5, 8, 7 ],
[ 0, 3, 7, 6 ],
[ 0, 6, 9, 1 ],
[ 2, 1, 9, 8 ],
[ 6, 7, 8, 9 ]
],
"normals": [
[ 1, 0, 0 ],
[ 0.7071, 0.7071, 0 ],
[ 0, 0.9701, 0.2425 ],
[ 0, 0.9701, -0.2425 ],
[ -0.7071, 0.7071, 0 ],
[ 0, 0, 1 ],
[ 0, -1, 0 ],
[ 0, 0, -1 ],
[ -1, 0, 0 ]
],
"faceColors": [
[ 1, .8, .8 ],
[ .7, .7, 1 ],
[ 0, 0, 1 ],
[ 0, 0, .7 ],
[ .7, .7, 1 ],
[ 1, 0, 0 ],
[ .4, .4, .4 ],
[ 1, 0, 0 ],
[ 1, .8, .8 ],
]
};
and another with more primitive return types:
/** The return value of each function is an object, model, with properties:
*
* model.vertexPositions -- the vertex coordinates;
* model.vertexNormals -- the normal vectors;
* model.vertexTextureCoords -- the texture coordinates;
* model.indices -- the face indices.
*
* The first three properties are of type Float32Array, while
* model.indices is of type Uint16Array.
*/
I tried to create a method to convert the data from the "modern" version to the "primitive":
function convertPoly(model) {
return {
vertexPositions: new Float32Array(model.vertices),
vertexNormals: new Float32Array(model.normals),
vertexTextureCoords: new Float32Array(model.faces),
indices: new Uint16Array(model.faces)
}
}
but I don't think this is correct, and I don't see anything rendered after trying to render it. How can I compute indices from the vertices or faces? I guess I don't really understand what the indices really represent or how they work (is it triangle vertices of the faces?).
I'm exploring Highcharts and it seems like a very comprehensive package! I have a question regarding legend colors.
I notice that when I use a linear color gradient for a line, the color next to the legend (I believe it's called the symbolColor) may or may not show up, depending on the format I use:
1) symbolColor works fine: linearGradient: [ 00, 00, 00, 350 ]
2) symbolColor doesn't show up: linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }
I'd rather use the second format; it's easier and the first is not responsive.
Should the symbolColor always show up and this is an obscure issue/bug? Or am I doing something wrong? I also just noticed that if the marker is enabled in the plotOptions for series, symbolColor works fine with the second format. But I have many data points and don't want to use markers.
The fiddle graph has two lines -- purple and green -- and while the purple symbolColor using method (1) looks fine, you'll notice that the green symbolColor using method (2) doesn't show up.
https://jsfiddle.net/jwinkle/s6d9ah17/6/
In your HTML file, add:
<script src="https://code.highcharts.com/maps/modules/map.src.js"></script>
Above your chart code add:
Highcharts.addEvent(Highcharts.Chart.prototype, 'render', function() {
this.series.forEach(function(series) {
if (series.legendLine) {
var pathDef = series.legendLine.attr('d').split(' ');
pathDef[5] = parseFloat(pathDef[2]) + 0.0001;
series.legendLine.attr({
d: pathDef
});
}
})
});
The fix is in adding a smidge to your path definition (you can test this by going into the svg path element in dev tools and changing the last number in the 'd' attribute to a float:
<path fill="none" d="M 0 11 L 16 11" ... ></path>
becomes:
<path fill="none" d="M 0 11 L 16 11.1" ... ></path>
The function above goes through each series and massages the line data adding the fractional value in the right place. Total hack. However why the line does not appear if it does have this fractional value, I don't know. I would also test this across browsers to see that it works consistently as it may not (I tested in Chrome).
Here is a somewhat related issue where I cribbed the fix: https://www.highcharts.com/forum/viewtopic.php?t=38588
(Most of it is addressing a completely different problem, but the legend lines did show up so I investigated why).
If you don't want to use the extra library, you could probably write a native js function to find the legend lines and manipulate them in the same way.
Here, you can find a nice explanation of the problem.
The difference results from the fact that Highcharts uses 'userSpaceOnUse' as a default value for gradientUnits if a gradient is defined as an array.
Highcharts source code:
// Keep < 2.2 kompatibility
if (isArray(gradAttr)) {
(colorOptions as any)[gradName] = gradAttr = {
x1: gradAttr[0] as number,
y1: gradAttr[1] as number,
x2: gradAttr[2] as number,
y2: gradAttr[3] as number,
gradientUnits: 'userSpaceOnUse'
};
}
As a possible solution, you can set gradientUnits also for linearGradient defined as an object:
color: {
linearGradient: {
...,
gradientUnits: 'userSpaceOnUse'
},
...
}
Live demo: http://jsfiddle.net/BlackLabel/yz6sagxj/
Or modify the paths very slightly so that they are not perfectly horizontal
chart: {
events: {
render: function() {
this.series.forEach(function(series) {
if (series.legendLine) {
var pathDef = series.legendLine.attr('d').split(' ');
pathDef[5] = parseFloat(pathDef[2]) + 0.0001;
series.legendLine.attr({
d: pathDef
});
}
})
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/L1kzg0cn/
Github thread: https://github.com/highcharts/highcharts/issues/1936
In addition to #Katharine's solution, here's another I discovered.
If I enable the marker in one series (setting the radius to 0) and then put the data in a second series which is linked to the previous, it works. (If I do it all in one series, there is again no legend color.)
series: [{
name: 'purple', lineWidth: 3, color: {
linearGradient: [ 00, 00, 00, 350 ],
//linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1, },
stops: [
[0, 'purple'], // start
[1, 'black'] // end
],
},
data: [ 100, 95, 80, 60, 35, 50, 20, 10, 3, 2, 30, 40, ],
},{
marker: {
enabled: true,
radius: 0,
},
name: 'green', color: 'green', lineWidth: 3,
},{
linkedTo: ':previous',
lineWidth: 3, color: {
//linearGradient: [ 00, 00, 00, 350 ],
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1, },
stops: [
[0, 'green'], // start
[1, 'black'] // end
],
},
data: [ 100, 100, 95, 80, 60, 35, 50, 20, 10, 3, 2, 30, ],
}],
Here's the "fixed" fiddle: https://jsfiddle.net/jwinkle/wztq78n1/6/
I reported the original issue as a possible bug to Highcharts, and they confirmed that it's an SVG rendering problem out of their control.
I have this chart
<script src="http://code.highcharts.com/highcharts.js"></script>
<div id="container" style="height: 300px"></div>
var seriesOptions = [],
seriesCounter = 0,
names = ['MSFT', 'AAPL', 'GOOG'];
/**
* Create the chart when all data is loaded
* #returns {undefined}
*/
function createChart() {
Highcharts.stockChart('container', {
plotOptions: {
series: {
gapSize: 5 * 24 * 3600 * 1000,
gapUnit: 'relative'
}
},
rangeSelector: {
selected: 5
},
yAxis: {
labels: {
formatter: function () {
return (this.value > 0 ? ' + ' : '') + this.value + '%';
}
},
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
},
plotOptions: {
series: {
compare: 'percent',
showInNavigator: true
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
valueDecimals: 2,
split: true
},
series: seriesOptions
});
}
$.each(names, function (i, name) {
$.getJSON('https://www.highcharts.com/samples/data/' + name.toLowerCase() + '-c.json', function (data) {
if (i==0) {
var first = [], last = [];
first.push.apply(first, data.slice(0,1)[0]);
last.push.apply(first, data.slice(0,1)[0]);
first[0] = first[0] - 1900 * 24 * 3600 * 1000;
last[0] = last[0] - 130 * 24 * 3600 * 1000;
data = [];
data.push(first);
data.push(last);
}
seriesOptions[i] = {
name: name,
data: data
};
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter += 1;
if (seriesCounter === names.length) {
createChart();
}
});
});
and as you can see there are three stocks shown. If you hover the chart with the mouse and go to the beginning you'll notice MSFT stock which has only 2 points and that's intentional. After MSFT there should be about 6 year gap, however on the chart it's shown in a few pixels.
How can I configure stockChart to show real gaps? In other words, I want to see the gap of 6 years so from 2005 till 2011 there will be empty space proportional to the whole chart?
The discussion in the comment section of the first answer reveals that OP wants to hide no-data periods only in some cases.
The solution here might be to set ordinal to false (as #ewolden) suggested and use breaks instead:
xAxis: {
breaks: [{
breakSize: 24 * 3600 * 1000,
from: Date.UTC(2017, 0, 6),
to: Date.UTC(2017, 0, 9)
}],
ordinal: false
},
series: [{
data: [
[Date.UTC(2017, 0, 2), 6],
[Date.UTC(2017, 0, 3), 7],
[Date.UTC(2017, 0, 4), 3],
[Date.UTC(2017, 0, 5), 4],
[Date.UTC(2017, 0, 6), 1],
[Date.UTC(2017, 0, 9), 8],
[Date.UTC(2017, 0, 10), 9],
[Date.UTC(2017, 6, 1), 4],
[Date.UTC(2017, 6, 2), 5]
]
Example: http://jsfiddle.net/BlackLabel/ocg0dujg/
In the above demo I was able to hide the weekend (7 and 8 Jan) and maintain the space between January and July.
API reference: https://api.highcharts.com/highstock/xAxis.breaks
What you are after is ordinal.
In an ordinal axis, the points are equally spaced in the chart regardless of the actual time or x distance between them. This means that missing data for nights or weekends will not take up space in the chart.
Setting ordinal to false, like this, will give you the gap you are after:
xAxis: {
type: 'datetime',
ordinal: false,
},
There are some other issues with your code, if you look in console, you are getting error 15 which states that highcharts requires data to be sorted. You get this because of how you add the series data to your MSFT series. You add both the x and the y to a single 1D array, which means highcharts tries to plot both your x and y values on the x axis.
I did a workaround that gives it the right format in this fiddle: http://jsfiddle.net/2cps91ka/91/
defs: {
patterns: [{
'id': 'budget-pattern',
'path': {
d: 'M 0 0 L 10 10 M 9 -1 L 11 1 M -1 9 L 1 11',
stroke: 'rgba(255, 0, 0, 0.1)',
strokeWidth: 3
}
}]
},
Here the stroke is hardcoded with 'rgba(255, 0, 0, 0.1)' but I want to have different stroke for every column in highchart.
thank you
You can set series's colorByPoint to true.
plotOptions: {
series: {
colorByPoint: true
}
},
Reference: http://api.highcharts.com/highcharts/plotOptions.column.colorByPoint
OR Refer Highcharts Fiddle: http://jsfiddle.net/gh/get/jquery/1.7.2/highslide-software/highcharts.com/tree/master/samples/highcharts/plotoptions/column-colorbypoint-true/