series labels are one over another(overlapping) - highcharts

the labels are one on another(overlapping)
is there an option to arrange them correctly ? (my real data is dynamic, and number of series is also dynamic)
example:
http://jsfiddle.net/6kBQY/
$(function () {
$('#container').highcharts({
chart: {
},
xAxis: {
categories: ['aa', 'bb', 'cc', 'dd', 'ee', 'ff']
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
borderRadius: 5,
backgroundColor: 'rgba(252, 255, 197, 0.7)',
borderWidth: 1,
borderColor: '#AAA',
y: -6
}
}
},
series: [{
data: [10, 20, 30, 25, 15, 5]
},{
data: [11, 22, 33, 20, 10, 0]
}]
});
});

You can use small workaround like here
function StaggerDataLabels(series) {
sc = series.length;
if (sc < 2) return;
for (s = 1; s < sc; s++) {
var s1 = series[s - 1].points,
s2 = series[s].points,
l = s1.length,
diff, h;
for (i = 0; i < l; i++) {
if (s1[i].dataLabel && s2[i].dataLabel) {
diff = s1[i].dataLabel.y - s2[i].dataLabel.y;
h = s1[i].dataLabel.height + 2;
if (isLabelOnLabel(s1[i].dataLabel, s2[i].dataLabel)) {
if (diff < 0) s1[i].dataLabel.translate(s1[i].dataLabel.translateX, s1[i].dataLabel.translateY - (h + diff));
else s2[i].dataLabel.translate(s2[i].dataLabel.translateX, s2[i].dataLabel.translateY - (h - diff));
}
}
}
}
}
//compares two datalabels and returns true if they overlap
function isLabelOnLabel(a, b) {
var al = a.x - (a.width / 2);
var ar = a.x + (a.width / 2);
var bl = b.x - (b.width / 2);
var br = b.x + (b.width / 2);
var at = a.y;
var ab = a.y + a.height;
var bt = b.y;
var bb = b.y + b.height;
if (bl > ar || br < al) {
return false;
} //overlap not possible
if (bt > ab || bb < at) {
return false;
} //overlap not possible
if (bl > al && bl < ar) {
return true;
}
if (br > al && br < ar) {
return true;
}
if (bt > at && bt < ab) {
return true;
}
if (bb > at && bb < ab) {
return true;
}
return false;
}
http://jsfiddle.net/menXU/7/

Related

HIGHCHARTS GANTT / X labels not rendering, not rotating, not overlapping

I have a chart with 3 X axes, the first show the year, the next line shows the Quarter (3 months) and the third by month, the expected behavior is similar to the following:
Now I do understand that because of the space, some of them disappear, but I tried to use allowOverlap and nothing happnes, rotate 90 or -90 and also nothing happens, and the worst of all is... when I zoom it shows correctly, but if I zoom out then zoom in other part of the chart, most of the months don't show, not because of lack of space, not sure why?, please take a look:
and when zooming out... (at the beginning it was showing just some months because of space, how did this get the space now?)
and when zooming back in...
please take a look at my code below:
xAxis: [
{
tickInterval: 1000 * 60 * 60 * 24 * 30,
labels: {
allowOverlap: true,
format: '{value:%b}',
style: {
fontSize: '8px'
},
rotate: 90,
},
units: [
[
'month',
[1]
]
]
},
{
currentDateIndicator: {
width: 1,
dashStyle: 'dash',
color: 'red',
label: undefined,
},
tickInterval: 1000 * 60 * 60 * 24 * 30,
units: [[
'month',
[3]
],],
labels: {
align: "center",
allowOverlap: true,
formatter: function AxisLabelsFormatterCallbackFunction() {
var providedLocalDate = new Date(this.value);
var realDate = new Date(providedLocalDate.getTime() + (providedLocalDate.getTimezoneOffset() * 60 * 1000));
var month = realDate.getMonth();
var QuarterNumber;
var MonthInits = [];
if (month >= 0 && month <= 2) {
QuarterNumber = 1;
MonthInits[0] = 'J';
MonthInits[1] = 'F';
MonthInits[2] = 'M';
}
if (month >= 3 && month <= 5) {
QuarterNumber = 2;
MonthInits[0] = 'A';
MonthInits[1] = 'M';
MonthInits[2] = 'J';
}
if (month >= 6 && month <= 8) {
QuarterNumber = 3;
MonthInits[0] = 'J';
MonthInits[1] = 'A';
MonthInits[2] = 'S';
}
if (month >= 9 && month <= 11) {
QuarterNumber = 4;
MonthInits[0] = 'O';
MonthInits[1] = 'N';
MonthInits[2] = 'D';
}
return `<div style="font-size: x-small; font-family:arial;font-weight:bold; color:${((QuarterNumber == 1 | QuarterNumber == 3) ? "#B86B00;" : "#0068B5;")};">QTR ${QuarterNumber}</div>`;
},
},
},
{
tickInterval: 1000 * 60 * 60 * 24 * 365, // Year
labels: {
format: '{value:%Y}',
style: {
fontSize: '15px'
}
},
},
],

