From 3eaf5eb61f966ca682d7e5ac5b2595cac59358f7 Mon Sep 17 00:00:00 2001 From: gozo1234 Date: Fri, 26 Oct 2012 13:22:47 +0800 Subject: [PATCH 1/3] add interactions --- lib/charts/histogram.js | 164 +++++++++++++++++++++++++++------------- 1 file changed, 111 insertions(+), 53 deletions(-) diff --git a/lib/charts/histogram.js b/lib/charts/histogram.js index e9a7e93..3482ebc 100644 --- a/lib/charts/histogram.js +++ b/lib/charts/histogram.js @@ -92,25 +92,16 @@ conf.dimensionY = yTemp; conf.xAxisData = []; this.source = []; - + var dimenT = conf.allDimensions; for (i = 1, l = source.length; i < l; i++) { - if (conf.typeNames.length == 1) { - var line = {}, dimenT = conf.allDimensions; - for (j = 0, ll = dimenT.length; j < ll; j++) { - line[dimenT[j]] = source[i][j]; //each line is an array, contains value for each dimension - } + for(j = 1; j <= conf.typeNames.length; j++) { + var line = {}; + line[dimenT[0]] = i; + line[dimenT[1]] = source[i][j]; this.source.push(line); } - else if (conf.typeNames.length == 2) { - var lineY = {}, lineZ = {}, dimenT = conf.allDimensions; - lineY[dimenT[0]] = i; - lineY[dimenT[1]] = source[i][1]; - this.source.push(lineY); - lineZ[dimenT[0]] = i; - lineZ[dimenT[1]] = source[i][2]; - this.source.push(lineZ); - conf.xAxisData.push(source[i][0]); - } + conf.xAxisData.push(source[i][0]); + } //设置默认的定义域 var getExtent = function (s, dimen) { @@ -233,14 +224,16 @@ //bars var mouseOverBar = function (event) { var bars = this.data.container; - var seq = this.data.seqNum - this.data.seqNum % 2; var rectBn = this.data.rectBn; var clicked = false; var typeSeq = -1; var typeNum = this.data.typeNum; + var seq = this.data.seqNum - this.data.seqNum % typeNum; var xPos, yPos; var temp; var paper = bars[0].paper; + var i, j, k; + var textWidth; for(i = 0, j = rectBn.length; i < j; i++) if(rectBn[i].data.isClicked) { clicked = true; @@ -258,10 +251,34 @@ bars[this.data.seqNum].attr({ "fill-opacity":1 }); + xPos = bars[this.data.seqNum].attrs.x + 16; + yPos = bars[this.data.seqNum].attrs.y; + textWidth = 5 * bars[this.data.seqNum].data.yAxisLabel.length + 20; + temp = paper.rect(xPos, yPos - 10, textWidth, 20, 2).attr({ + "fill": this.data.color[this.data.seqNum % typeNum], + "fill-opacity": 1, + "stroke": "none" + }); + bars.push(temp); + temp = paper.path("M" + xPos + "," + (yPos - 4) + "L" + (xPos - 8) + "," + yPos + + "L" + xPos + "," + (yPos + 4) + "V" + yPos + "Z").attr({ + "fill" : this.data.color[this.data.seqNum % typeNum], + "stroke" : this.data.color[this.data.seqNum % typeNum] + }); + bars.push(temp); + temp = paper.text(xPos + 16, yPos, bars[this.data.seqNum].data.yAxisLabel).attr({ + "fill": "#ffffff", + "fill-opacity": 1, + "font-family": "雅黑", + "font-weight": "bold", + "font-size": 12, + "text-anchor": "middle" + }); + bars.push(temp); } else { for(i = 0, j = bars.length; i < j; i++) { if(i == seq) { - i++; + i+=typeNum-1; } else { @@ -270,35 +287,61 @@ }); } } + for(i = 0; i < typeNum; i++) { + xPos = bars[seq].attrs.x + 8 * typeNum + 8; + yPos = bars[seq + i].attrs.y; + textWidth = 5 * bars[seq + i].data.yAxisLabel.length + 20; + temp = paper.rect(xPos, yPos - 10, textWidth, 20, 2).attr({ + "fill": this.data.color[i], + "fill-opacity": 1, + "stroke": "none" + }); + bars.push(temp); + temp = paper.path("M" + xPos + "," + (yPos - 4) + "L" + (xPos - 8) + "," + yPos + + "L" + xPos + "," + (yPos + 4) + "V" + yPos + "Z").attr({ + "fill" : this.data.color[i], + "stroke" : this.data.color[i] + }); + bars.push(temp); + temp = paper.text(xPos + 16, yPos, bars[seq + i].data.yAxisLabel).attr({ + "fill": "#ffffff", + "fill-opacity": 1, + "font-family": "雅黑", + "font-weight": "bold", + "font-size": 12, + "text-anchor": "middle" + }); + bars.push(temp); + } } //pins xPos = bars[seq].attrs.x + 4 * typeNum; yPos = bars[seq].attrs.y + bars[seq].attrs.height; - //axis x text - temp = paper.text(xPos, yPos, this.data.xAxisLabel).attr({ - "file": "#ffffff", - "fill-opacity": 0.7, - "font-family": "雅黑", - "font-size": 12, - "text-anchor": "middle" - }); - var textWidth = temp.node.clientWidth + 8; - temp.remove(); + + textWidth = 6 * this.data.xAxisLabel.length + 20; //axis x rect - temp = paper.rect(xPos - textWidth/2, yPos, textWidth, 20, 2).attr({ + temp = paper.rect(xPos - textWidth/2, yPos + 8, textWidth, 20, 2).attr({ "fill": "#5f5f5f", "fill-opacity": 1, "stroke": "none" });; bars.push(temp); - temp = paper.text(xPos, yPos + 10, this.data.xAxisLabel).attr({ - "file": "#abcdef", - "fill-opacity": 0.7, + //axis x text + temp = paper.text(xPos, yPos + 18, this.data.xAxisLabel).attr({ + "fill": "#ffffff", + "fill-opacity": 1, "font-family": "雅黑", + "font-weight": "bold", "font-size": 12, "text-anchor": "middle" }); bars.push(temp); + temp = paper.path("M" + (xPos - 4) + "," + (yPos + 8) + "L" + xPos + "," + yPos + + "L" + (xPos + 4) + "," + (yPos + 8) + "H" + xPos + "Z").attr({ + "fill" : "#5F5F5F", + "stroke" : "#5F5F5F" + }); + bars.push(temp); }; var mouseOutBar = function (event) { @@ -309,6 +352,7 @@ var typeSeq = -1; var typeNum = this.data.typeNum; var temp; + var i, j, k; for(i = 0, j = rectBn.length; i < j; i++) if(rectBn[i].data.isClicked) { clicked = true; @@ -323,23 +367,26 @@ "fill-opacity":1 }); } + for(i = 0; i < 3; i++) { + temp = bars.pop(); + temp.remove(); + } } else { for(i = 0, j = bars.length; i < j; i++) { - if(i == seq) { - i++; - } - else { - bars[i].attr({ + bars[i].attr({ "fill-opacity":1 - }); - } + }); + } + for(i = 0, j = typeNum * 3; i < j; i++) { + temp = bars.pop(); + temp.remove(); } } //pins - temp = bars.pop(); - temp.remove(); - temp = bars.pop(); - temp.remove(); + for(i = 0; i < 3; i++) { + temp = bars.pop(); + temp.remove(); + } }; for (i = 0, j = this.source.length; i < j; i++) { @@ -356,8 +403,9 @@ temp.data.seqNum = i; temp.data.rectBn = rectBn; temp.data.typeNum = conf.typeNames.length; - temp.data.xAxisLabel = conf.xAxisData[d3.round((i-1)/l)]; + temp.data.xAxisLabel = conf.xAxisData[Math.floor(i/l)]; temp.data.yAxisLabel = this.source[i][dimenY]; + temp.data.color = conf.barColor; temp.mouseover(mouseOverBar); temp.mouseout(mouseOutBar); bars.push(temp); @@ -368,14 +416,18 @@ var bars = this.data.container; var seq = this.data.seqNum; var rectBn = this.data.rectBn; + var typeNum = this.data.typeNum; + var i, j, k; for(i = 0, j = rectBn.length; i < j; i++) if(rectBn[i].data.isClicked) return; - // - for(i = (seq + 1)%2, j = bars.length; i < j; i+=2) { - bars[i].attr({ - "fill-opacity":0.3 - }); + for(k = 0; k < typeNum; k++) { + if(seq % typeNum != k) + for(i = k, j = bars.length; i < j; i+=typeNum) { + bars[i].attr({ + "fill-opacity":0.3 + }); + } } this.data.underBn[seq].attr({ "fill-opacity":0.5 @@ -385,14 +437,19 @@ var bars = this.data.container; var seq = this.data.seqNum; var rectBn = this.data.rectBn; + var typeNum = this.data.typeNum; + var i, j, k; for(i = 0, j = rectBn.length; i < j; i++) if(rectBn[i].data.isClicked) return; // - for(i = (seq + 1)%2, j = bars.length; i < j; i+=2) { - bars[i].attr({ - "fill-opacity":1 - }); + for(k = 0; k < typeNum; k++) { + if(seq % typeNum != k) + for(i = k, j = bars.length; i < j; i+=typeNum) { + bars[i].attr({ + "fill-opacity":1 + }); + } } this.data.underBn[seq].attr({ "fill-opacity":0 @@ -406,6 +463,7 @@ var rectBn = this.data.rectBn; var lastClickedSeq; var typeNum = this.data.typeNum; + var i, j, k; //check if any legend has been already clicked for(i = 0, j = rectBn.length; i < j; i++) { if(rectBn[i].data.isClicked) { From 77f2ce4455c307b9a9aa43d0287c94451a2447d8 Mon Sep 17 00:00:00 2001 From: gozo1234 Date: Fri, 26 Oct 2012 14:35:36 +0800 Subject: [PATCH 2/3] solved the overlapped problem --- lib/charts/histogram.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/charts/histogram.js b/lib/charts/histogram.js index 3482ebc..289c10e 100644 --- a/lib/charts/histogram.js +++ b/lib/charts/histogram.js @@ -287,9 +287,23 @@ }); } } + //check if the labels will be overlapped + var overlapped = false; + var pos = []; + for(i = 0; i < typeNum; i++) { + pos.push(bars[seq + i].attrs.y); + } + pos.sort(); + var sub = []; + for(i = 0; i < pos.length - 1; i++) { + sub.push(pos[i+1] - pos[i]); + } + sub.sort(); + if(sub[0] < 20) + overlapped = true; for(i = 0; i < typeNum; i++) { xPos = bars[seq].attrs.x + 8 * typeNum + 8; - yPos = bars[seq + i].attrs.y; + yPos = overlapped?(bars[seq + typeNum - 1].attrs.y + 20 * (typeNum - i - 1)):bars[seq + i].attrs.y; textWidth = 5 * bars[seq + i].data.yAxisLabel.length + 20; temp = paper.rect(xPos, yPos - 10, textWidth, 20, 2).attr({ "fill": this.data.color[i], From 122e802a6f1756bea178fa84fdab5c9707ec1079 Mon Sep 17 00:00:00 2001 From: gozo1234 Date: Mon, 29 Oct 2012 10:29:59 +0800 Subject: [PATCH 3/3] modified some details --- lib/charts/histogram.js | 110 +++++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 46 deletions(-) diff --git a/lib/charts/histogram.js b/lib/charts/histogram.js index 289c10e..00b598f 100644 --- a/lib/charts/histogram.js +++ b/lib/charts/histogram.js @@ -93,6 +93,12 @@ conf.xAxisData = []; this.source = []; var dimenT = conf.allDimensions; + if (conf.typeNames == null) { + conf.typeNames = []; + for (i = 0, j = source[0].length; i < j; i++) { + conf.typeNames.push(source[0][i]); + } + } for (i = 1, l = source.length; i < l; i++) { for(j = 1; j <= conf.typeNames.length; j++) { var line = {}; @@ -103,6 +109,7 @@ conf.xAxisData.push(source[i][0]); } + //设置默认的定义域 var getExtent = function (s, dimen) { return d3.extent(s, function (p) { @@ -168,7 +175,7 @@ tickText.push(paper.text(x[dimenX](ticks[j]), downPos+10, conf.xAxisData[ticks[j]-1]).attr({ "fill": "#878791", "fill-opacity": 0.7, - "font-family": "雅黑", + "font-family": "宋", "font-size": 12 }).attr({ "text-anchor": "middle" @@ -188,7 +195,7 @@ tickText.push(paper.text(leftPos - 10, y[dimenY](ticks[j]), ticks[j]).attr({ "fill": "#878791", "fill-opacity": 0.7, - "font-family": "雅黑", + "font-family": "宋", "font-size": 12 }).attr({ "text-anchor": "end" @@ -234,16 +241,17 @@ var paper = bars[0].paper; var i, j, k; var textWidth; - for(i = 0, j = rectBn.length; i < j; i++) + for (i = 0, j = rectBn.length; i < j; i++) if(rectBn[i].data.isClicked) { clicked = true; typeSeq = i; } //hover - if(clicked) { - if(typeSeq != this.data.seqNum % typeNum) + if (clicked) { + if (typeSeq != this.data.seqNum % typeNum) { return; - for(i = this.data.seqNum % typeNum, j = bars.length; i < j; i+=typeNum) { + } + for (i = this.data.seqNum % typeNum, j = bars.length; i < j; i+=typeNum) { bars[i].attr({ "fill-opacity":0.3 }); @@ -269,39 +277,39 @@ temp = paper.text(xPos + 16, yPos, bars[this.data.seqNum].data.yAxisLabel).attr({ "fill": "#ffffff", "fill-opacity": 1, - "font-family": "雅黑", + "font-family": "宋", "font-weight": "bold", "font-size": 12, "text-anchor": "middle" }); bars.push(temp); } else { - for(i = 0, j = bars.length; i < j; i++) { + for (i = 0, j = bars.length; i < j; i++) { if(i == seq) { - i+=typeNum-1; + i += typeNum - 1; } else { - - bars[i].attr({ - "fill-opacity":0.3 - }); + bars[i].attr({ + "fill-opacity":0.3 + }); } } //check if the labels will be overlapped var overlapped = false; var pos = []; - for(i = 0; i < typeNum; i++) { + for (i = 0; i < typeNum; i++) { pos.push(bars[seq + i].attrs.y); } pos.sort(); var sub = []; - for(i = 0; i < pos.length - 1; i++) { + for (i = 0; i < pos.length - 1; i++) { sub.push(pos[i+1] - pos[i]); } sub.sort(); - if(sub[0] < 20) + if (sub[0] < 20) { overlapped = true; - for(i = 0; i < typeNum; i++) { + } + for (i = 0; i < typeNum; i++) { xPos = bars[seq].attrs.x + 8 * typeNum + 8; yPos = overlapped?(bars[seq + typeNum - 1].attrs.y + 20 * (typeNum - i - 1)):bars[seq + i].attrs.y; textWidth = 5 * bars[seq + i].data.yAxisLabel.length + 20; @@ -320,7 +328,7 @@ temp = paper.text(xPos + 16, yPos, bars[seq + i].data.yAxisLabel).attr({ "fill": "#ffffff", "fill-opacity": 1, - "font-family": "雅黑", + "font-family": "宋", "font-weight": "bold", "font-size": 12, "text-anchor": "middle" @@ -344,7 +352,7 @@ temp = paper.text(xPos, yPos + 18, this.data.xAxisLabel).attr({ "fill": "#ffffff", "fill-opacity": 1, - "font-family": "雅黑", + "font-family": "宋", "font-weight": "bold", "font-size": 12, "text-anchor": "middle" @@ -367,45 +375,47 @@ var typeNum = this.data.typeNum; var temp; var i, j, k; - for(i = 0, j = rectBn.length; i < j; i++) - if(rectBn[i].data.isClicked) { + for (i = 0, j = rectBn.length; i < j; i++) { + if (rectBn[i].data.isClicked) { clicked = true; typeSeq = i; } + } //hover if(clicked) { - if(typeSeq != this.data.seqNum % typeNum) + if (typeSeq != this.data.seqNum % typeNum) { return; - for(i = this.data.seqNum % typeNum, j = bars.length; i < j; i+=typeNum) { + } + for (i = this.data.seqNum % typeNum, j = bars.length; i < j; i+=typeNum) { bars[i].attr({ "fill-opacity":1 }); } - for(i = 0; i < 3; i++) { + for (i = 0; i < 3; i++) { temp = bars.pop(); temp.remove(); } } else { - for(i = 0, j = bars.length; i < j; i++) { + for (i = 0, j = bars.length; i < j; i++) { bars[i].attr({ "fill-opacity":1 }); } - for(i = 0, j = typeNum * 3; i < j; i++) { + for (i = 0, j = typeNum * 3; i < j; i++) { temp = bars.pop(); temp.remove(); } } //pins - for(i = 0; i < 3; i++) { + for (i = 0; i < 3; i++) { temp = bars.pop(); temp.remove(); } }; for (i = 0, j = this.source.length; i < j; i++) { - for (k = 0, l = conf.typeNames.length; k < l; k++) - if(i%l == k) { + for (k = 0, l = conf.typeNames.length; k < l; k++) { + if (i%l == k) { temp = paper.rect((x[dimenX](this.source[i][dimenX])-barWidth * (l / 2 - i % l)), y[dimenY](this.source[i][dimenY]), barWidth, downPos - y[dimenY](this.source[i][dimenY])).attr({ "fill": conf.barColor[k], @@ -424,6 +434,7 @@ temp.mouseout(mouseOutBar); bars.push(temp); } + } } //legend var mouseOverLegend = function (event) { @@ -432,16 +443,17 @@ var rectBn = this.data.rectBn; var typeNum = this.data.typeNum; var i, j, k; - for(i = 0, j = rectBn.length; i < j; i++) + for (i = 0, j = rectBn.length; i < j; i++) if(rectBn[i].data.isClicked) return; - for(k = 0; k < typeNum; k++) { - if(seq % typeNum != k) - for(i = k, j = bars.length; i < j; i+=typeNum) { + for (k = 0; k < typeNum; k++) { + if (seq % typeNum != k) { + for (i = k, j = bars.length; i < j; i+=typeNum) { bars[i].attr({ "fill-opacity":0.3 }); } + } } this.data.underBn[seq].attr({ "fill-opacity":0.5 @@ -453,17 +465,20 @@ var rectBn = this.data.rectBn; var typeNum = this.data.typeNum; var i, j, k; - for(i = 0, j = rectBn.length; i < j; i++) - if(rectBn[i].data.isClicked) + for (i = 0, j = rectBn.length; i < j; i++) { + if(rectBn[i].data.isClicked) { return; + } + } // - for(k = 0; k < typeNum; k++) { - if(seq % typeNum != k) - for(i = k, j = bars.length; i < j; i+=typeNum) { + for (k = 0; k < typeNum; k++) { + if (seq % typeNum != k) { + for (i = k, j = bars.length; i < j; i+=typeNum) { bars[i].attr({ "fill-opacity":1 }); } + } } this.data.underBn[seq].attr({ "fill-opacity":0 @@ -479,8 +494,8 @@ var typeNum = this.data.typeNum; var i, j, k; //check if any legend has been already clicked - for(i = 0, j = rectBn.length; i < j; i++) { - if(rectBn[i].data.isClicked) { + for (i = 0, j = rectBn.length; i < j; i++) { + if (rectBn[i].data.isClicked) { clicked = true; lastClickedSeq = i; break; @@ -489,17 +504,18 @@ if(this.data.isClicked) { for(i = 0; i < typeNum; i++) { if(i != seq % typeNum) { - for(var j = i, m = bars.length; j < m; j+=typeNum) + for(var j = i, m = bars.length; j < m; j+=typeNum) { bars[j].attr({ "fill-opacity":0.3 }); + } } } this.data.isClicked = false; } else if(!clicked) { - for(i = 0; i < typeNum; i++) { - if(i != seq % typeNum) { - for(j = i, m = bars.length; j < m; j+=typeNum) + for (i = 0; i < typeNum; i++) { + if (i != seq % typeNum) { + for (j = i, m = bars.length; j < m; j+=typeNum) bars[j].attr({ "fill-opacity":0.1 }); @@ -511,14 +527,16 @@ underBn[lastClickedSeq].attr({ "fill-opacity":0 }); - for(i = lastClickedSeq % typeNum, j = bars.length; i < j; i+=typeNum) + for (i = lastClickedSeq % typeNum, j = bars.length; i < j; i+=typeNum) { bars[i].attr({ "fill-opacity":0.1 }); - for(i = seq % typeNum, j = bars.length; i < j; i+=typeNum) + } + for (i = seq % typeNum, j = bars.length; i < j; i+=typeNum) { bars[i].attr({ "fill-opacity":1 }); + } this.data.rectBn[lastClickedSeq].data.isClicked = false; this.data.isClicked = true; }