Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

property x0shift, x1shift, y0shift, y1shift for adjusting the shape coordinates #7005

Merged
merged 26 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
aa0cd7a
property shape.x_shift/y_shift for adjusting the shape coordinates
my-tien May 27, 2024
44d1858
Add draftlog for PR 7005
my-tien May 27, 2024
7abea61
Add x_shift/y_shift for selections as well, add selection example to …
my-tien May 27, 2024
a617017
baseline images zzz_shape_shift_horizontal and zzz_shape_shift_vertical
my-tien May 27, 2024
c2f7f27
Update shapes_test after adding shift param to getDataToPixel
my-tien May 27, 2024
fdcaa0c
Rename x_shift/y_shift → xshift/yshift
my-tien May 31, 2024
9921522
Replace xshift and yshift with x0shift and y0shift
my-tien Jun 10, 2024
3ac32f3
Only coerce x0/x1/y0/y1shift if referenced axis is category/multicate…
my-tien Jun 10, 2024
6680745
Fix typo in calc_autorange: x/ysizemode "scale" -> "scaled"
my-tien Jun 10, 2024
ada2289
Add scatter to zzz_shape_shift_vertical mock
my-tien Jun 10, 2024
e11f6f6
Merge remote-tracking branch 'origin-plotly/master' into shape_shift
my-tien Jun 10, 2024
1bfb22d
Updated baseline image after adding scatter to zzz_shape_shift_vertic…
my-tien Jun 10, 2024
04466db
getDataToPixel: If shift is undefined, set it to 0
my-tien Jun 10, 2024
91db7c8
Update draftlog with final property names
my-tien Jun 12, 2024
4bbb669
Adjust attribute descriptions with property formatting and mention of…
my-tien Jun 12, 2024
ab935ac
Move calculation of shape shift into a dedicated function
my-tien Jun 18, 2024
82de6b1
Merge remote-tracking branch 'origin-plotly/master' into shape_shift
my-tien Jun 19, 2024
f9c44bf
Update overlooked test after changing xshift/yshift to x0shift,x1shif…
my-tien Jul 3, 2024
b00d4d8
Remove shift properties from selection for now
my-tien Jul 10, 2024
8cf665a
Merge remote-tracking branch 'origin-plotly/master' into shape_shift
my-tien Jul 10, 2024
78a7e5e
Fix getPixelShift for reversed axes, add reversed axis to mock
my-tien Jul 11, 2024
18e7c84
Update baseline image of zzz_shape_shift_vertical
my-tien Jul 11, 2024
5509ee6
Account for shift when dragging a shape
my-tien Jul 15, 2024
6f8e5a6
Support shape shift in texttemplate as well
my-tien Jul 15, 2024
7de45c3
Update baseline image after updated mock for texttemplate shape
my-tien Jul 15, 2024
9ac970a
Refine description for x0shift/x1shift/y0shift/y1shift
my-tien Jul 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions draftlogs/7005_add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Add property x_shift/y_shift for shapes/selections referencing (multi-)category axes [[#7005](https://github.com/plotly/plotly.js/pull/7005)]
my-tien marked this conversation as resolved.
Show resolved Hide resolved
23 changes: 23 additions & 0 deletions src/components/selections/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,29 @@ module.exports = overrideAll(templatedArray('selection', {
description: 'Sets the selection\'s end y position.'
},

xshift: {
valType: 'number',
dflt: 0,
min: -0.5,
max: 0.5,
my-tien marked this conversation as resolved.
Show resolved Hide resolved
editType: 'calc',
description: [
'Only relevant if xref is a (multi-)category axes. Shifts x0 and x1 by a fraction of',
'the reference unit.'
my-tien marked this conversation as resolved.
Show resolved Hide resolved
].join(' ')
},
yshift: {
valType: 'number',
dflt: 0,
min: -0.5,
max: 0.5,
editType: 'calc',
description: [
'Only relevant if yref is a (multi-)category axes. Shifts y0 and y1 by a fraction of',
'the reference unit.'
].join(' ')
},

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also add these to newselection and test it.

path: {
valType: 'string',
editType: 'arraydraw',
Expand Down
2 changes: 2 additions & 0 deletions src/components/selections/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ function handleSelectionDefaults(selectionIn, selectionOut, fullLayout) {
coerce('line.color');
coerce('line.width');
coerce('line.dash');
coerce('xshift');
my-tien marked this conversation as resolved.
Show resolved Hide resolved
coerce('yshift');

// positioning
var axLetters = ['x', 'y'];
Expand Down
24 changes: 22 additions & 2 deletions src/components/shapes/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,17 @@ module.exports = templatedArray('shape', {
'See `type` and `xsizemode` for more info.'
].join(' ')
},

xshift: {
valType: 'number',
dflt: 0,
min: -0.5,
max: 0.5,
my-tien marked this conversation as resolved.
Show resolved Hide resolved
editType: 'calc',
description: [
'Only relevant if xref is a (multi-)category axes. Shifts x0 and x1 by a fraction of',
'the reference unit.'
].join(' ')
},
yref: extendFlat({}, annAttrs.yref, {
description: [
'Sets the shape\'s y coordinate axis.',
Expand Down Expand Up @@ -220,7 +230,17 @@ module.exports = templatedArray('shape', {
'See `type` and `ysizemode` for more info.'
].join(' ')
},

yshift: {
valType: 'number',
dflt: 0,
min: -0.5,
max: 0.5,
editType: 'calc',
description: [
'Only relevant if yref is a (multi-)category axes. Shifts y0 and y1 by a fraction of',
'the reference unit.'
].join(' ')
},
archmoj marked this conversation as resolved.
Show resolved Hide resolved
path: {
valType: 'string',
editType: 'calc+arraydraw',
Expand Down
13 changes: 9 additions & 4 deletions src/components/shapes/calc_autorange.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ module.exports = function calcAutorange(gd) {
var vx1 = shape.xsizemode === 'pixel' ? shape.xanchor : shape.x1;
ax = Axes.getFromId(gd, shape.xref);

bounds = shapeBounds(ax, vx0, vx1, shape.path, constants.paramIsX);
bounds = shapeBounds(ax, vx0, vx1, shape.path, shape.xshift, constants.paramIsX);
if(bounds) {
shape._extremes[ax._id] = Axes.findExtremes(ax, bounds, calcXPaddingOptions(shape));
}
Expand All @@ -38,7 +38,7 @@ module.exports = function calcAutorange(gd) {
var vy1 = shape.ysizemode === 'pixel' ? shape.yanchor : shape.y1;
ax = Axes.getFromId(gd, shape.yref);

bounds = shapeBounds(ax, vy0, vy1, shape.path, constants.paramIsY);
bounds = shapeBounds(ax, vy0, vy1, shape.path, shape.yshift, constants.paramIsY);
if(bounds) {
shape._extremes[ax._id] = Axes.findExtremes(ax, bounds, calcYPaddingOptions(shape));
}
Expand Down Expand Up @@ -77,8 +77,13 @@ function calcPaddingOptions(lineWidth, sizeMode, v0, v1, path, isYAxis) {
}
}

function shapeBounds(ax, v0, v1, path, paramsToUse) {
var convertVal = (ax.type === 'category' || ax.type === 'multicategory') ? ax.r2c : ax.d2c;
function shapeBounds(ax, v0, v1, path, shift, paramsToUse) {
var convertVal;
if(ax.type === 'category' || ax.type === 'multicategory') {
convertVal = function(v) { return ax.r2c(v) + shift; };
} else {
convertVal = ax.d2c;
}

if(v0 !== undefined) return [convertVal(v0), convertVal(v1)];
if(!path) return;
Expand Down
3 changes: 3 additions & 0 deletions src/components/shapes/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ function handleShapeDefaults(shapeIn, shapeOut, fullLayout) {
var pos2r;
var r2pos;

coerce('xshift');
my-tien marked this conversation as resolved.
Show resolved Hide resolved
coerce('yshift');

// xref, yref
var axRef = Axes.coerceRef(shapeIn, shapeOut, gdMock, axLetter, undefined,
'paper');
Expand Down
6 changes: 4 additions & 2 deletions src/components/shapes/display_labels.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,12 @@ module.exports = function drawLabel(gd, index, options, shapeGroup) {
// Setup conversion functions
var xa = Axes.getFromId(gd, options.xref);
var xRefType = Axes.getRefType(options.xref);
var xShift = options.xshift;
var ya = Axes.getFromId(gd, options.yref);
var yRefType = Axes.getRefType(options.yref);
var x2p = helpers.getDataToPixel(gd, xa, false, xRefType);
var y2p = helpers.getDataToPixel(gd, ya, true, yRefType);
var yShift = options.yshift;
var x2p = helpers.getDataToPixel(gd, xa, xShift, false, xRefType);
var y2p = helpers.getDataToPixel(gd, ya, yShift, true, yRefType);
shapex0 = x2p(options.x0);
shapex1 = x2p(options.x1);
shapey0 = y2p(options.y0);
Expand Down
6 changes: 4 additions & 2 deletions src/components/shapes/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,12 @@ function setupDragElement(gd, shapePath, shapeOptions, index, shapeLayer, editHe
// setup conversion functions
var xa = Axes.getFromId(gd, shapeOptions.xref);
var xRefType = Axes.getRefType(shapeOptions.xref);
var xShift = shapeOptions.xshift;
var ya = Axes.getFromId(gd, shapeOptions.yref);
var yRefType = Axes.getRefType(shapeOptions.yref);
var x2p = helpers.getDataToPixel(gd, xa, false, xRefType);
var y2p = helpers.getDataToPixel(gd, ya, true, yRefType);
var yShift = shapeOptions.yshift;
var x2p = helpers.getDataToPixel(gd, xa, xShift, false, xRefType);
var y2p = helpers.getDataToPixel(gd, ya, yShift, true, yRefType);
var p2x = helpers.getPixelToData(gd, xa, false, xRefType);
var p2y = helpers.getPixelToData(gd, ya, true, yRefType);

Expand Down
37 changes: 26 additions & 11 deletions src/components/shapes/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ exports.extractPathCoords = function(path, paramsToUse, isRaw) {
return extractedCoordinates;
};

exports.getDataToPixel = function(gd, axis, isVertical, refType) {
exports.getDataToPixel = function(gd, axis, shift, isVertical, refType) {
archmoj marked this conversation as resolved.
Show resolved Hide resolved
var gs = gd._fullLayout._size;
var dataToPixel;

Expand All @@ -66,7 +66,15 @@ exports.getDataToPixel = function(gd, axis, isVertical, refType) {
var d2r = exports.shapePositionToRange(axis);

dataToPixel = function(v) {
return axis._offset + axis.r2p(d2r(v, true));
var shiftPixels = 0;
if(axis.type === 'category' || axis.type === 'multicategory') {
if(isVertical) {
shiftPixels = -1 * ((gs.h - axis.r2p(d2r(0.5, true))) * shift);
} else {
shiftPixels = axis.r2p(d2r(0.5, true)) * shift;
}
}
return axis._offset + axis.r2p(d2r(v, true)) + (shiftPixels || 0);
};

if(axis.type === 'date') dataToPixel = exports.decodeDate(dataToPixel);
Expand Down Expand Up @@ -179,6 +187,8 @@ exports.getPathString = function(gd, options) {
var ya = Axes.getFromId(gd, options.yref);
var gs = gd._fullLayout._size;
var x2r, x2p, y2r, y2p;
var shiftUnitX = 0;
var shiftUnitY = 0;
var x0, x1, y0, y1;

if(xa) {
Expand All @@ -187,6 +197,9 @@ exports.getPathString = function(gd, options) {
} else {
x2r = exports.shapePositionToRange(xa);
x2p = function(v) { return xa._offset + xa.r2p(x2r(v, true)); };
if(xa.type === 'category' || xa.type === 'multicategory') {
shiftUnitX = xa.r2p(x2r(0.5, true));
}
}
} else {
x2p = function(v) { return gs.l + gs.w * v; };
Expand All @@ -198,6 +211,9 @@ exports.getPathString = function(gd, options) {
} else {
y2r = exports.shapePositionToRange(ya);
y2p = function(v) { return ya._offset + ya.r2p(y2r(v, true)); };
if(ya.type === 'category' || ya.type === 'multicategory') {
shiftUnitY = gs.h - ya.r2p(y2r(0.5, true));
}
}
} else {
y2p = function(v) { return gs.t + gs.h * (1 - v); };
Expand All @@ -208,23 +224,22 @@ exports.getPathString = function(gd, options) {
if(ya && ya.type === 'date') y2p = exports.decodeDate(y2p);
return convertPath(options, x2p, y2p);
}

if(options.xsizemode === 'pixel') {
var xAnchorPos = x2p(options.xanchor);
x0 = xAnchorPos + options.x0;
x1 = xAnchorPos + options.x1;
x0 = xAnchorPos + options.x0 + shiftUnitX * options.xshift;
x1 = xAnchorPos + options.x1 + shiftUnitX * options.xshift;
} else {
x0 = x2p(options.x0);
x1 = x2p(options.x1);
x0 = x2p(options.x0) + shiftUnitX * options.xshift;
x1 = x2p(options.x1) + shiftUnitX * options.xshift;
my-tien marked this conversation as resolved.
Show resolved Hide resolved
}

if(options.ysizemode === 'pixel') {
var yAnchorPos = y2p(options.yanchor);
y0 = yAnchorPos - options.y0;
y1 = yAnchorPos - options.y1;
y0 = yAnchorPos - options.y0 - shiftUnitY * options.yshift;
y1 = yAnchorPos - options.y1 - shiftUnitY * options.yshift;
} else {
y0 = y2p(options.y0);
y1 = y2p(options.y1);
y0 = y2p(options.y0) - shiftUnitY * options.yshift;
y1 = y2p(options.y1) - shiftUnitY * options.yshift;
}

if(type === 'line') return 'M' + x0 + ',' + y0 + 'L' + x1 + ',' + y1;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/image/baselines/zzz_shape_shift_vertical.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 changes: 87 additions & 0 deletions test/image/mocks/zzz_shape_shift_horizontal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"data": [
{
archmoj marked this conversation as resolved.
Show resolved Hide resolved
"y": [
["A", "A", "B", "B"], ["C", "D", "C", "D"]
],
"x": [
1, 2, 3, 4
],
"type": "bar",
"marker": {
"color": "rgba(153, 217, 234, 1)"
},
"orientation": "h"
},
{
"y": [
["A", "A", "B", "B"], ["C", "D", "C", "D"]
],
"x": [
4, 3, 2, 1
],
"type": "bar",
"orientation": "h"
}
],
"layout": {
"shapes": [
{
"layer": "above",
"type": "rect",
"label": {
"text": "around A,D",
"textposition": "bottom center",
"textangle": 0
},
"line": {
"color": "black",
"width": 3.0
},
"y0": ["A", "C"],
my-tien marked this conversation as resolved.
Show resolved Hide resolved
"y1": ["A", "D"],
"x0": 0,
"x1": 0.25,
"yshift": 0.5,
"xref": "paper"
},
{
"layer": "above",
"type": "line",
"label": {
"text": "on B,D",
"textposition": "middle",
"textangle": 0
},
"line": {
"color": "blue",
"width": 3.0
},
"y0": ["B", "D"],
"y1": ["B", "D"],
"x0": 0,
"x1": 0.25,
"xref": "paper"
},
{
"layer": "above",
"type": "line",
"label": {
"text": "Before B,D",
"textposition": "middle",
"textangle": 0
},
"line": {
"color": "green",
"width": 3.0
},
"y0": ["B", "D"],
"y1": ["B", "D"],
"x0": 0,
"x1": 0.25,
"yshift": -0.5,
"xref": "paper"
}
]
}
}
65 changes: 65 additions & 0 deletions test/image/mocks/zzz_shape_shift_vertical.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"data": [
{
"x": [
"A", "B", "C", "D"
],
"y": [
1, 2, 3, 4
],
"type": "bar"
}
],
"layout": {
"width": 600,
"shapes": [
{
"layer": "above",
"type": "line",
"label": {
"text": "right from A",
"textposition": "end",
"textangle": 0
},
"line": {
"color": "yellow",
"width": 3.0
},
"x0": "A",
"x1": "A",
"y0": 0,
"y1": 0.5,
"xshift": 0.5,
"yref": "paper"
},
{
"layer": "above",
"type": "line",
"label": {
"text": "slightly left from D",
"textposition": "end",
"textangle": 0
},
"line": {
"color": "pink",
"width": 3.0
},
"x0": 3,
"x1": 3,
"y0": 0,
"y1": 0.5,
"xshift": -0.25,
"yref": "paper"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this also working for a path?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this should only do something when using x0, x1, y0, y1

],
"selections": [
{
"x0": 0,
"x1": 4,
"y0": 1,
"y1": 3,
"xshift": -0.5
}
]
}
}
Loading