-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Copy pathconvert_coords.js
79 lines (67 loc) · 2.92 KB
/
convert_coords.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
* Copyright 2012-2017, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
var isNumeric = require('fast-isnumeric');
var toLogRange = require('../../lib/to_log_range');
/*
* convertCoords: when converting an axis between log and linear
* you need to alter any images on that axis to keep them
* pointing at the same data point.
* In v2.0 this will become obsolete (or perhaps size will still need conversion?)
* we convert size by declaring that the maximum extent *in data units* should be
* the same, assuming the image is anchored by its center (could remove that restriction
* if we think it's important) even though the actual left and right values will not be
* quite the same since the scale becomes nonlinear (and central anchor means the pixel
* center of the image, not the data units center)
*
* gd: the plot div
* ax: the axis being changed
* newType: the type it's getting
* doExtra: function(attr, val) from inside relayout that sets the attribute.
* Use this to make the changes as it's aware if any other changes in the
* same relayout call should override this conversion.
*/
module.exports = function convertCoords(gd, ax, newType, doExtra) {
var toLog = (newType === 'log') && (ax.type === 'linear'),
fromLog = (newType === 'linear') && (ax.type === 'log');
if(!(toLog || fromLog)) return;
var images = gd._fullLayout.images,
axLetter = ax._id.charAt(0),
image,
attrPrefix;
for(var i = 0; i < images.length; i++) {
image = images[i];
attrPrefix = 'images[' + i + '].';
if(image[axLetter + 'ref'] === ax._id) {
var currentPos = image[axLetter],
currentSize = image['size' + axLetter],
newPos = null,
newSize = null;
if(toLog) {
newPos = toLogRange(currentPos, ax.range);
// this is the inverse of the conversion we do in fromLog below
// so that the conversion is reversible (notice the fromLog conversion
// is like sinh, and this one looks like arcsinh)
var dx = currentSize / Math.pow(10, newPos) / 2;
newSize = 2 * Math.log(dx + Math.sqrt(1 + dx * dx)) / Math.LN10;
}
else {
newPos = Math.pow(10, currentPos);
newSize = newPos * (Math.pow(10, currentSize / 2) - Math.pow(10, -currentSize / 2));
}
// if conversion failed, delete the value so it can get a default later on
if(!isNumeric(newPos)) {
newPos = null;
newSize = null;
}
else if(!isNumeric(newSize)) newSize = null;
doExtra(attrPrefix + axLetter, newPos);
doExtra(attrPrefix + 'size' + axLetter, newSize);
}
}
};