jui.define("chart.brush.flame", [ "util.base", "util.color", "chart.brush.treemap.nodemanager" ],
function(_, ColorUtil, NodeManager) {
var TEXT_MARGIN = 3;
/**
* @class chart.brush.flame
*
* @extends chart.brush.core
*/
var FlameBrush = function() {
var self = this,
g = null,
height = 0,
maxHeight = 0,
nodes = new NodeManager(),
disableOpacity = 1,
newData = [],
activeDepth = null;
function getNodeAndTextOpacity(depth) {
return (activeDepth == null) ? 1 : (depth < activeDepth) ? disableOpacity : 1;
}
function createNodeElement(node, color) {
var newColor = self.chart.color(color);
var r = self.svg.rect({
fill: newColor,
"fill-opacity": getNodeAndTextOpacity(node.depth),
stroke: self.chart.theme("flameNodeBorderColor"),
"stroke-width": self.chart.theme("flameNodeBorderWidth"),
width: node.width,
height: node.height,
x: node.x,
y: node.y,
cursor: "pointer"
});
// 마우스 오버 효과
r.hover(function() {
r.attr({ stroke: newColor });
}, function() {
r.attr({ stroke: self.chart.theme("flameNodeBorderColor") });
});
// 노드 공통 이벤트 설정
self.addEvent(r, node);
// 노드 엘리먼트 캐싱
node.element = {
rect: r
};
return r;
}
function createTextElement(node, color) {
if(!_.typeCheck("function", self.brush.format)) {
return null;
}
var newColor = self.chart.color(color),
fontSize = self.chart.theme("flameTextFontSize"),
startX = node.x;
if(self.brush.textAlign == "middle") {
startX += node.width / 2;
} else if(self.brush.textAlign == "end") {
startX += node.width - TEXT_MARGIN;
} else {
startX += TEXT_MARGIN;
}
var t = self.chart.text({
"font-size": fontSize,
"font-weight": "bold",
fill: self.chart.theme("flameTextFontColor"),
"fill-opacity": getNodeAndTextOpacity(node.depth),
x: startX,
y: node.y + (fontSize / 3) + (height / 2),
"text-anchor": self.brush.textAlign,
cursor: "pointer"
}, self.format(node));
// 마우스 오버 효과
t.hover(function() {
node.element.rect.attr({ stroke: newColor });
}, function() {
node.element.rect.attr({ stroke: self.chart.theme("flameNodeBorderColor") });
});
// 노드 공통 이벤트 설정
self.addEvent(t, node);
// 노드 엘리먼트 캐싱
node.element.text = t;
return t;
}
function drawNodeAll(g, node, width, sx) {
var color = self.color(0);
node.width = width;
node.height = height;
node.x = sx;
// 노드 그리는 위치 설정
if(self.brush.nodeOrient == "bottom") {
node.y = maxHeight - (height * node.depth);
} else {
node.y = height * node.depth;
}
// 노드 컬러 설정
if(_.typeCheck("function", self.brush.nodeColor)) {
color = self.brush.nodeColor.call(self.chart, node);
}
var r = createNodeElement(node, color),
t = createTextElement(node, color);
if(self.brush.nodeAlign == "start") {
var cStartX = node.x;
for (var i = 0; i < node.children.length; i++) {
var cNode = node.children[i],
cRate = cNode.value / node.value,
cWidth = node.width * cRate;
drawNodeAll(g, cNode, cWidth, cStartX);
cStartX += cWidth;
}
} else {
var cStartX = node.x + node.width;
for(var i = node.children.length - 1; i >= 0; i--) {
var cNode = node.children[i],
cRate = cNode.value / node.value,
cWidth = node.width * cRate;
cStartX -= cWidth;
drawNodeAll(g, cNode, cWidth, cStartX);
}
}
g.append(r);
if(t != null) {
g.append(t);
}
}
function getMaxDepth(nodes) {
var maxDepth = 0;
for(var i = 0; i < nodes.length; i++) {
maxDepth = Math.max(maxDepth, nodes[i].depth);
}
return maxDepth;
}
function createFilteredNodes(activeNode) {
setCacheParents(activeNode, activeNode.value);
setCacheChildren(activeNode);
sortingCacheNodes();
var tmpData = createIndexData(activeNode),
tmpNodes = new NodeManager();
for(var i = 0; i < tmpData.length; i++) {
var d = tmpData[i];
tmpNodes.insertNode(d.index, {
text: d.text,
value: d.value,
x: 0,
y: 0,
width: 0,
height: 0
});
}
// 필터링 된 노드 캐싱
self.axis.cacheNodes = tmpNodes;
return tmpNodes.getNode()[0];
}
function setCacheParents(node, value) {
if(node.depth > 0) {
node.value = value;
newData.push(node);
if(node.parent) {
setCacheParents(node.parent, value);
}
}
}
function setCacheChildren(node) {
for(var i = 0; i < node.children.length; i++) {
var cNode = node.children[i];
newData.push(cNode);
if(cNode.children.length > 0) {
setCacheChildren(cNode);
}
}
}
function sortingCacheNodes() {
var qs = _.sort(newData);
qs.setCompare(function(a, b) {
return (a.depth < b.depth) ? true : false;
});
qs.run();
}
function createIndexData(node) {
var tmpData = [], index = "";
for(var i = 0; i < newData.length; i++) {
if(index == "") {
index = "0";
} else {
index += ".0";
}
if(newData[i].depth < node.depth) {
tmpData.push({
index: index,
text: newData[i].text,
value: newData[i].value
});
} else {
createChildIndexData(node, index, tmpData);
break;
}
}
return tmpData;
}
function createChildIndexData(node, index, result) {
result.push({
index: index,
value: node.value,
text: node.text
});
for(var i = 0; i < node.children.length; i++) {
var cNode = node.children[i];
createChildIndexData(cNode, index + "." + i, result);
}
}
this.drawBefore = function() {
g = this.svg.group();
for (var i = 0; i < this.axis.data.length; i++) {
var d = this.axis.data[i],
k = this.getValue(d, "index");
nodes.insertNode(k, {
text: "" + this.getValue(d, "text", ""),
value: this.getValue(d, "value", 0),
x: this.getValue(d, "x", 0),
y: this.getValue(d, "y", 0),
width: this.getValue(d, "width", 0),
height: this.getValue(d, "height", 0)
});
}
var maxDepth = (this.brush.maxDepth == null) ? getMaxDepth(nodes.getNodeAll()) : this.brush.maxDepth;
height = this.axis.area("height") / maxDepth;
maxHeight = this.axis.area("height");
// 비활성화 노드 투명도
disableOpacity = this.chart.theme("flameDisableBackgroundOpacity");
}
this.draw = function() {
var area = this.axis.area(),
root = nodes.getNode()[0],
activeIndex = this.brush.activeIndex;
if(root) {
// 액티브 노드가 있을 경우, 노드 재정의
if(_.typeCheck("string", activeIndex)) {
var activeNode = nodes.getNode(activeIndex);
if(activeNode == null) {
activeNode = this.axis.cacheNodes.getNode(activeIndex);
}
root = createFilteredNodes(activeNode);
activeDepth = activeNode.depth;
}
drawNodeAll(g, root, area.width, area.x);
}
return g;
}
}
FlameBrush.setup = function() {
return {
maxDepth: null,
nodeOrient: "bottom",
nodeAlign: "end",
textAlign: "start",
nodeColor: null,
activeIndex: null,
clip: false,
format: null
};
}
return FlameBrush;
}, "chart.brush.core");