Highcharts.js question: is it possible to not draw line beyond MACD indicator histogram?

I develop a project using Highstock.js library. I have a requirement to not draw lines beyond MACD indicator histogram (https://prnt.sc/lxjoit). In Highstock.js documentation related to MACD indicator there is macdLine API: https://api.highcharts.com/highstock/series.macd.macdLine , signalLine API: https://api.highcharts.com/highstock/series.macd.signalLine.zones. Those API allows only to set colors for MACD indicator parts divided by y axis. So it doesn't fit. From documentation it isn't clear if we can to not draw MACD indicator lines beyond the histogram. Do you know if it is possible to implement that and how? Please advise.
Here is live demo in JSFiddle showing chart with MACD indicator: http://jsfiddle.net/ogorobets/x3tcpq72/14/
var ohlc = JSON.parse(ohlcStringified),
volume = JSON.parse(volumeStringified);
var wvapSerieData = [];
var lastDayDate = new Date("December 6, 2018 00:00:00");
var lastDayDateTs = lastDayDate.getTime();
Highcharts.stockChart('container', {
chart: {
borderWidth: 1
},
title: {
text: 'Volume Weighted Average Price (VWAP)'
},
legend: {
enabled: true
},
yAxis: [{
height: '30%'
}, {
top: '30%',
height: '35%',
offset: 0
}, {
top: '65%',
height: '35%',
offset: 0
}],
series: [{
type: 'candlestick',
id: 'candlestick',
name: 'AAPL',
data: ohlc,
tooltip: {
valueDecimals: 2
}
}, {
type: 'column',
id: 'volume',
name: 'Volume',
data: volume,
yAxis: 1
},
{
type: 'macd',
color: '#f05f5f',
linkedTo: 'candlestick',
showInLegend: true,
enableMouseTracking: true,
dataGrouping: {
enabled: false,
},
zones:[
{
value: 0,
color: '#f05f5f',
},
{
color: '#31c26d'
}
],
yAxis: 2
}]
});
Unfortunately, MACD indicator was not designed to not plot MACD indicator lines beyond the histogram.
However, you can override the method that calculates MACD values and remove first values that are beyond the histogram. Check the code and demo I posted you below.
Lines added to H.seriesTypes.macd.prototype.getValues method:
// params.signalPeriod - 1 - amount of points beyond the histroram
MACD.splice(0, params.signalPeriod - 1);
xMACD.splice(0, params.signalPeriod - 1);
yMACD.splice(0, params.signalPeriod - 1);
Whole wrapper code:
(function(H) {
H.seriesTypes.macd.prototype.getValues = function(series, params) {
var j = 0,
EMA = H.seriesTypes.ema,
merge = H.merge,
defined = H.defined,
correctFloat = H.correctFloat,
MACD = [],
xMACD = [],
yMACD = [],
signalLine = [],
shortEMA,
longEMA,
i;
if (series.xData.length < params.longPeriod + params.signalPeriod) {
return false;
}
// Calculating the short and long EMA used when calculating the MACD
shortEMA = EMA.prototype.getValues(series, {
period: params.shortPeriod
});
longEMA = EMA.prototype.getValues(series, {
period: params.longPeriod
});
shortEMA = shortEMA.values;
longEMA = longEMA.values;
// Subtract each Y value from the EMA's and create the new dataset
// (MACD)
for (i = 1; i <= shortEMA.length; i++) {
if (
defined(longEMA[i - 1]) &&
defined(longEMA[i - 1][1]) &&
defined(shortEMA[i + params.shortPeriod + 1]) &&
defined(shortEMA[i + params.shortPeriod + 1][0])
) {
MACD.push([
shortEMA[i + params.shortPeriod + 1][0],
0,
null,
shortEMA[i + params.shortPeriod + 1][1] -
longEMA[i - 1][1]
]);
}
}
// Set the Y and X data of the MACD. This is used in calculating the
// signal line.
for (i = 0; i < MACD.length; i++) {
xMACD.push(MACD[i][0]);
yMACD.push([0, null, MACD[i][3]]);
}
// Setting the signalline (Signal Line: X-day EMA of MACD line).
signalLine = EMA.prototype.getValues({
xData: xMACD,
yData: yMACD
}, {
period: params.signalPeriod,
index: 2
});
signalLine = signalLine.values;
// Setting the MACD Histogram. In comparison to the loop with pure
// MACD this loop uses MACD x value not xData.
for (i = 0; i < MACD.length; i++) {
if (MACD[i][0] >= signalLine[0][0]) { // detect the first point
MACD[i][2] = signalLine[j][1];
yMACD[i] = [0, signalLine[j][1], MACD[i][3]];
if (MACD[i][3] === null) {
MACD[i][1] = 0;
yMACD[i][0] = 0;
} else {
MACD[i][1] = correctFloat(MACD[i][3] -
signalLine[j][1]);
yMACD[i][0] = correctFloat(MACD[i][3] -
signalLine[j][1]);
}
j++;
}
}
MACD.splice(0, params.signalPeriod - 1);
xMACD.splice(0, params.signalPeriod - 1);
yMACD.splice(0, params.signalPeriod - 1);
return {
values: MACD,
xData: xMACD,
yData: yMACD
};
}
})(Highcharts);
Demo:
http://jsfiddle.net/1f2m0yz4/
Docs:
https://www.highcharts.com/docs/extending-highcharts/extending-highcharts

Stacked, grouped column chart with variable width of x points

I'm trying to dynamically set the width of each x point based on the number of non-zero stacks with that x value.
Example:
What I have:
What I want:
I want to get rid of the empty spaces by lowering the width of each date. (Sep 7 should have width 2, Sep 8 and Sep 9 should have width 1, instead of all 3 dates having width 3)
Here's a more extreme example, lots of wasted space:
I've looked into variwide charts but I can't seem to find an example of a variwide chart with both stacking and grouping.
The closest question I was able to find on stackoverflow is Display Different Number of Groups in Highcharts Stacked Column Graph but that answer doesn't change the width of the points, it just centers the bars.
JSFiddle: http://jsfiddle.net/t3z76o4b/3/
$(function() {
$('#container').highcharts({
chart: {
type: 'column',
},
legend: {
enabled: false
},
title: {
text: 'Fruits by day'
},
xAxis: {
type: 'category',
labels: {
rotation: -45,
formatter: function() {
var placeholder = Number(this.value);
if (!!placeholder) {
return ""
}
//var obj = data[this.value];
if (this.axis.series[0].levelNumber == 1 && !this.isFirst) {
return '';
} else {
return this.value;
}
}
},
crosshair: true,
},
plotOptions: {
series: {
stacking: 'normal'
}
},
series: [{
name: "Apples",
stack: "Apples",
date: "7 Sep 2018",
data: [{
color: "rgba(51,193,59,1)",
name: "7 Sep 2018",
y: 1
},
{
color: "rgba(51,193,50,0.4)",
name: "7 Sep 2018",
y: 2
}],
},
{
name: "Blueberries",
stack: "Blueberries",
date: "7 Sep 2018",
data: [{
color: "rgba(51,50,250,1)",
name: "7 Sep 2018",
y: 3
},
{
color: "rgba(51,50,250,0.4)",
name: "7 Sep 2018",
y: 1
}],
},
{
name: "Oranges",
stack: "Oranges",
date: "8 Sep 2018",
data: [{
color: "rgba(250,193,10,0.5)",
name: "8 Sep 2018",
y: 1
}, ],
},
{
name: "Blueberries",
stack: "Blueberries",
date: "9 Sep 2018",
data: [{
color: "rgba(51,50,250,1)",
name: "9 Sep 2018",
y: 2
}],
},
]
});
});
In the above JSFiddle, each series element represents a certain fruit on a certain day:
series[ 0] = Apples on Sep 7 2018
series[ 1] = Blueberries on Sep 7 2018
series[ 2] = Oranges on Sep 8 2018
series[ 3] = Blueberries on Sep
9 2018
Thanks in advance!
Unfortunately, Highcharts calculate groups space as xAxis width divided by categories length. So this space will be always equal among categories. The chart as you showed above requires a lot of changes in the core Highcharts functions and it is tricky to achieve.
Only centring columns in the group can be done with a bit of custom code:
var stacks = [
'section 1',
'section 2',
'section 3',
'section 4',
'section 5',
'section 6',
'section 7'
];
var categoriesStacksColl = [];
var seriesStackColl = {};
function calculateColumnTranslate(params) {
var m = params.stackLen / 2 + 0.5, // middle bar + offset to calc
barIndex = params.stackIndex,
a = Math.abs(barIndex - m), // bar offset from the middle point
barW = params.barW,
p = params.padding,
posX,
translateX;
if (barIndex === m) {
posX = -barW / 2;
} else if (barIndex > m) {
posX = a * barW + a * p - barW / 2;
} else {
posX = -a * barW - a * p - barW / 2;
}
translateX = posX - params.offset;
return translateX;
}
// Inside Highcharts options
chart: {
type: 'column',
events: {
load: function() {
var chart = this,
series = chart.series,
categoriesLen = chart.xAxis[0].tickPositions.length,
changeWidthFlag = false,
seriesPoints,
nextSeriesPoints,
stack,
length,
arrIndex,
i,
j;
categoriesStacksColl = [];
// Init stacks per categories array
for (j = 0; j < categoriesLen; j++) {
categoriesStacksColl.push(stacks.slice());
}
series.forEach(function(singleSeries) {
stack = singleSeries.options.stack;
if (!seriesStackColl[stack]) {
seriesStackColl[stack] = [];
}
seriesStackColl[stack].push(singleSeries);
});
stacks.forEach(function(initStack) {
seriesPoints = seriesStackColl[initStack][0].points;
length = seriesStackColl[initStack].length;
seriesPoints.forEach(function(point, index) {
if (!point.y && length === 1) {
// increase column width
changeWidthFlag = true;
} else if (!point.y && length > 1) {
changeWidthFlag = true;
for (i = 1; i < length; i++) {
nextSeriesPoints = seriesStackColl[initStack][i].points;
if (nextSeriesPoints[index].y) {
changeWidthFlag = false;
}
}
}
// when all points in category stack are null
if (changeWidthFlag) {
arrIndex = categoriesStacksColl[index].indexOf(initStack);
categoriesStacksColl[index].splice(arrIndex, 1);
changeWidthFlag = false;
}
});
});
},
render: function() {
var chart = this,
series = chart.series[0],
columnMetrics = series.columnMetrics,
barW = columnMetrics.width,
barOffsets = {},
offsets = [],
columnsToTranslate = [],
offsetMin = 0,
offsetMax = 0,
columnsGroupLen = stacks.length,
offset,
columnsGroupWidth,
padding,
point,
pointOffset,
stackIndex,
stackLen,
pointOffsetTemp,
translateBarX;
stacks.forEach(function(stack) {
if (seriesStackColl[stack][0].visible) {
offset = seriesStackColl[stack][0].columnMetrics.offset;
offsetMax = offsetMax < offset ? offset : offsetMax;
offsetMin = offsetMin > offset ? offset : offsetMin;
barOffsets[stack] = offset;
offsets.push(offset);
}
});
columnsGroupWidth = Math.abs(offsetMin) + Math.abs(offsetMax) + barW;
padding = (columnsGroupWidth - columnsGroupLen * barW) / (columnsGroupLen - 1);
categoriesStacksColl.forEach(function(cat, index) {
if (cat.length < stacks.length) {
columnsToTranslate.push({
index: index,
stack: cat
});
}
});
columnsToTranslate.forEach(function(elem) {
stackIndex = 0;
pointOffsetTemp = 0;
chart.series.forEach(function(singleSeries) {
point = singleSeries.points[elem.index];
if (point.y && singleSeries.visible) {
pointOffset = point.series.columnMetrics.offset;
stackLen = elem.stack.length;
if (pointOffsetTemp !== pointOffset) {
pointOffsetTemp = pointOffset;
stackIndex++;
}
translateBarX = calculateColumnTranslate({
padding: padding,
barW: barW,
offset: pointOffset,
stackIndex: stackIndex,
stackLen: stackLen
});
point.graphic.translate(translateBarX);
}
});
});
}
}
}
Demo:
https://jsfiddle.net/wchmiel/9eb74hys/2/

Fixed number of rows per page using pdfmake.js

Defined an own table layouts using pdfmake.js. On print I want per page to contain 7 rows(fixed).I have tried adjusting the height and width of the table cell to contain 7 rows but however if the data in table cell increases the page accumulates with less/more no.of rows.
//layout of the table:
var tablelist={
style: 'tableExample',
table: {
dontBreakRows: true,
widths: [ 20,55,55,55,55,55,55,55,55,55,55,55,55],
headerRows: 1,
body: body
},
layout: {
hLineWidth: function (i, node) {
return (i === 0 || i === node.table.body.length) ? 1 : 1;
},
vLineWidth: function (i, node) {
return (i === 0 || i === node.table.widths.length) ? 1: 1;
},
hLineColor: function (i, node) {
return (i === 0 || i === node.table.body.length) ? 'gray' : 'gray';
},
vLineColor: function (i, node) {
return (i === 0 || i === node.table.widths.length) ? 'gray' : 'gray';
},
},
}
return tablelist;
}
//pushing the table header and other data to the table body
$scope.makePrintTable = function(){
var headers = {
col_1:{ text: 'Day', style: 'tableHeader',rowSpan: 1, alignment: 'center',margin: [0, 8, 0, 0] },
col_2:{ text: 'Date', style: 'tableHeader',rowSpan: 1, alignment: 'center',margin: [0, 8, 0, 0] },
col_3:{ text: '0600-0800', style: 'tableHeader',rowSpan: 1, alignment: 'center',margin: [0, 8, 0, 0] },
.
.
.//Similarly till col_13
col_13:{ text: '1700-1800', style: 'tableHeader',rowSpan: 1, alignment: 'center' ,margin: [0, 8, 0, 0]},
}
body = [];
var row = new Array();
for (var key in headers) {
row.push( headers[key] );
}
body.push(row);
for ( var j=0 ; j< $scope.table.length; j++){
var tableEach={ };
tableEach= $scope.table[j];
/*This for Genarating Object variables*/
for (var i = 1; i < 3; i++) {
window["obj"+i] = new Object();
}
var row = new Array();
var slNoValue = tableEach.slNo;
/*This is for slNo */
obj1["text"] = slNoValue;
obj1["style"]= "cellswidth";
row.push(obj1);
/*This is for Date */
var dateValue = new Date(tableEach.date);
obj2["text"]= dateValue.getDate() + '-' + basicFormats.getMonthName(dateValue.getMonth() )+ '-' + dateValue.getFullYear()+','+ basicFormats.getDayName(dateValue.getDay());
obj2["style"]= "cellswidth";
row.push(obj2);
/*This is for remaining columns (i ranges from 6 to 17 (time in 24hrs clock format) ) */
for(var i=6 ; i<=17 ; i++){
var obj={};
var hourValue = "hour_"+i+"_"+(i+1)+"_value";
var hourValueColor = "hour_"+i+"_"+(i+1)+"_"+"color_value";
hourValue = ( tableEach["hour_"+i] == undefined ? '':(tableEach["hour_"+i]));
hourValueColor =(tableEach["hour_"+i+"_colour"] == undefined ? '#ffffff':(tableEach["hour_"+i+"_colour"]));
obj["text"] = hourValue;
obj["fillColor"] = hourValueColor;
obj["style"] = "cellswidth";
row.push(obj);
console.log(obj);
}
// if( j!= 0 && j % 7 == 0){
// pageBreak : 'before'
// }
}
body.push(row);
}
};
//CSS for tablecells
cellswidth : {
fontSize: 10,
// color:'gray',
bold: true,
alignment: 'center',
margin: [0, 12.55, 0, 12.75],
},
You can use pageBreak function for it:
pageBreakBefore: function(currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage) {
//Here you can change the criteria according to your requirements
if (currentNode.index % 7 === 0)) {
return true;
}
return false;
},

