jui.define("chart.grid.radar", [ "util.math", "util.base" ], function(math, _) {
/**
* @class chart.grid.radar
* @extends chart.grid.core
*/
var RadarGrid = function() {
var self = this,
position = [];
function drawCircle(root, centerX, centerY, x, y, count) {
var r = Math.abs(y),
cx = centerX,
cy = centerY;
root.append(self.chart.svg.circle({
cx : cx,
cy : cy,
r : r,
"fill-opacity" : 0,
stroke : self.color("gridBorderColor"),
"stroke-width" : self.chart.theme("gridBorderWidth")
}));
}
function drawRadial(root, centerX, centerY, x, y, count, unit) {
var g = self.chart.svg.group();
var points = [];
points.push([centerX + x, centerY + y]);
var startX = x,
startY = y;
for (var i = 0; i < count; i++) {
var obj = math.rotate(startX, startY, unit);
startX = obj.x;
startY = obj.y;
points.push([centerX + obj.x, centerY + obj.y]);
}
var path = self.chart.svg.path({
"fill" : "none",
stroke : self.color("gridBorderColor"),
"stroke-width" : self.chart.theme("gridBorderWidth")
});
for (var i = 0; i < points.length; i++) {
var point = points[i];
if (i == 0) {
path.MoveTo(point[0], point[1])
} else {
path.LineTo(point[0], point[1]);
}
}
path.LineTo(points[0][0], points[0][1]);
//path.ClosePath();
g.append(path);
root.append(g);
}
function scale(obj) {
var max = self.grid.max;
var dx = self.chart.padding('left');
var dy = self.chart.padding('top');
return function(index, value) {
var rate = value / max;
var height = Math.abs(obj.y1) - Math.abs(obj.y2),
pos = height * rate,
unit = 2 * Math.PI / self.domain.length;
var cx = obj.x1,
cy = obj.y1,
y = -pos,
x = 0;
var o = math.rotate(x, y, unit * index);
var result = {
x : dx + cx + o.x,
y : dy + cy + o.y
}
return result;
}
}
this.initDomain = function() {
var domain = [];
if (_.typeCheck("string", this.grid.domain)) {
var field = this.grid.domain;
var data = this.data();
if (this.grid.reverse) {
var start = data.length - 1,
end = 0,
step = -1;
} else {
var start = 0,
end = data.length - 1,
step = 1;
}
for (var i = start; ((this.grid.reverse) ? i >= end : i <=end); i += step) {
domain.push(data[i][field]);
}
//grid.domain = domain;
} else if (_.typeCheck("function", this.grid.domain)) { // block 은 배열을 통째로 리턴함
domain = this.grid.domain(this.chart, this.grid);
} else {
domain = this.grid.domain;
}
if (this.grid.reverse) {
domain.reverse();
}
return domain;
}
this.drawBefore = function() {
this.domain = this.initDomain();
}
this.draw = function() {
var width = this.axis.area('width'), height = this.axis.area('height');
var min = width;
if (height < min) {
min = height;
}
// center
var w = min / 2,
centerX = this.axis.area('x') + width / 2,
centerY = this.axis.area('y') + height / 2;
var startY = -w,
startX = 0,
count = this.domain.length,
step = this.grid.step,
unit = 2 * Math.PI / count,
h = Math.abs(startY) / step;
var g = this.chart.svg.group(),
root = this.chart.svg.group();
g.append(root);
// domain line
position = [];
for (var i = 0; i < count; i++) {
var x2 = centerX + startX,
y2 = centerY + startY;
root.append(this.chart.svg.line({
x1 : centerX,
y1 : centerY,
x2 : x2,
y2 : y2,
stroke : this.color("gridAxisBorderColor"),
"stroke-width" : this.chart.theme("gridBorderWidth")
}));
position[i] = {
x1 : centerX,
y1 : centerY,
x2 : x2,
y2 : y2
};
var ty = y2,
tx = x2,
talign = "middle";
if (y2 > centerY) {
ty = y2 + 20;
} else if (y2 < centerY) {
ty = y2 - 10;
}
if (x2 > centerX) {
talign = "start";
tx += 10;
} else if (x2 < centerX) {
talign = "end";
tx -= 10;
}
if (!this.grid.hideText) {
root.append(this.chart.text({
x : tx,
y : ty,
"text-anchor" : talign,
"font-size" : this.chart.theme("gridCFontSize"),
"font-weight" : this.chart.theme("gridCFontWeight"),
fill : this.chart.theme("gridCFontColor")
}, this.domain[i]))
}
var obj = math.rotate(startX, startY, unit);
startX = obj.x;
startY = obj.y;
}
if (!this.grid.line) {
return {
root : root ,
scale : scale(position[0])
};
}
// area split line
startY = -w;
var stepBase = 0,
stepValue = this.grid.max / this.grid.step;
for (var i = 0; i < step; i++) {
if (i == 0 && this.grid.extra) {
startY += h;
continue;
}
if (this.grid.shape == "circle") {
drawCircle(root, centerX, centerY, 0, startY, count);
} else {
drawRadial(root, centerX, centerY, 0, startY, count, unit);
}
if (!this.grid.hideText) {
root.append(this.chart.text({
x : centerX,
y : centerY + (startY + h - 5),
"font-size" : this.chart.theme("gridCFontSize"),
"font-weight" : this.chart.theme("gridCFontWeight"),
fill : this.chart.theme("gridCFontColor")
}, (this.grid.max - stepBase) + ""))
}
startY += h;
stepBase += stepValue;
}
// hide
if (this.grid.hide) {
root.attr({ display : "none" })
}
return {
root : root,
scale : scale(position[0])
};
}
}
RadarGrid.setup = function() {
return {
/** @cfg {String/Array/Function} [domain=null] Sets the value displayed on an axis.*/
domain: null,
/** @cfg {Boolean} [reverse=false] Reverses the value on domain values*/
reverse: false,
/** @cfg {Number} [max=null] Sets the maximum value of a grid. */
max: 100,
/** @cfg {Array} [step=10] Sets the interval of the scale displayed on a grid. */
step : 10,
/** @cfg {Boolean} [line=true] Determines whether to display a line on the axis background. */
line: true,
/** @cfg {Boolean} [hideText=false] Determines whether to show text across the grid. */
hideText: false,
extra: false,
/** @cfg {"radial"/"circle"} [shape="radial"] Determines the shape of a grid (radial, circle). */
shape: "radial" // or circle
};
}
return RadarGrid;
}, "chart.grid.core");