ScatterplotMatrix.prototype.drawDiagram = function () { var i, j, k, z, ticks; var conf = this.defaults, x = this.x, y = this.y, sw = conf.squareWidth, g = conf.gap, cR = conf.circleR; var paper = this.canvas; var sourceData = this.source; var dimensionsX = conf.dimensionsX, dimensionsY = conf.dimensionsY, lx = dimensionsX.length, ly = dimensionsY.length; var browserName = navigator.appName; var that = this; $(this.node).append(this.floatTag); //画背景点 var circlesBg = paper.set(); //背景点 var centerPos; if (browserName !== "Microsoft Internet Explorer") { for (k = 0; k < sourceData.length; k++) { for (i = 0; i < lx; i++) { for (j = 0; j < ly; j++) { centerPos = this.circleCenter(k, dimensionsX[i], dimensionsY[j]); circlesBg.push(paper.circle(centerPos[0], centerPos[1], cR).attr({ "fill": "gray", "stroke": "none", "opacity": 0.2 })); } } } } // 画矩形框 var squares = paper.set(); var x1, y1; for (i = 0; i < lx; i++) { for (j = 0; j < ly; j++) { x1 = x[dimensionsX[i]].range()[0]; y1 = y[dimensionsY[j]].range()[1]; squares.push(paper.rect(x1 - 1, y1 - 1, sw + 2, sw + 2)); } } squares.attr({ "fill": "white", "fill-opacity": 0.5, //背景点的蒙版 "stroke": "#d6d6d6", "stroke-width": '1px' }); //画虚线 var reLines = paper.set(), tickText = paper.set(); var tickAr = [10], //set the number of ticks leftPos = x[dimensionsX[0]].range()[0], rightPos = x[dimensionsX[lx - 1]].range()[1], upPos = y[dimensionsY[0]].range()[1], downPos = y[dimensionsY[ly - 1]].range()[0]; var reLineGap = sw / 7; //每个矩形框中画6条虚线 var reLinePos; //画纵向的虚线 for (i = 0; i < lx; i++) { ticks = x[dimensionsX[i]].ticks; for (j = 0; j < ticks.length; j++) { tickText.push(paper.text((x[dimensionsX[i]](ticks[j])), downPos + 6, ticks[j]).attr({ "fill": "#aaaaaa", "fill-opacity": 0.7, "font-family": "雅黑", "font-size": 12 }).attr({ "text-anchor": "end" }).rotate(-45, x[dimensionsX[i]](ticks[j]), downPos + 6)); } for (z = 1; z < 7; z++) { reLinePos = x[dimensionsX[i]].range()[0] + z * reLineGap; reLines.push(paper.path("M" + (reLinePos) + "," + (upPos) + "L" + (reLinePos) + "," + (downPos)).attr({ "stroke": "#ebebeb", "stroke-dasharray": "-" })); } } //画横向的虚线 for (i = 0; i < ly; i++) { //draw reference lines ticks = y[dimensionsY[i]].ticks; for (j = 0; j < ticks.length; j++) { tickText.push(paper.text(rightPos + 6, y[dimensionsY[i]](ticks[j]), ticks[j]).attr({ "fill": "#aaaaaa", "fill-opacity": 0.7, "font-family": "雅黑", "font-size": 12 }).attr({ "text-anchor": "start" }).rotate(315, rightPos + 6, y[dimensionsY[i]](ticks[j]))); } for (z = 1; z < 7; z++) { reLinePos = y[dimensionsY[i]].range()[1] + z * reLineGap; reLines.push(paper.path("M" + (leftPos) + "," + (reLinePos) + "L" + (rightPos) + "," + (reLinePos)).attr({ "stroke": "#ebebeb", "stroke-dasharray": "-" })); } } //坐标轴名称 var axText = paper.set(); var xPos, yPos; var pos = y[dimensionsY[0]].range()[1] - 10; for (i = 0; i < lx; i++) { xPos = x[dimensionsX[i]].range()[0] + sw / 2; axText.push(paper.text(xPos, pos, dimensionsX[i]).attr({ "fill": "#000000", "fill-opacity": 0.7, "font-family": "Verdana", //"font-weight": "bold", "font-size": 12 }).attr({ "text-anchor": "middle" })); } pos = x[dimensionsX[0]].range()[0] - 10; for (i = 0; i < ly; i++) { yPos = y[dimensionsY[i]].range()[1] + sw / 2; axText.push(paper.text(pos, yPos, dimensionsY[i]).attr({ "fill": "#000000", "fill-opacity": 0.7, "font-family": "Verdana", //"font-weight": "bold", "font-size": 12 }).attr({ "text-anchor": "middle" }).rotate(-90, pos, yPos)); } // 画前景点 var circlesFg = []; //circles in foreground var circleType = -1; var typeMax = -1; this.preIndex = "start"; this.linePosition = [0,0]; //水平虚线 that.lineH = paper.path("M" + (leftPos) + "," + (0) + "L" + (rightPos) + "," + (0)).attr({ "stroke-dasharray": "- ", 'stroke': '#000000' }).hide(); //垂直虚线 that.lineV = paper.path("M" + (0) + "," + (upPos) + "L" + (0) + "," + (downPos)).attr({ "stroke-dasharray": "- ", 'stroke': '#000000' }).hide(); var hoverTag; var circle; for (k = 0; k < sourceData.length; k++) { if (conf.typeName !== "NoTypeDefinition") { //classify the circles according to their types circleType = sourceData[k][conf.typeName] - 1; typeMax = Math.max(typeMax, circleType); } else { circleType = 0; } for (i = 0; i < lx; i++) { for (j = 0; j < ly; j++) { centerPos = this.circleCenter(k, dimensionsX[i], dimensionsY[j]); //前景点 circle = paper.circle(centerPos[0], centerPos[1], cR) .data("type", circleType) .data("canHover", 0) .data("position", centerPos) .data('colorType', circleType) .attr({ "fill": "#800", "stroke": "none", "opacity": 0.5 }).attr({ "fill": this.getColor(circleType) }); //如果制定了hover要显示的文字,则hover显示的文字 if (conf.legendDimen !== "NoTagDimen") { hoverTag = conf.legendDimen + ": " + sourceData[k][conf.legendDimen]; circle.data("legend", hoverTag); } circlesFg.push(circle); } } } //图例 var legendArea = this.defaults.legendArea; var rectBn = paper.set(); var underBn = []; for (i = 0; i <= typeMax; i++) { //底框 underBn.push(paper.rect(legendArea[0] + 10, legendArea[1] + 10 + (20 + 3) * i, 180, 20).attr({ "fill": "#ebebeb", "stroke": "none" }).hide()); //色框 paper.rect(legendArea[0] + 10 + 3, legendArea[1] + 10 + (20 + 3) * i + 6, 16, 8).attr({ "fill": this.getColor(i), "stroke": "none" }); //文字 paper.text(legendArea[0] + 10 + 3 + 16 + 8, legendArea[1] + 10 + (20 + 3) * i + 10, conf.typeNames[i]).attr({ "fill": "black", "fill-opacity": 1, "font-family": "Verdana", "font-size": 12 }).attr({ "text-anchor": "start" }); //选框 rectBn.push(paper.rect(legendArea[0] + 10, legendArea[1] + 10 + (20 + 3) * i, 180, 20).attr({ "fill": "white", "fill-opacity": 0, "stroke": "none" //"r": 3 }).data("type", i)).data("clicked", 0); } if (browserName !== "Microsoft Internet Explorer") { rectBn.forEach(function (d, i) { underBn[i].data('legendclicked', false); d.mouseover(function () { if (underBn[i].data('legendclicked') === false) { underBn[i].attr('opacity', 0.5).show(); } }).mouseout(function () { if (underBn[i].data('legendclicked') === false) { underBn[i].hide(); } }); d.click(function () { for (j = 0; j < underBn.length; j++) { if (j === i) { underBn[j].show(); } else { underBn[j].hide(); } } rectBn.forEach(function (eachBn) { if (eachBn !== d) { eachBn.data("clicked", 0); } }); if (d.data("clicked") === 0) { underBn[i].attr('opacity', 1).show(); underBn[i].data('legendclicked', true); circlesFg.forEach(function (ec) { if (ec.data("type") !== d.data("type")) { ec.hide(); ec.data("canHover", 0); } else { ec.show(); ec.data("canHover", 1); } }); d.data("clicked", 1); } else if (d.data("clicked") === 1) { underBn[i].hide(); underBn[i].data('legendclicked', false); d.data("clicked", 0); circlesFg.forEach(function (ec) { ec.show(); ec.data("canHover", 0); }); } }); }); //Bursh函数定义 var curBrush; function brushstart() { if (curBrush !== undefined && curBrush !== d3.event.target) { curBrush.clear(); } var i; for (i = 0; i < circlesFg.length; i++) { circlesFg[i].hide(); circlesFg[i].data("canHover", 0); } underBn.forEach(function (ub) { ub.hide(); }); rectBn.forEach(function (rb) { rb.data("clicked", 0); }); } function brush() { curBrush = d3.event.target; var e = curBrush.extent(), dimX = d3.event.target.dimX, dimY = d3.event.target.dimY, tempX, tempY, count = lx * ly, i, z; for (i = 0; i < sourceData.length; i++) { tempX = sourceData[i][dimX]; tempY = sourceData[i][dimY]; if (e[0][0] - 1 <= tempX && tempX <= e[1][0] + 1 && e[0][1] - 1 <= tempY && tempY <= e[1][1] + 1) { for (z = 0; z < count; z++) { circlesFg[i * count + z].show(); } } else { for (z = 0; z < count; z++) { circlesFg[i * count + z].hide(); } } } } function brushend() { if (d3.event.target.empty()) { circlesFg.forEach(function (d) { d.show(); }); } } //Brush交互 var brushes = []; var b; for (i = 0; i < lx; i++) { for (j = 0; j < ly; j++) { b = Brush().x(x[dimensionsX[i]]).y(y[dimensionsY[j]]).backgroundAttr({ "opacity": 0, //背景颜色:白色、全透明 "fill": "white" }).foregroundAttr({ //选框颜色 "opacity": 0.2, "fill": "#fff700" }).on("brushstart", brushstart).on("brush", brush).on("brushend", brushend); b(paper); b.dimX = dimensionsX[i]; b.dimY = dimensionsY[j]; brushes.push(b); } } //hover交互 //var preIndex = "start"; var floatTag = this.floatTag; $(paper.canvas).bind("mousemove", function (e) { var bgOffset = $(this).parent().offset(); var mouse = [e.pageX - bgOffset.left, e.pageY - bgOffset.top]; var location = [Math.floor((mouse[0] - leftPos) / (sw + g)), Math.floor((mouse[1] - upPos) / (sw + g))]; if (that.preIndex !== "start") { that.lineV.hide(); that.lineH.hide(); if (conf.legendDimen !== "NoTagDimen") { floatTag.css({"visibility" : "hidden"}); } } if (location[0] >= 0 && location[0] <= lx && location[1] >= 0 && location[1] <= ly) { for (i = location[0] * ly + location[1]; i < circlesFg.length; i = i + lx * ly) { var center = circlesFg[i].data("position"); var canHover = circlesFg[i].data("canHover"); if ((canHover === 1) && (Math.abs(mouse[0] - center[0]) <= cR) && (Math.abs(mouse[1] - center[1]) <= cR)) { that.lineV.translate(center[0] - that.linePosition[0], 0).attr('stroke', that.getColor(circlesFg[i].data('colorType'))).show(); that.lineH.translate(0, center[1] - that.linePosition[1]).attr('stroke', that.getColor(circlesFg[i].data('colorType'))).show(); that.linePosition = center; if (conf.legendDimen !== "NoTagDimen") { floatTag.html('<div style="text-align: center;margin:auto;color:#ffffff">' + circlesFg[i].data("legend") + '</div>'); floatTag.css({"visibility" : "visible"}); } that.preIndex = i; break; } } } }); } };
Parallel.prototype.generatePaths = function () { var conf = this.defaults; var axis = Axis() .orient("left") .tickAttr(conf.axisStyle.tickAttr) .tickTextAttr(conf.axisStyle.tickTextAttr) .domainAttr(conf.axisStyle.domainAttr); var m = conf.marginWidth; var paper = this.canvas; this.bg = paper.set(); var i, l; for (i = 0, l = this.source.length; i<l; i++) { var line = this.source[i]; this.bg.push(paper.path(this.path(line))); } this.bg.attr(conf.backgroundAttr).attr({transform: "t" + m[3] + ',0'}); this.fg = paper.set(); for (i = 0, l = this.source.length; i<l; i++) { var line = this.source[i]; this.fg.push(paper.path(this.path(line))); } this.fg.attr(conf.foregroundAttr).attr({transform: "t" + m[3] + ',0'}); var dimensions = this.dimensions; for(i = 0, l = dimensions.length; i<l; i++){ var ax=axis.scale(this.y[dimensions[i]])(paper); ax.push(paper.text(0, m[0] - 12, dimensions[i]).attr({"text-anchor": "middle"})); ax.attr({transform: "t" + (m[3] + this.x.range()[i] ) + ',0'}); } var xInterval = Math.min(this.x.range()[1] - this.x.range()[0] - 20, 16); var brushs = []; this.statistic = {}; this.statistic["selected"] = 0; this.statistic["all"] = this.source.length; this.statistic["items"] = {}; var that = this; this.brush = function() { var statistic = that.statistic; var dimensionExtents = that.dimensionExtent; var actives = that.dimensions.filter(function(p) { var empty = that.y[p].brush.empty(); if (empty) { statistic.items[p] = -1; dimensionExtents[p] = undefined; } else { statistic.items[p] = 0; } return !empty; }), extents = actives.map(function(p) { var extent = that.y[p].brush.extent(); if (that.dimensionType[p] === "quantitative") { that.dimensionExtent[p] = extent; } else { that.dimensionExtent[p] = [ that.dimensionDomain[p][Math.ceil(extent[0] - 0.5)], that.dimensionDomain[p][Math.floor(extent[1] - 0.5)] ]; } return extent; }); var i, j, l, ll, p; var d, value, inExtent, selected; //var brush, dimen; statistic["selected"] = 0; for (j=0, l=that.fg.length; j<l; j++) { d = that.source[j]; selected = true; for (i = 0, ll = actives.length; i < ll; i++) { p = actives[i]; value = that.dimensionType[p] === "quantitative" ? d[p] : that.dimensionDomain[p].itemIndex[d[p]] + 0.5; inExtent = extents[i][0] <= value && value <= extents[i][1]; if (inExtent) { statistic.items[p] += 1;} if (!inExtent) {selected = false;} } if (selected) { statistic["selected"] += 1; that.fg[j].attr({"stroke": "steelblue"}); } else { that.fg[j].attr({"stroke": "none"}); } } that.defaults.customEvent["brush"].call(that); }, brushstart = function () { that.defaults.customEvent["brushstart"].call(that); }, brushend = function () { that.defaults.customEvent["brushend"].call(that); }; var b, start, end, temp; for (var i = 0, l = dimensions.length; i<l; i++) { dimen = dimensions[i]; b = Brush().y(this.y2[dimen]) .left(m[3] + this.x.range()[i] - xInterval/2) .width(xInterval) .backgroundAttr({"opacity": 0, "fill": "white"}) .foregroundAttr({"opacity": 0.5, "fill": "gray"}) .on("brushstart", brushstart) .on("brush", this.brush) .on("brushend", brushend); if (typeof this.dimensionExtent[dimen] !== 'undefined') { if (this.dimensionType[dimen] === "quantitative") { b.extent(this.dimensionExtent[dimen]); } else { b.extent(this._getOrdinalExtent(dimen, this.dimensionExtent[dimen])); } } this.y[dimen].brush = b(paper); //this.y[dimensions[i]].brush.dimension = dimensions[i]; } if (!$.isEmptyObject(this.dimensionExtent)) { this.brush(); } };