jui.define("chart.widget.zoom", [ "util.base" ], function(_) { /** * @class chart.widget.zoom * @extends chart.widget.core * @alias ZoomWidget * @requires util.base */ var ZoomWidget = function() { var self = this, top = 0, left = 0; function setDragEvent(axisIndex, thumb, bg) { var axis = self.chart.axis(axisIndex), xtype = axis.get("x").type, startDate = null, // only date isMove = false, mouseStart = 0, thumbWidth = 0; self.on("axis.mousedown", function(e) { if(isMove) return; isMove = true; mouseStart = e.bgX; if(xtype == "date") { // x축이 date일 때 startDate = axis.x.invert(e.chartX); } self.chart.emit("zoom.start"); }, axisIndex); self.on("axis.mousemove", function(e) { if(!isMove) return; thumbWidth = e.bgX - mouseStart; if(thumbWidth > 0) { thumb.attr({ width: thumbWidth }); thumb.translate(mouseStart, top + axis.area("y")); } else { thumb.attr({ width: Math.abs(thumbWidth) }); thumb.translate(mouseStart + thumbWidth, top + axis.area("y")); } }, axisIndex); self.on("axis.mouseup", endZoomAction, axisIndex); self.on("chart.mouseup", endZoomAction); self.on("bg.mouseup", endZoomAction); self.on("bg.mouseout", endZoomAction); function endZoomAction(e) { var args = []; isMove = false; if(thumbWidth == 0) return; if(xtype == "block") { args = updateBlockGrid(); } else if(xtype == "date") { if(startDate != null) { args = updateDateGrid(axis.x.invert(e.chartX)); } } resetDragStatus(); self.chart.emit("zoom.end", args); } function updateBlockGrid() { var tick = axis.area("width") / (axis.end - axis.start), x = ((thumbWidth > 0) ? mouseStart : mouseStart + thumbWidth) - left, start = Math.floor(x / tick) + axis.start, end = Math.ceil((x + Math.abs(thumbWidth)) / tick) + axis.start; // 차트 줌 if(start < end) { axis.zoom(start, end); bg.attr({ "visibility": "visible" }); // 차트 렌더링이 활성화되지 않았을 경우 if(!self.chart.isRender()) { self.chart.render(); } return [ start, end ]; } } function updateDateGrid(endDate) { var stime = startDate.getTime(), etime = endDate.getTime(); if(stime >= etime) return; var interval = self.widget.interval, format = self.widget.format; // interval 콜백 옵션 설정 if(_.typeCheck("function", interval)) { interval = interval.apply(self.chart, [ stime, etime ]); } // format 콜백 옵션 설정 if(_.typeCheck("function", format)) { format = format.apply(self.chart, [ stime, etime ]); } axis.updateGrid("x", { domain: [ stime, etime ], interval: (interval != null) ? interval : axis.get("x").interval, format: (format != null) ? format : axis.get("x").format }); bg.attr({ "visibility": "visible" }); // 차트 렌더링이 활성화되지 않았을 경우 if(!self.chart.isRender()) { self.chart.render(); } return [ stime, etime ]; } function resetDragStatus() { // 엘리먼트 및 데이터 초기화 isMove = false; mouseStart = 0; thumbWidth = 0; startDate = null; thumb.attr({ width: 0 }); } } this.drawSection = function(axisIndex) { var axis = this.chart.axis(axisIndex), xtype = axis.get("x").type, domain = axis.get("x").domain, interval = axis.get("x").interval, format = axis.get("x").format, cw = axis.area("width"), ch = axis.area("height"), r = 12; return this.chart.svg.group({}, function() { var thumb = self.chart.svg.rect({ height: ch, fill: self.chart.theme("zoomBackgroundColor"), opacity: 0.3 }); var bg = self.chart.svg.group({ visibility: "hidden" }, function() { self.chart.svg.rect({ width: cw, height: ch, fill: self.chart.theme("zoomFocusColor"), opacity: 0.2 }); self.chart.svg.group({ cursor: "pointer" }, function() { self.chart.svg.circle({ r: r, cx: cw, cy: 0, opacity: 0 }); self.chart.svg.path({ d: "M12,2C6.5,2,2,6.5,2,12c0,5.5,4.5,10,10,10s10-4.5,10-10C22,6.5,17.5,2,12,2z M16.9,15.5l-1.4,1.4L12,13.4l-3.5,3.5 l-1.4-1.4l3.5-3.5L7.1,8.5l1.4-1.4l3.5,3.5l3.5-3.5l1.4,1.4L13.4,12L16.9,15.5z", fill: self.chart.theme("zoomFocusColor") }).translate(cw - r, -r); }).on("click", function(e) { bg.attr({ visibility: "hidden" }); if(xtype == "block") { axis.screen(1); } else if(xtype == "date") { axis.updateGrid("x", { domain: domain, interval: interval, format: format }); } // 차트 렌더링이 활성화되지 않았을 경우 if(!self.chart.isRender()) { self.chart.render(); } // 줌 종료 self.chart.emit("zoom.close"); }); }).translate(left + axis.area("x"), top + axis.area("y")); setDragEvent(axisIndex, thumb, bg); }); } this.drawBefore = function() { top = this.chart.padding("top"); left = this.chart.padding("left"); } this.draw = function() { var g = this.chart.svg.group(), list = (_.typeCheck("array", this.widget.axis)) ? this.widget.axis : [ this.widget.axis ]; for (var i = 0; i < list.length; i++) { g.append(this.drawSection(list[i])); } return g; } } ZoomWidget.setup = function() { return { axis: 0, /** @cfg {Number} [interval=1000] Sets the interval of the scale displayed on a grid.*/ interval: null, /** @cfg {Function} [format=null] Determines whether to format the value on an axis. */ format: null } } return ZoomWidget; }, "chart.widget.core");