diff --git a/samples/zoom.html b/samples/zoom.html
new file mode 100644
index 000000000..695463103
--- /dev/null
+++ b/samples/zoom.html
@@ -0,0 +1,232 @@
+
+
+
+
+ Scatter Chart
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/core/core.scale.js b/src/core/core.scale.js
index 24881e128..45b36dd91 100644
--- a/src/core/core.scale.js
+++ b/src/core/core.scale.js
@@ -393,6 +393,9 @@ module.exports = function(Chart) {
// Used to get data value locations. Value can either be an index or a numerical value
getPixelForValue: helpers.noop,
+ // Used to get the data value from a given pixel. This is the inverse of getPixelForValue
+ getValueForPixel: helpers.noop,
+
// Used for tick location, should
getPixelForTick: function(index, includeOffset) {
if (this.isHorizontal()) {
diff --git a/src/scales/scale.linear.js b/src/scales/scale.linear.js
index 3cf2b020d..868d6581c 100644
--- a/src/scales/scale.linear.js
+++ b/src/scales/scale.linear.js
@@ -250,6 +250,19 @@ module.exports = function(Chart) {
return Math.round(pixel);
}
},
+ getValueForPixel: function(pixel) {
+ var offset;
+
+ if (this.isHorizontal()) {
+ var innerWidth = this.width - (this.paddingLeft + this.paddingRight);
+ offset = (pixel - this.left - this.paddingLeft) / innerWidth;
+ } else {
+ var innerHeight = this.height - (this.paddingTop + this.paddingBottom);
+ offset = (this.bottom - this.paddingBottom - pixel) / innerHeight;
+ }
+
+ return this.min + ((this.max - this.min) * offset);
+ },
getPixelForTick: function(index, includeOffset) {
return this.getPixelForValue(this.ticksAsNumbers[index], null, null, includeOffset);
}
diff --git a/src/scales/scale.logarithmic.js b/src/scales/scale.logarithmic.js
index 070a08d61..7476765db 100644
--- a/src/scales/scale.logarithmic.js
+++ b/src/scales/scale.logarithmic.js
@@ -187,6 +187,16 @@ module.exports = function(Chart) {
}
return pixel;
+ },
+ getValueForPixel: function(pixel) {
+ var offset;
+
+ if (this.isHorizontal) {
+ var innerWidth = this.width - (this.paddingLeft + this.paddingRight);
+ } else {
+ var innerHeight = this.height - (this.paddingTop + this.paddingBottom);
+ }
+
}
});
diff --git a/src/scales/scale.time.js b/src/scales/scale.time.js
index 2dbb4ba6d..47d1fa09c 100644
--- a/src/scales/scale.time.js
+++ b/src/scales/scale.time.js
@@ -316,6 +316,11 @@ module.exports = function(Chart) {
}
}
},
+ getValueForPixel: function(pixel) {
+ var offset = pixel - (this.isHorizontal() ? this.left + this.paddingLeft : this.top + this.paddingTop);
+ offset *= this.scaleSizeInUnits;
+ return this.firstTick.clone().add(offset, this.tickUnit);
+ },
parseTime: function(label) {
if (typeof this.options.time.parser === 'string') {
return moment(label, this.options.time.parser);
diff --git a/test/scale.linear.tests.js b/test/scale.linear.tests.js
index 3236949b1..59af5968f 100644
--- a/test/scale.linear.tests.js
+++ b/test/scale.linear.tests.js
@@ -778,8 +778,13 @@ describe('Linear Scale', function() {
verticalScale.height = 110;
expect(verticalScale.getPixelForValue(1, 0, 0)).toBe(5); // top + paddingTop
+ expect(verticalScale.getValueForPixel(5)).toBe(1);
+
expect(verticalScale.getPixelForValue(-1, 0, 0)).toBe(105); // bottom - paddingBottom
+ expect(verticalScale.getValueForPixel(105)).toBe(-1);
+
expect(verticalScale.getPixelForValue(0, 0, 0)).toBe(55); // halfway
+ expect(verticalScale.getValueForPixel(55)).toBe(0);
var horizontalConfig = Chart.helpers.clone(config);
horizontalConfig.position = 'bottom';
@@ -806,8 +811,13 @@ describe('Linear Scale', function() {
// Range expands to [-2, 2] due to nicenum algorithm
expect(horizontalScale.getPixelForValue(2, 0, 0)).toBe(105); // right - paddingRight
+ expect(horizontalScale.getValueForPixel(105)).toBe(2);
+
expect(horizontalScale.getPixelForValue(-2, 0, 0)).toBe(5); // left + paddingLeft
+ expect(horizontalScale.getValueForPixel(5)).toBe(-2);
+
expect(horizontalScale.getPixelForValue(0, 0, 0)).toBe(55); // halfway
+ expect(horizontalScale.getValueForPixel(55)).toBe(0);
});
it('should fit correctly', function() {
diff --git a/test/scale.logarithmic.tests.js b/test/scale.logarithmic.tests.js
index a75f174e1..f49865a94 100644
--- a/test/scale.logarithmic.tests.js
+++ b/test/scale.logarithmic.tests.js
@@ -595,8 +595,14 @@ describe('Logarithmic Scale tests', function() {
verticalScale.height = 110;
expect(verticalScale.getPixelForValue(80, 0, 0)).toBe(5); // top + paddingTop
+ expect(verticalScale.getValueForPixel(5)).toBeCloseTo(80, 1e-4);
+
expect(verticalScale.getPixelForValue(1, 0, 0)).toBe(105); // bottom - paddingBottom
+ expect(verticalScale.getValueForPixel(105)).toBeCloseTo(1, 1e-4);
+
expect(verticalScale.getPixelForValue(10, 0, 0)).toBeCloseTo(52.4, 1e-4); // halfway
+ expect(verticalScale.getValueForPixel(52.4)).toBeCloseTo(10, 1e-4);
+
expect(verticalScale.getPixelForValue(0, 0, 0)).toBe(5); // 0 is invalid. force it on top
var horizontalConfig = Chart.helpers.clone(config);
@@ -623,8 +629,14 @@ describe('Logarithmic Scale tests', function() {
horizontalScale.height = 50;
expect(horizontalScale.getPixelForValue(80, 0, 0)).toBe(105); // right - paddingRight
+ expect(horizontalScale.getValueForPixel(105)).toBeCloseTo(80, 1e-4);
+
expect(horizontalScale.getPixelForValue(1, 0, 0)).toBe(5); // left + paddingLeft
+ expect(horizontalScale.getValueForPixel(5)).toBeCloseTo(1, 1e-4);
+
expect(horizontalScale.getPixelForValue(10, 0, 0)).toBeCloseTo(57.5, 1e-4); // halfway
+ expect(horizontalScale.getValueForPixel(57.5)).toBeCloseTo(10, 1e-4);
+
expect(horizontalScale.getPixelForValue(0, 0, 0)).toBe(5); // 0 is invalid, put it on the left.
});
});
diff --git a/test/scale.time.tests.js b/test/scale.time.tests.js
index c35b4cea3..722354d59 100644
--- a/test/scale.time.tests.js
+++ b/test/scale.time.tests.js
@@ -337,7 +337,10 @@ describe('Time scale tests', function() {
scale.bottom = 38;
expect(scale.getPixelForValue('', 0, 0)).toBe(81);
+ expect(scale.getValueForPixel(81)).toEqual(scale.firstTick);
+
expect(scale.getPixelForValue('', 6, 0)).toBe(323);
+ expect(scale.getValueForPixel(323)).toEqual(scale.lastTick);
var verticalScaleConfig = Chart.helpers.clone(Chart.scaleService.getScaleDefaults('time'));
verticalScaleConfig.position = "left";
@@ -359,7 +362,10 @@ describe('Time scale tests', function() {
verticalScale.bottom = 400;
expect(verticalScale.getPixelForValue('', 0, 0)).toBe(38);
+ expect(verticalScale.getValueForPixel(38)).toEqual(verticalScale.firstTick);
+
expect(verticalScale.getPixelForValue('', 6, 0)).toBe(375);
+ expect(verticalScale.getValueForPixel(375)).toEqual(verticalScale.lastTick);
});
it('should get the correct label for a data value', function() {