diff --git a/spec/zoom-spec.js b/spec/zoom-spec.js index b5259bec0..887c00f55 100644 --- a/spec/zoom-spec.js +++ b/spec/zoom-spec.js @@ -4,30 +4,40 @@ */ /* eslint-disable */ /* global describe, beforeEach, it, expect */ +import CLASS from "../src/config/classes"; import util from "./assets/util"; describe("ZOOM", function() { - const chart = util.generate({ - data: { - columns: [ - ["data1", 30, 200, 100, 400, 3150, 250], - ["data2", 50, 20, 10, 40, 15, 6025] - ] - }, - axis: { - x: { - extent: [[1, 0], [2, 60]] - } - }, - zoom: { - enable: true - }, - subchart: { - show: true - } + let chart; + let args; + + beforeEach(() => { + chart = util.generate(args); }); describe("default extent", () => { + before(() => { + args = { + data: { + columns: [ + ["data1", 30, 200, 100, 400, 3150, 250], + ["data2", 50, 20, 10, 40, 15, 6025] + ] + }, + axis: { + x: { + extent: [[1, 0], [2, 60]] + } + }, + zoom: { + enable: true + }, + subchart: { + show: true + } + }; + }); + describe("main chart domain", () => { it("should have original y domain", () => { const yDomain = chart.internal.y.domain(); @@ -58,4 +68,66 @@ describe("ZOOM", function() { }); }); }); + + describe("zoom event", () => { + before(() => { + args = { + size: { + width: 300, + height: 250 + }, + data: { + columns: [ + ["data1", 30, 200, 100, 400, 3150, 250], + ["data2", 50, 20, 10, 40, 15, 6025] + ] + }, + zoom: { + enable: true + } + }; + }); + + it("check for data zoom", () => { + const main = chart.internal.main; + const xValue = +main.select(`.${CLASS.eventRect}-2`).attr("x"); + + // when + chart.zoom([0,3]); // zoom in + + expect(+main.select(`.${CLASS.eventRect}-2`).attr("x")).to.be.above(xValue); + }); + + it("check for x axis resize after zoom", () => { + const main = chart.internal.main; + const rx = /H(\d+)/; + + const domain = main.select(`.${CLASS.axisX} > .domain`); + const pathValue = +domain.attr("d").match(rx)[1]; + + chart.zoom([0,4]); + chart.resize({width:400}); + + expect(+domain.attr("d").match(rx)[1]).to.be.above(pathValue); + }); + + it("check for x axis resize after zoom in/out", () => { + const main = chart.internal.main; + const rx = /H(\d+)/; + + const domain = main.select(`.${CLASS.axisX} > .domain`); + const pathValue = +domain.attr("d").match(rx)[1]; + + chart.zoom([0,4]); // zoom in + chart.zoom([0,6]); // zoom out + + expect(+domain.attr("d").match(rx)[1]).to.be.equal(pathValue); + + // resize + chart.resize({width:400}); + + // check if chart react on resize + expect(+domain.attr("d").match(rx)[1]).to.be.above(pathValue); + }); + }); }); diff --git a/src/axis/Axis.js b/src/axis/Axis.js index db2237135..1bda99e7e 100644 --- a/src/axis/Axis.js +++ b/src/axis/Axis.js @@ -67,10 +67,11 @@ export default class Axis { tickWidth: config.axis_x_tick_width, tickTextRotate: withoutRotateTickText ? 0 : config.axis_x_tick_rotate, withoutTransition, + orgXScale: $$.x }; const axis = bbAxis(axisParams) - .scale(scale) + .scale($$.zoomScale || scale) .orient(orient); let newTickValues = tickValues; @@ -595,11 +596,12 @@ export default class Axis { redraw(transitions, isHidden) { const $$ = this.owner; + const opacity = isHidden ? "0" : "1"; - $$.axes.x.style("opacity", isHidden ? "0" : "1"); - $$.axes.y.style("opacity", isHidden ? "0" : "1"); - $$.axes.y2.style("opacity", isHidden ? "0" : "1"); - $$.axes.subx.style("opacity", isHidden ? "0" : "1"); + $$.axes.x.style("opacity", opacity); + $$.axes.y.style("opacity", opacity); + $$.axes.y2.style("opacity", opacity); + $$.axes.subx.style("opacity", opacity); transitions.axisX.call($$.xAxis); transitions.axisY.call($$.yAxis); diff --git a/src/axis/bb.axis.js b/src/axis/bb.axis.js index 5a4d898e7..2983f7f65 100644 --- a/src/axis/bb.axis.js +++ b/src/axis/bb.axis.js @@ -157,7 +157,9 @@ export default function(params = {}) { let tickX; let tickY; - const range = scale.rangeExtent ? scale.rangeExtent() : scaleExtent(scale.range()); + const range = scale.rangeExtent ? + scale.rangeExtent() : + scaleExtent((params.orgXScale || scale).range()); // update selection - data join const path = g.selectAll(".domain").data([0]); diff --git a/src/interactions/zoom.js b/src/interactions/zoom.js index 7275e8efd..c47ccf610 100644 --- a/src/interactions/zoom.js +++ b/src/interactions/zoom.js @@ -10,7 +10,7 @@ import { } from "d3"; import ChartInternal from "../internals/ChartInternal"; import CLASS from "../config/classes"; -import {extend, diffDomain} from "../internals/util"; +import {extend, diffDomain, isFunction} from "../internals/util"; extend(ChartInternal.prototype, { /** @@ -46,7 +46,8 @@ extend(ChartInternal.prototype, { $$.redrawEventRect(); $$.updateZoom(); - config.zoom_onzoomend.call($$.api, $$.x.orgDomain()); + + isFunction(config.zoom_onzoomend) && config.zoom_onzoomend.call($$.api, $$.x.orgDomain()); }); $$.zoom.orgScaleExtent = () => { @@ -60,6 +61,7 @@ extend(ChartInternal.prototype, { const extent = this.orgScaleExtent(); this.scaleExtent([extent[0] * ratio, extent[1] * ratio]); + return this; }; @@ -100,6 +102,18 @@ extend(ChartInternal.prototype, { // .call(z) // .on("dblclick.zoom", null); + if ($$.zoomScale) { + const range1 = $$.zoomScale.domain()[0]; + const range2 = $$.x.domain()[0]; + const delta = 0.015; + + // reset scale when zoom is out as initial + if (range1 <= range2 || (range1 - delta) <= range2) { + $$.zoomScale = null; + $$.xAxis.scale($$.x); + } + } + $$.main.select(`.${CLASS.eventRects}`) .call(z) .on("dblclick.zoom", null); @@ -116,6 +130,7 @@ extend(ChartInternal.prototype, { if (!config.zoom_enabled) { return; } + const zoom = $$.zoom; const x = $$.x; const event = d3Event; @@ -149,6 +164,6 @@ extend(ChartInternal.prototype, { $$.cancelClick = true; } - config.zoom_onzoom.call($$.api, x.orgDomain()); + isFunction(config.zoom_onzoom) && config.zoom_onzoom.call($$.api, x.orgDomain()); }, }); diff --git a/src/internals/ChartInternal.js b/src/internals/ChartInternal.js index 66117fef4..77b7d0cbd 100644 --- a/src/internals/ChartInternal.js +++ b/src/internals/ChartInternal.js @@ -568,6 +568,7 @@ export default class ChartInternal { if (targetsToShow.length) { $$.updateXDomain(targetsToShow, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain); + if (!config.axis_x_tick_values) { tickValues = $$.axis.updateXAxisTickValues(targetsToShow); } @@ -904,11 +905,15 @@ export default class ChartInternal { } xx(d) { - if (this.config.zoom_enabled && this.zoomScale) { - return d ? this.zoomScale(d.x) : null; - } else { - return d ? this.x(d.x) : null; + const x = d ? d.x : null; + let scale = null; + + if (x) { + scale = this.config.zoom_enabled && this.zoomScale ? + this.zoomScale(x) : this.x(x); } + + return scale; } xv(d) { @@ -1134,26 +1139,6 @@ export default class ChartInternal { }); addEvent(window, "resize", $$.resizeFunction); - - // if (window.attachEvent) { - // window.attachEvent("onresize", $$.resizeFunction); - // } else if (window.addEventListener) { - // window.addEventListener("resize", $$.resizeFunction, false); - // } else { - // // fallback to this, if this is a very old browser - // let wrapper = window.onresize; - // if (!wrapper) { - // // create a wrapper that will call all charts - // wrapper = $$.generateResize(); - // } else if (!wrapper.add || !wrapper.remove) { - // // there is already a handler registered, make sure we call it too - // wrapper = $$.generateResize(); - // wrapper.add(window.onresize); - // } - // // add this graph to the wrapper, we will be removed if the user calls destroy - // wrapper.add($$.resizeFunction); - // window.onresize = wrapper; - // } } generateResize() { diff --git a/src/internals/legend.js b/src/internals/legend.js index bc75754a9..4ba8856b2 100644 --- a/src/internals/legend.js +++ b/src/internals/legend.js @@ -511,5 +511,5 @@ extend(ChartInternal.prototype, { // Update g positions $$.transformAll(withTransitionForTransform, transitions); $$.legendHasRendered = true; - }, + } });