diff --git a/example/column/column.html b/example/column/column.html
index 3831584..e6fde2b 100644
--- a/example/column/column.html
+++ b/example/column/column.html
@@ -1,39 +1,64 @@
-
-
-
- Column
-
-
+
+
+ Column
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/example/column/column_source.html b/example/column/column_source.html
deleted file mode 100644
index 03611d6..0000000
--- a/example/column/column_source.html
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
- Column
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/lib/charts/column.js b/lib/charts/column.js
index 6c0de8c..b226c1d 100644
--- a/lib/charts/column.js
+++ b/lib/charts/column.js
@@ -13,12 +13,20 @@
/**
* Column构造函数
- * Creates Column in a DOM node with id "chart", default width is 522; height is 522px;
+ * Creates Column in a DOM node with id "chart"
* Options:
*
- * - `width` 宽度,默认为节点宽度
- * - `yBase` 纵坐标的基线值,有的以0为起始值,有的则以数据中的最小值为起始值
+ * - `width` 宽度,默认为522,单位像素
+ * - `height` 高度,默认为522,单位像素
+ * - `yBase` 纵坐标的基线值,默认为0,可以设置为任意数值;为undefined时,以数据中的最小值为起始值
* - `gap` 组与组之间的缝隙宽度
+ * - `showLegend` 是否显示图例
+ * - `legendWidth` 图例的宽度
+ * - `margin` 图表的间距,依次为上右下左
+ * - `xTickNumber` 横轴刻度数
+ * - `yTickNumber` 纵轴刻度数
+ * - `formatLabel` 横轴提示格式化函数,传入横轴值,默认函数传出原始值
+ * - `formatYScale` 纵轴刻度格式化函数,传入纵轴刻度值,
*
* Examples:
* ```
@@ -38,7 +46,7 @@
this.dimension.column = {
type: "string",
required: true,
- index: 0
+ index: undefined
};
/**
* 横向纬度
@@ -61,20 +69,33 @@
// canvas parameters
this.defaults.width = 522;
this.defaults.height = 522;
- this.defaults.margin = 50;
+
+ this.defaults.margin = [50, 50, 50, 50];
+
this.defaults.gap = 15;
this.defaults.circleR = 3;
this.defaults.barColor = ["#308BE6","#8EEC00","#DDDF0D"];
this.defaults.xTickNumber = 5;
this.defaults.yTickNumber = 5;
- this.defaults.yBase = undefined;
+ this.defaults.yBase = 0;
+ this.defaults.showLegend = true;
+ this.defaults.legendWidth = 100;
//图例区域的左上顶点坐标x,y,宽,高
this.defaults.legendArea = [422, 50, 472, 220];
//散点矩阵区域的左上顶点坐标x,y,宽,高
this.defaults.diagramArea = [50, 50, 422, 472];
this.columnSet = [];
+ this.formatLabel = function (text) {
+ return text;
+ };
+ this.formatYScale = function (text) {
+ return text;
+ };
+ this.formatValue = function (value) {
+ return value;
+ };
this.setOptions(options);
this.createCanvas();
@@ -145,20 +166,26 @@
} else {
dataTable = source;
}
- this.columns = _.groupBy(dataTable, map.column);
+ // 不指定列,将当前数据作为一列
+ this.columns = (typeof map.column === 'undefined') ? {column: dataTable} : _.groupBy(dataTable, map.column);
+ var that = this;
+ _.each(this.columns, function (group, key) {
+ that.columns[key] = _.sortBy(group, map.x);
+ });
this.columnCount = _.keys(this.columns).length;
-
conf.xAxisData = _.pluck(_.first(_.values(this.columns)), map.x);
conf.xTickNumber = Math.min(conf.xAxisData.length, conf.xTickNumber);
// 纵坐标的范围
- conf.yExtent = d3.extent(dataTable, function (item) {
+ var yExtent = d3.extent(dataTable, function (item) {
return item[map.value];
});
// 纵坐标基线值
- if (conf.yBase !== undefined) {
- conf.yExtent.push(conf.yBase);
- conf.yExtent = d3.extent(conf.yExtent);
+ if (typeof conf.yBase !== 'undefined') {
+ yExtent.push(conf.yBase);
}
+ yExtent = d3.extent(yExtent);
+ // 最大值放大1/10
+ conf.yExtent = [yExtent[0], yExtent[1] * 1.1];
};
/**
@@ -166,16 +193,20 @@
*/
Column.prototype.setAxis = function () {
var conf = this.defaults;
- var tagWidth = conf.width / 5 > 50 ? 50 : conf.width / 5;
- conf.legendArea = [conf.width - tagWidth - conf.margin, 0, conf.width, conf.height];
- conf.diagramArea = [0, 0, conf.width - tagWidth - conf.margin, conf.height];
- var w = conf.diagramArea[2] - 2 * conf.margin;
- var h = conf.diagramArea[3] - conf.margin;
+ if (conf.showLegend) {
+ conf.legendArea = [conf.width - conf.legendWidth, 0, conf.width, conf.height];
+ } else {
+ conf.legendWidth = 0;
+ conf.legendArea = [0, 0, 0, 0];
+ }
+
+ var margin = conf.margin;
+ conf.diagramArea = [margin[3], margin[0], conf.width - conf.legendWidth - margin[1], conf.height - margin[2]];
//设置x轴
- this.x = d3.scale.linear().domain([0, conf.xAxisData.length]).range([conf.margin, w]);
+ this.x = d3.scale.linear().domain([0, conf.xAxisData.length]).range([conf.diagramArea[0], conf.diagramArea[2]]);
//设置y轴
- this.value = d3.scale.linear().domain(conf.yExtent).range([h, conf.margin]);
+ this.value = d3.scale.linear().domain(conf.yExtent).range([conf.diagramArea[3], conf.diagramArea[1]]);
var xRange = this.x.range();
var valueRange = this.value.range();
var axis = this.axisPosition = {
@@ -187,7 +218,9 @@
var columnsMaxLen = _.max(this.columns, function (column) {
return column.length;
}).length;
- this.barWidth = (axis.right - axis.left - columnsMaxLen * conf.gap) / columnsMaxLen / _.keys(this.columns).length;
+ var width = conf.diagramArea[2] - conf.diagramArea[0];
+ var height = conf.diagramArea[3] - conf.diagramArea[1];
+ this.barWidth = width / columnsMaxLen / this.columnCount - conf.gap;
};
/**
@@ -202,18 +235,18 @@
var axisLines = paper.set();
var tickText = paper.set();
var axis = this.axisPosition;
- var ticks;
// X轴
- ticks = this.x.ticks(conf.xTickNumber);
- console.log(ticks);
- var range = this.x.range();
+ var ticks = this.x.ticks(conf.xTickNumber);
+ var formatLabel = conf.formatLabel || this.formatLabel;
// 修复显示不从第一个x轴单位显示的bug
for (j = 0; j < ticks.length; j++) {
// 修改x轴单位显示在所有Column组的中间位置
// 修复x轴单位对于柱位置的偏移
- var x = this.x(ticks[j]) + conf.gap / 2 + this.columnCount * Math.floor(this.barWidth) / 2;
- tickText.push(paper.text(x, axis.down + 14, conf.xAxisData[ticks[j]]).rotate(0, x, axis.up));
+ var x = this.x(ticks[j]) + conf.gap / 2 + this.columnCount * this.barWidth / 2;
+ var text = conf.xAxisData[ticks[j]];
+ tickText.push(paper.text(x, axis.down + 14, formatLabel(text)).rotate(0, x, axis.up));
+ // 画x轴刻度线
axisLines.push(paper.path("M" + x + "," + axis.down + "L" + x + "," + (axis.down + 5)));
}
@@ -224,6 +257,7 @@
"text-anchor": "middle"
});
+ // 绘制Y轴
axisLines.push(paper.path("M" + axis.left + "," + axis.up + "L" + axis.left + "," + axis.down));
axisLines.attr({
"stroke": "#D7D7D7",
@@ -231,8 +265,9 @@
});
//Y轴
ticks = this.value.ticks(conf.yTickNumber);
+ var formatYScale = conf.formatYScale || this.formatYScale;
for (j = 0; j < ticks.length; j++) {
- tickText.push(paper.text(axis.left - 8, this.value(ticks[j]), ticks[j]).attr({
+ tickText.push(paper.text(axis.left - 8, this.value(ticks[j]), formatYScale(ticks[j])).attr({
"fill": "#878791",
"fill-opacity": 0.7,
"font-size": 12,
@@ -254,7 +289,7 @@
}
hLines.attr({
"stroke": "#ECECEC",
- "stroke-width": 1
+ "stroke-width": 0.1
});
};
@@ -286,12 +321,17 @@
return that.clicked ? that.clickedColumnIndex === columnIndex : true;
});
currentSet.forEach(function (set, columnIndex) {
- set.animate({
- "fill-opacity": 0.3
- }, 10);
- set[xIndex].animate({
- "fill-opacity":1
- }, 10);
+ set.forEach(function (bar, index) {
+ if (index === xIndex) {
+ bar.stop().attr({
+ "fill-opacity": 1
+ });
+ } else {
+ bar.stop().animate({
+ "fill-opacity": 0.3
+ }, 100);
+ }
+ });
});
var hovered = currentSet.map(function (set) {
@@ -320,9 +360,10 @@
}
}
}
+ var formatValue = conf.formatValue || that.formatValue;
hovered.forEach(function (item, columnIndex) {
var yPos = y[columnIndex];
- var valueLabel = '' + values[columnIndex][xIndex][dim.value.index];
+ var valueLabel = '' + formatValue(values[columnIndex][xIndex][dim.value.index]);
var textWidth = 5 * valueLabel.length + 20;
var rect = paper.rect(xPos, yPos - 10, textWidth, 20, 2).attr({
@@ -334,7 +375,7 @@
"fill" : conf.barColor[columnIndex],
"stroke" : conf.barColor[columnIndex]
});
- var text = paper.text(xPos + 16, yPos, valueLabel).attr({
+ var text = paper.text(xPos + textWidth / 2, yPos, valueLabel).attr({
"fill": "#ffffff",
"fill-opacity": 1,
"font-weight": "bold",
@@ -347,7 +388,8 @@
xPos = hovered.reduce(function (pre, cur) {
return pre + cur.attrs.x;
}, 0) / hovered.length + barWidth / 2;
- var xLabel = '' + values[columnIndex][xIndex][dim.x.index];
+ var formatLabel = conf.formatLabel || this.formatLabel;
+ var xLabel = formatLabel(values[columnIndex][xIndex][dim.x.index]);
var textWidth = 6 * xLabel.length + 20;
//axis x rect
var rect = paper.rect(xPos - textWidth / 2, axis.down + 8, textWidth, 20, 2).attr({
@@ -364,9 +406,9 @@
"text-anchor": "middle"
});
var arrow = paper.path("M" + (xPos - 4) + "," + (axis.down + 8) + "L" + xPos + "," + axis.down +
- "L" + (xPos + 4) + "," + (axis.down + 8) + "H" + xPos + "Z").attr({
- "fill": "#5F5F5F",
- "stroke": "#5F5F5F"
+ "L" + (xPos + 4) + "," + (axis.down + 8) + "H" + xPos + "Z").attr({
+ "fill": "#5F5F5F",
+ "stroke": "#5F5F5F"
});
tagSet.push(rect, text, arrow);
};
@@ -377,11 +419,11 @@
var currentSet = columnSet.filter(function (set, columnIndex) {
return that.clicked ? that.clickedColumnIndex === columnIndex : true;
});
- tagSet.animate({"opacity": 0}, 1000, function () {
+ tagSet.stop().animate({"opacity": 0}, 300, function () {
tagSet.remove();
});
currentSet.forEach(function (set, columnIndex) {
- set.attr({"fill-opacity": 1});
+ set.stop().animate({"fill-opacity": 1}, 100);
});
};
@@ -397,8 +439,8 @@
"stroke": "none"
});
rect.data('column', index).data('index', i);
- rect.mouseover(mouseOverBar);
- rect.mouseout(mouseOutBar);
+ rect.mouseover(_.debounce(mouseOverBar, 300));
+ rect.mouseout(_.debounce(mouseOutBar, 300));
columnSet[index].push(rect);
});
});
@@ -496,12 +538,15 @@
* @param {Object} options options json object for determin column style.
*/
Column.prototype.render = function (options) {
+ var conf = this.defaults;
this.setOptions(options);
this.canvas.clear();
this.setAxis();
this.drawAxis();
this.drawDiagram();
- this.drawLegend();
+ if (conf.showLegend) {
+ this.drawLegend();
+ }
};
/*!
* 导出
diff --git a/package.json b/package.json
index 5c5de12..864cae6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "datavjs",
- "version": "0.0.1",
+ "version": "0.1.1",
"repository": {
"type": "git",
"url": "git://github.com/TBEDP/datavjs.git"
@@ -11,10 +11,12 @@
"author": "DataV",
"license": "MIT",
"description": "DataV.js is a JavaScript library for data visualization",
- "dependencies": {
- "uglify-js": "*"
+ "devDependencies": {
+ "uglify-js": "*",
+ "anywhere": "*"
},
"scripts": {
+ "start": "npm run build & anywhere 8888",
"build": "node bin/build.js"
},
"tracker": "UA-17170593-4"