UNPKG

juijs-chart

Version:

SVG-based JUI chart that can be used in the browser and Node.js. Support many types of charts. (Dashboard, Map, Topology, Full 3D)

295 lines (247 loc) 10.8 kB
import jui from "../main.js"; import AreaBrush from '../brush/area.js'; jui.use(AreaBrush); export default { name: "chart.widget.zoomscroll", extend: "chart.widget.core", component: function() { var _ = jui.include("util.base"); var builder = jui.include("chart.builder"); var ZoomScrollWidget = function() { var self = this, axis = null; var w = null, // width h = null, // height b = null, // area border width size = 0, // button size radius = null, // button round tick = 0, start = null, end = null, count = null; var l_rect = null, l_ctrl = null, r_rect = null, r_ctrl = null, c_rect = null; function setDragEvent(bg, ctrl, isLeft) { var isMove = false, isCenter = false, mouseStart = 0, centerStart = 0, bgWidth = 0; ctrl.on("mousedown", function(e) { if(isMove) return; isCenter = (bg == null) ? true : false; isMove = true; if(isCenter) { bgWidth = ctrl.size().width; centerStart = l_rect.size().width; mouseStart = e.clientX; } else { bgWidth = bg.size().width; mouseStart = e.clientX; } // 커스텀 이벤트 발생 self.chart.emit("zoomscroll.dragstart"); }); self.on("chart.mousemove", dragZoomAction); self.on("bg.mousemove", dragZoomAction); self.on("chart.mouseup", endZoomAction); self.on("bg.mouseup", endZoomAction); function dragZoomAction(e) { if(!isMove) return; var dis = e.clientX - mouseStart; if(isCenter) { var tw = centerStart + dis, rw = tw + bgWidth, val = Math.floor(tw / tick) - start; if(tw > 0 && tw + bgWidth < w) { l_rect.round(tw, h, radius, 0, 0, radius); l_ctrl.attr({ x: tw - size / 2 }); r_rect.round(w - rw, h, 0, radius, radius, 0); r_rect.translate(rw, 0); r_ctrl.attr({ x: rw - size / 2 }); c_rect.translate(tw, 0); start += val; end += val; } } else { if(isLeft) { var tw = bgWidth + dis; if(tw < 0) return; if(!preventDragAction(tw) && dis > 0) return; bg.round(tw, h, radius, 0, 0, radius); ctrl.attr({ x: tw - size/2 }); // 가운데 영역 c_rect.attr({ width: w - l_rect.size().width - r_rect.size().width }); c_rect.translate(tw, 0); start = Math.floor(tw / tick); } else { var tw = bgWidth - dis; if(tw < 0) return; if(!preventDragAction(tw) && dis < 0) return; bg.round(tw, h, 0, radius, radius, 0); bg.translate(w - tw, 0); ctrl.attr({ x: w - tw - size/2 }); // 가운데 영역 c_rect.attr({ width: w - l_rect.size().width - r_rect.size().width }); end = count - Math.floor(tw / tick); } } } function endZoomAction() { if(!isMove) return; isMove = false; var axes = self.chart.axis(); // 차트 렌더링 이전에 커스텀 이벤트 발생 self.chart.emit("zoomscroll.dragend", [ start, end - 1 ]); for(var i = 0; i < axes.length; i++) { axes[i].zoom(start, end); } // 차트 렌더링이 활성화되지 않았을 경우 if(!self.chart.isRender()) { self.chart.render(); } // 차트 렌더링 이후에 커스텀 이벤트 발생 self.chart.emit("zoomscroll.render", [ start, end - 1 ]); } function preventDragAction() { var t = r_rect.data("translate"), l = l_rect.size().width, r = parseInt(t.split(",")[0]), max = r - tick/2; // 좌/우 버튼 교차 방지 if (l < max) { return true; } return false; } } function createChartImage() { var size = self.chart.theme("zoomScrollGridFontSize"); var image = builder(null, { width: w, height: h, padding: { top: 0, left: 0, right: 0, bottom: size + 8 }, axis: { x: _.extend({ hide: false, line: "solid", format: self.widget.format }, axis.get("x"), true), y: _.extend({ hide: true, line: false }, axis.get("y"), true), data: axis.origin }, brush: [{ type: self.widget.symbol, target: [ self.widget.key ], colors: [ self.widget.color ] }], style: { backgroundColor: "transparent", gridXFontSize : size, gridTickPadding : self.chart.theme("zoomScrollGridTickPadding"), areaBackgroundOpacity: self.chart.theme("zoomScrollBrushAreaBackgroundOpacity"), lineBorderWidth: self.chart.theme("zoomScrollBrushLineBorderWidth") } }); return "data:image/svg+xml;utf8," + encodeURIComponent(image.svg.toXML()); } this.drawBefore = function() { axis = this.chart.axis(this.widget.axis); count = axis.origin.length; start = axis.start; end = axis.end; b = this.chart.theme("zoomScrollAreaBorderWidth"); w = this.chart.area("width") - b*2; h = this.chart.theme("zoomScrollBackgroundSize") - b*2; size = this.chart.theme("zoomScrollButtonSize"); radius = this.chart.theme("zoomScrollAreaBorderRadius"); tick = w / count; } this.draw = function() { var areaStyle = { fill: this.chart.theme("zoomScrollAreaBackgroundColor"), "fill-opacity": this.chart.theme("zoomScrollAreaBackgroundOpacity"), stroke: this.chart.theme("zoomScrollAreaBorderColor"), "stroke-width": b }; return this.svg.group({}, function() { var lw = start * tick, rw = (count - end) * tick; if(isNaN(lw) || isNaN(rw)) { return; } self.svg.image({ width: w, height: h, "xlink:href": createChartImage() }); l_rect = self.svg.pathRect(areaStyle); l_rect.round(lw, h, radius, 0, 0, radius); r_rect = self.svg.pathRect(areaStyle); r_rect.round(rw, h, 0, radius, radius, 0); r_rect.translate(w - rw, 0); c_rect = self.svg.rect({ width: w - lw - rw, height: h, fill: "transparent", "fill-opacity": 0, stroke: self.chart.color(self.widget.color), "stroke-width": b, cursor: "move" }).translate(lw, 0); l_ctrl = self.svg.rect({ x: lw - size/2, y: h / 2 - size/2, width: size, height: size, fill:"#e0e0e0", cursor: "e-resize", rx:size/2, "stroke-linecap":"round", "stroke":"#616161" }); r_ctrl = self.svg.rect({ x: w - rw - size/2, y: h / 2 - size/2, width: size, height: size, fill:"#e0e0e0", cursor: "e-resize", rx:size/2, "stroke-linecap":"round", "stroke":"#616161" }); setDragEvent(l_rect, l_ctrl, true); setDragEvent(r_rect, r_ctrl, false); setDragEvent(null, c_rect); }).translate( this.widget.dx + this.chart.area("x"), this.widget.dy + this.chart.area("y2") - b ); } } ZoomScrollWidget.setup = function() { return { symbol : "area", key : null, color : 0, format : null, axis : 0, dx : 0, dy : 0 } } return ZoomScrollWidget; } }