d3.js : Zoomable / Pannable on multiple circles based chart

Sorry if the title or my explanation are bad, probleme is not easy in french so in english ...
So, i try to make a chart like : Focus+Context via Brushing but, instead of having one path to show data, i've 500 circle.
For moment, Zoom and Pan dont work.
To my understanding of problem, i need to convert my 500 circle to one single path but i dont know how to do this, if it's the good solution or event if it's possible ..
Thanks for your help, here a fiddle (my first one): http://jsfiddle.net/Kazual/R96Kc/
And the code: (i give all the code, but this is only the pan effect that i need to fix, all data are random and dont mean anything, and use the 3 button on bottom right to update circle position)
function graphiqueCircle(x, y, w, h, trgDiv){
graphiqueCircle.C_INDICE_VIE = "Indice Vie";
graphiqueCircle.C_INDICE_SANTE = "Indice Sante";
graphiqueCircle.C_INDICE_INSTRUCTION = "Indice Instruction";
var indiceVie = false,
indiceSante = false,
indiceInstruction = false;
var margin = {top: y, right: 0, bottom: 0, left: x},
width = w,
height = h,
height2 = 20;
//
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var x2 = d3.scale.linear()
.range([0, width]);
var y2 = d3.scale.linear()
.range([height2, 0]);
//
var color = d3.scale.category10();
//
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var xAxis2 = d3.svg.axis()
.scale(x2)
.orient("bottom");
//
var brush = d3.svg.brush()
.x(x2)
.on("brush", brushed);
//
var area = d3.svg.area()
.interpolate("monotone")
.x(function(d) { return x(d.codeCom); })
.y0(height)
.y1(function(d) { return [0,1]; });
var area2 = d3.svg.area()
.interpolate("monotone")
.x(function(d) { return x2(d.codeCom); })
.y0(height2)
.y1(function(d) { return [0,1]; });
//
var svg = d3.select(trgDiv).append("svg").attr("class", "gMap")
.attr("width", width + 50 )
.attr("height", height + 50 + height2 +50);
//
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
//
var allCircles,
allCirclesContext,
theckBox,
axeX,
axeY,
_data;
//
var focus = svg.append("g")
.attr("transform", "translate(" + (margin.left + 10) + "," + margin.top + ")")
var context = svg.append("g")
.attr("transform", "translate(" + (margin.left + 10) + "," + (margin.top+height+height2+30) + ")")
//
_data = [
{codeCom:33001, communes:"obj1", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib1"},
{codeCom:33002, communes:"obj2", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib2"},
{codeCom:33003, communes:"obj3", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib3"},
{codeCom:33004, communes:"obj4", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib4"},
{codeCom:33005, communes:"obj5", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib5"},
{codeCom:33006, communes:"obj6", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib6"},
{codeCom:33007, communes:"obj7", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib7"},
{codeCom:33008, communes:"obj8", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib8"},
{codeCom:33009, communes:"obj9", indiceVie:0.4, indiceSante:0.5, indiceInstruction:0.3, IDH:0.6, LIBSCOT:"lib9"}
]
_data.forEach(function(d) {
d.IDH4 = (d.IDH4 != "NULL") ? +d.IDH4 : 0;
d.indiceVie = (d.indiceVie != "NULL") ? +d.indiceVie : 0;
d.indiceSante = (d.indiceSante != "NULL") ? +d.indiceSante : 0;
d.indiceInstruction = (d.indiceInstruction != "NULL") ? +d.indiceInstruction : 0;
d.codeCom = (d.codeCom != "NULL") ? +d.codeCom : 0;
});
//
x.domain(d3.extent(_data.map(function(d) { return d.codeCom; })));
y.domain([0,1]);
x2.domain(x.domain());
y2.domain(y.domain());
//
allCircles = focus.append("g");
allCircles.attr("id", "allCicles")
.datum(_data)
.attr("clip-path", "url(#clip)")
.attr("d", area)
.selectAll(".dot")
.data(_data)
.enter().append("circle")
.attr("class", "dot")
.attr("id", function(d){ return d.communes; })
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.codeCom); })
.attr("cy", function(d) { return 0; })
.style("fill", function(d) { return color(d.LIBSCOT); });
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("Communes");
focus.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("x", -6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Indice");
allCirclesContext = context.append("g");
allCirclesContext.attr("id", "allCirclesContext")
.datum(_data)
.attr("d", area2)
.selectAll(".dot")
.data(_data)
.enter().append("circle")
.attr("class", "dot")
.attr("id", function(d){ return d.communes; })
.attr("r", 2)
.attr("cx", function(d) { return x2(d.codeCom); })
.attr("cy", function(d) { return 0; })
.style("fill", function(d) { return color(d.LIBSCOT); });
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
//
context.append("g")
.attr("transform", function(d, i) { return "translate(0,-20)"; })
.style("fill", "blue")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", height2 + 7)
.style("fill-opacity", .2)
.style("visibility", "visible");
//
// LEGEND & CHEKBOX
var legend = focus.selectAll(".legend")
.data(color.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
//
createTchekBox();
function createTchekBox(){
theckBox = focus.selectAll(".theckBox")
.data(["Indice Vie", "Indice Sante", "Indice Instruction"])
.enter().append("g")
.attr("class", "theckBox")
.attr("transform", function(d, i) { return "translate(0," + ((i * 20)+300) + ")"; });
theckBox.append("rect")
.attr("isClicked", "false")
.attr("id", function(d) { return d; })
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", "black")
.on("mouseover", function(){
d3.select(this).style("fill", "grey");
})
.on("mouseout", function(){
if(d3.select(this).attr("isClicked") == "false")
d3.select(this).style("fill", "black");
else
d3.select(this).style("fill", "red");
})
.on("click", function(){
if(d3.select(this).attr("isClicked") == "false"){
d3.select(this).style("fill", "red");
d3.select(this).attr("isClicked", "true");
}else{
d3.select(this).style("fill", "black");
d3.select(this).attr("isClicked", "false");
}
if(d3.select(this).attr("id") == "Indice Vie")
indiceVie = !indiceVie;
else if(d3.select(this).attr("id") == "Indice Sante")
indiceSante = !indiceSante;
else if(d3.select(this).attr("id") == "Indice Instruction")
indiceInstruction = !indiceInstruction;
//
onUpdate();
});
theckBox.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
}
function brushed() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.select("#allCicles").attr("d", area);
focus.select(".x.axis").call(xAxis);
}
function onUpdate(){
var data1,
data2,
data3;
//
if(indiceVie)
data1 = graphiqueCircle.C_INDICE_VIE;
else
data1 = null;
if(indiceSante)
data2 = graphiqueCircle.C_INDICE_SANTE;
else
data2 = null;
if(indiceInstruction)
data3 = graphiqueCircle.C_INDICE_INSTRUCTION;
else
data3 = null;
//
allCircles.selectAll(".dot").each(function(d, i){
d3.select(this).transition().duration(400).delay(i*1)
.attr("cy", function(d, i) {
var returnValue = 0;
var diviseur = 0;
if(data1 == graphiqueCircle.C_INDICE_VIE){
returnValue += y(d.indiceVie);
diviseur++;
}
if(data2 == graphiqueCircle.C_INDICE_SANTE){
returnValue += y(d.indiceSante);
diviseur++;
}
if(data3 == graphiqueCircle.C_INDICE_INSTRUCTION){
returnValue += y(d.indiceInstruction);
diviseur++;
}
if(diviseur == 0)
return 0;
return returnValue/diviseur;
});
});
allCirclesContext.selectAll(".dot").each(function(d, i){
d3.select(this).transition().duration(400).delay(i*1)
.attr("cy", function(d, i) {
var returnValue = 0;
var diviseur = 0;
if(data1 == graphiqueCircle.C_INDICE_VIE){
returnValue += y2(d.indiceVie);
diviseur++;
}
if(data2 == graphiqueCircle.C_INDICE_SANTE){
returnValue += y2(d.indiceSante);
diviseur++;
}
if(data3 == graphiqueCircle.C_INDICE_INSTRUCTION){
returnValue += y2(d.indiceInstruction);
diviseur++;
}
if(diviseur == 0)
return 0;
return returnValue/diviseur-20;
});
});
}
}
var _myGraphique = new graphiqueCircle(20, 20, 800, 400, ".div_iMap");

Resources