diff --git a/src/components/drawing/index.js b/src/components/drawing/index.js
index ca3ac9bca02..a52bc3537fd 100644
--- a/src/components/drawing/index.js
+++ b/src/components/drawing/index.js
@@ -221,6 +221,7 @@ var SYMBOLDEFS = require('./symbol_defs');
drawing.symbolNames = [];
drawing.symbolFuncs = [];
+drawing.symbolBackOffs = [];
drawing.symbolNeedLines = {};
drawing.symbolNoDot = {};
drawing.symbolNoFill = {};
@@ -240,6 +241,7 @@ Object.keys(SYMBOLDEFS).forEach(function(k) {
);
drawing.symbolNames[n] = k;
drawing.symbolFuncs[n] = symDef.f;
+ drawing.symbolBackOffs[n] = symDef.backoff || 0;
if(symDef.needLine) {
drawing.symbolNeedLines[n] = true;
@@ -287,9 +289,9 @@ drawing.symbolNumber = function(v) {
0 : Math.floor(Math.max(v, 0));
};
-function makePointPath(symbolNumber, r) {
+function makePointPath(symbolNumber, r, t, s) {
var base = symbolNumber % 100;
- return drawing.symbolFuncs[base](r) + (symbolNumber >= 200 ? DOTPATH : '');
+ return drawing.symbolFuncs[base](r, t, s) + (symbolNumber >= 200 ? DOTPATH : '');
}
var HORZGRADIENT = {x1: 1, x2: 0, y1: 0, y2: 0};
@@ -649,7 +651,10 @@ drawing.singlePointStyle = function(d, sel, trace, fns, gd) {
// because that impacts how to handle colors
d.om = x % 200 >= 100;
- sel.attr('d', makePointPath(x, r));
+ var angle = getMarkerAngle(d, trace);
+ var standoff = getMarkerStandoff(d, trace);
+
+ sel.attr('d', makePointPath(x, r, angle, standoff));
}
var perPointGradient = false;
@@ -898,7 +903,7 @@ drawing.selectedPointStyle = function(s, trace) {
var mx = d.mx || marker.symbol || 0;
var mrc2 = fns.selectedSizeFn(d);
- pt.attr('d', makePointPath(drawing.symbolNumber(mx), mrc2));
+ pt.attr('d', makePointPath(drawing.symbolNumber(mx), mrc2, getMarkerAngle(d, trace), getMarkerStandoff(d, trace)));
// save for Drawing.selectedTextStyle
d.mrc2 = mrc2;
@@ -1069,6 +1074,26 @@ drawing.smoothclosed = function(pts, smoothness) {
return path;
};
+var lastDrawnX, lastDrawnY;
+
+function roundEnd(pt, isY, isLastPoint) {
+ if(isLastPoint) pt = applyBackoff(pt);
+
+ return isY ? roundY(pt[1]) : roundX(pt[0]);
+}
+
+function roundX(p) {
+ var v = d3.round(p, 2);
+ lastDrawnX = v;
+ return v;
+}
+
+function roundY(p) {
+ var v = d3.round(p, 2);
+ lastDrawnY = v;
+ return v;
+}
+
function makeTangent(prevpt, thispt, nextpt, smoothness) {
var d1x = prevpt[0] - thispt[0];
var d1y = prevpt[1] - thispt[1];
@@ -1082,11 +1107,11 @@ function makeTangent(prevpt, thispt, nextpt, smoothness) {
var denom2 = 3 * d1a * (d1a + d2a);
return [
[
- d3.round(thispt[0] + (denom1 && numx / denom1), 2),
- d3.round(thispt[1] + (denom1 && numy / denom1), 2)
+ roundX(thispt[0] + (denom1 && numx / denom1)),
+ roundY(thispt[1] + (denom1 && numy / denom1))
], [
- d3.round(thispt[0] - (denom2 && numx / denom2), 2),
- d3.round(thispt[1] - (denom2 && numy / denom2), 2)
+ roundX(thispt[0] - (denom2 && numx / denom2)),
+ roundY(thispt[1] - (denom2 && numy / denom2))
]
];
}
@@ -1094,35 +1119,99 @@ function makeTangent(prevpt, thispt, nextpt, smoothness) {
// step paths - returns a generator function for paths
// with the given step shape
var STEPPATH = {
- hv: function(p0, p1) {
- return 'H' + d3.round(p1[0], 2) + 'V' + d3.round(p1[1], 2);
+ hv: function(p0, p1, isLastPoint) {
+ return 'H' +
+ roundX(p1[0]) + 'V' +
+ roundEnd(p1, 1, isLastPoint);
},
- vh: function(p0, p1) {
- return 'V' + d3.round(p1[1], 2) + 'H' + d3.round(p1[0], 2);
+ vh: function(p0, p1, isLastPoint) {
+ return 'V' +
+ roundY(p1[1]) + 'H' +
+ roundEnd(p1, 0, isLastPoint);
},
- hvh: function(p0, p1) {
- return 'H' + d3.round((p0[0] + p1[0]) / 2, 2) + 'V' +
- d3.round(p1[1], 2) + 'H' + d3.round(p1[0], 2);
+ hvh: function(p0, p1, isLastPoint) {
+ return 'H' +
+ roundX((p0[0] + p1[0]) / 2) + 'V' +
+ roundY(p1[1]) + 'H' +
+ roundEnd(p1, 0, isLastPoint);
},
- vhv: function(p0, p1) {
- return 'V' + d3.round((p0[1] + p1[1]) / 2, 2) + 'H' +
- d3.round(p1[0], 2) + 'V' + d3.round(p1[1], 2);
+ vhv: function(p0, p1, isLastPoint) {
+ return 'V' +
+ roundY((p0[1] + p1[1]) / 2) + 'H' +
+ roundX(p1[0]) + 'V' +
+ roundEnd(p1, 1, isLastPoint);
}
};
-var STEPLINEAR = function(p0, p1) {
- return 'L' + d3.round(p1[0], 2) + ',' + d3.round(p1[1], 2);
+var STEPLINEAR = function(p0, p1, isLastPoint) {
+ return 'L' +
+ roundEnd(p1, 0, isLastPoint) + ',' +
+ roundEnd(p1, 1, isLastPoint);
};
drawing.steps = function(shape) {
var onestep = STEPPATH[shape] || STEPLINEAR;
return function(pts) {
- var path = 'M' + d3.round(pts[0][0], 2) + ',' + d3.round(pts[0][1], 2);
- for(var i = 1; i < pts.length; i++) {
- path += onestep(pts[i - 1], pts[i]);
+ var path = 'M' + roundX(pts[0][0]) + ',' + roundY(pts[0][1]);
+ var len = pts.length;
+ for(var i = 1; i < len; i++) {
+ path += onestep(pts[i - 1], pts[i], i === len - 1);
}
return path;
};
};
+function applyBackoff(pt, start) {
+ var backoff = pt.backoff;
+ var trace = pt.trace;
+ var d = pt.d;
+ var i = pt.i;
+
+ if(backoff && trace &&
+ trace.marker &&
+ trace.marker.angle % 360 === 0 &&
+ trace.line &&
+ trace.line.shape !== 'spline'
+ ) {
+ var arrayBackoff = Lib.isArrayOrTypedArray(backoff);
+ var end = pt;
+
+ var x1 = start ? start[0] : lastDrawnX || 0;
+ var y1 = start ? start[1] : lastDrawnY || 0;
+
+ var x2 = end[0];
+ var y2 = end[1];
+
+ var dx = x2 - x1;
+ var dy = y2 - y1;
+
+ var t = Math.atan2(dy, dx);
+
+ var b = arrayBackoff ? backoff[i] : backoff;
+
+ if(b === 'auto') {
+ var endI = end.i;
+ if(trace.type === 'scatter') endI--; // Why we need this hack?
+
+ var endMarker = end.marker;
+ b = endMarker ? drawing.symbolBackOffs[drawing.symbolNumber(endMarker.symbol)] * endMarker.size : 0;
+ b += drawing.getMarkerStandoff(d[endI], trace) || 0;
+ }
+
+ var x = x2 - b * Math.cos(t);
+ var y = y2 - b * Math.sin(t);
+
+ if(
+ ((x <= x2 && x >= x1) || (x >= x2 && x <= x1)) &&
+ ((y <= y2 && y >= y1) || (y >= y2 && y <= y1))
+ ) {
+ pt = [x, y];
+ }
+ }
+
+ return pt;
+}
+
+drawing.applyBackoff = applyBackoff;
+
// off-screen svg render testing element, shared by the whole page
// uses the id 'js-plotly-tester' and stores it in drawing.tester
drawing.makeTester = function() {
@@ -1447,3 +1536,168 @@ drawing.setTextPointsScale = function(selection, xScale, yScale) {
el.attr('transform', transforms.join(''));
});
};
+
+function getMarkerStandoff(d, trace) {
+ var standoff;
+
+ if(d) standoff = d.mf;
+
+ if(standoff === undefined) {
+ standoff = trace.marker ? trace.marker.standoff || 0 : 0;
+ }
+
+ if(!trace._geo && !trace._xA) {
+ // case of legends
+ return -standoff;
+ }
+
+ return standoff;
+}
+
+drawing.getMarkerStandoff = getMarkerStandoff;
+
+var atan2 = Math.atan2;
+var cos = Math.cos;
+var sin = Math.sin;
+
+function rotate(t, xy) {
+ var x = xy[0];
+ var y = xy[1];
+ return [
+ x * cos(t) - y * sin(t),
+ x * sin(t) + y * cos(t)
+ ];
+}
+
+var previousLon;
+var previousLat;
+var previousX;
+var previousY;
+var previousI;
+var previousTraceUid;
+
+function getMarkerAngle(d, trace) {
+ var angle = d.ma;
+
+ if(angle === undefined) {
+ angle = trace.marker.angle || 0;
+ }
+
+ var x, y;
+ var ref = trace.marker.angleref;
+ if(ref === 'previous' || ref === 'north') {
+ if(trace._geo) {
+ var p = trace._geo.project(d.lonlat);
+ x = p[0];
+ y = p[1];
+ } else {
+ var xa = trace._xA;
+ var ya = trace._yA;
+ if(xa && ya) {
+ x = xa.c2p(d.x);
+ y = ya.c2p(d.y);
+ } else {
+ // case of legends
+ return 90;
+ }
+ }
+
+ if(trace._geo) {
+ var lon = d.lonlat[0];
+ var lat = d.lonlat[1];
+
+ var north = trace._geo.project([
+ lon,
+ lat + 1e-5 // epsilon
+ ]);
+
+ var east = trace._geo.project([
+ lon + 1e-5, // epsilon
+ lat
+ ]);
+
+ var u = atan2(
+ east[1] - y,
+ east[0] - x
+ );
+
+ var v = atan2(
+ north[1] - y,
+ north[0] - x
+ );
+
+ var t;
+ if(ref === 'north') {
+ t = angle / 180 * Math.PI;
+ // To use counter-clockwise angles i.e.
+ // East: 90, West: -90
+ // to facilitate wind visualisations
+ // in future we should use t = -t here.
+ } else if(ref === 'previous') {
+ var lon1 = lon / 180 * Math.PI;
+ var lat1 = lat / 180 * Math.PI;
+ var lon2 = previousLon / 180 * Math.PI;
+ var lat2 = previousLat / 180 * Math.PI;
+
+ var dLon = lon2 - lon1;
+
+ var deltaY = cos(lat2) * sin(dLon);
+ var deltaX = sin(lat2) * cos(lat1) - cos(lat2) * sin(lat1) * cos(dLon);
+
+ t = -atan2(
+ deltaY,
+ deltaX
+ ) - Math.PI;
+
+ previousLon = lon;
+ previousLat = lat;
+ }
+
+ var A = rotate(u, [cos(t), 0]);
+ var B = rotate(v, [sin(t), 0]);
+
+ angle = atan2(
+ A[1] + B[1],
+ A[0] + B[0]
+ ) / Math.PI * 180;
+
+ if(ref === 'previous' && !(
+ previousTraceUid === trace.uid &&
+ d.i === previousI + 1
+ )) {
+ angle = null;
+ }
+ }
+
+ if(ref === 'previous' && !trace._geo) {
+ if(
+ previousTraceUid === trace.uid &&
+ d.i === previousI + 1 &&
+ isNumeric(x) &&
+ isNumeric(y)
+ ) {
+ var dX = x - previousX;
+ var dY = y - previousY;
+
+ var shape = trace.line ? trace.line.shape || '' : '';
+
+ var lastShapeChar = shape.slice(shape.length - 1);
+ if(lastShapeChar === 'h') dY = 0;
+ if(lastShapeChar === 'v') dX = 0;
+
+ angle += atan2(dY, dX) / Math.PI * 180 + 90;
+ } else {
+ angle = null;
+ }
+ }
+ }
+
+ previousX = x;
+ previousY = y;
+ previousI = d.i;
+ previousTraceUid = trace.uid;
+
+ return angle;
+}
+
+drawing.getMarkerAngle = getMarkerAngle;
diff --git a/src/components/drawing/symbol_defs.js b/src/components/drawing/symbol_defs.js
index 77b02946170..ce99d7c430d 100644
--- a/src/components/drawing/symbol_defs.js
+++ b/src/components/drawing/symbol_defs.js
@@ -1,6 +1,7 @@
'use strict';
-var d3 = require('@plotly/d3');
+var parseSvgPath = require('parse-svg-path');
+var round = require('@plotly/d3').round;
/** Marker symbol definitions
* users can specify markers either by number or name
@@ -10,340 +11,416 @@ var d3 = require('@plotly/d3');
* add both and you get both
*/
+
+var emptyPath = 'M0,0Z';
+var sqrt2 = Math.sqrt(2);
+var sqrt3 = Math.sqrt(3);
+var PI = Math.PI;
+var cos = Math.cos;
+var sin = Math.sin;
+
module.exports = {
circle: {
n: 0,
- f: function(r) {
- var rs = d3.round(r, 2);
- return 'M' + rs + ',0A' + rs + ',' + rs + ' 0 1,1 0,-' + rs +
- 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rs = round(r, 2);
+ var circle = 'M' + rs + ',0A' + rs + ',' + rs + ' 0 1,1 0,-' + rs + 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z';
+ return standoff ? align(angle, standoff, circle) : circle;
}
},
square: {
n: 1,
- f: function(r) {
- var rs = d3.round(r, 2);
- return 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rs = round(r, 2);
+ return align(angle, standoff, 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z');
}
},
diamond: {
n: 2,
- f: function(r) {
- var rd = d3.round(r * 1.3, 2);
- return 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rd = round(r * 1.3, 2);
+ return align(angle, standoff, 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z');
}
},
cross: {
n: 3,
- f: function(r) {
- var rc = d3.round(r * 0.4, 2);
- var rc2 = d3.round(r * 1.2, 2);
- return 'M' + rc2 + ',' + rc + 'H' + rc + 'V' + rc2 + 'H-' + rc +
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rc = round(r * 0.4, 2);
+ var rc2 = round(r * 1.2, 2);
+ return align(angle, standoff, 'M' + rc2 + ',' + rc + 'H' + rc + 'V' + rc2 + 'H-' + rc +
'V' + rc + 'H-' + rc2 + 'V-' + rc + 'H-' + rc + 'V-' + rc2 +
- 'H' + rc + 'V-' + rc + 'H' + rc2 + 'Z';
+ 'H' + rc + 'V-' + rc + 'H' + rc2 + 'Z');
}
},
x: {
n: 4,
- f: function(r) {
- var rx = d3.round(r * 0.8 / Math.sqrt(2), 2);
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rx = round(r * 0.8 / sqrt2, 2);
var ne = 'l' + rx + ',' + rx;
var se = 'l' + rx + ',-' + rx;
var sw = 'l-' + rx + ',-' + rx;
var nw = 'l-' + rx + ',' + rx;
- return 'M0,' + rx + ne + se + sw + se + sw + nw + sw + nw + ne + nw + ne + 'Z';
+ return align(angle, standoff, 'M0,' + rx + ne + se + sw + se + sw + nw + sw + nw + ne + nw + ne + 'Z');
}
},
'triangle-up': {
n: 5,
- f: function(r) {
- var rt = d3.round(r * 2 / Math.sqrt(3), 2);
- var r2 = d3.round(r / 2, 2);
- var rs = d3.round(r, 2);
- return 'M-' + rt + ',' + r2 + 'H' + rt + 'L0,-' + rs + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rt = round(r * 2 / sqrt3, 2);
+ var r2 = round(r / 2, 2);
+ var rs = round(r, 2);
+ return align(angle, standoff, 'M-' + rt + ',' + r2 + 'H' + rt + 'L0,-' + rs + 'Z');
}
},
'triangle-down': {
n: 6,
- f: function(r) {
- var rt = d3.round(r * 2 / Math.sqrt(3), 2);
- var r2 = d3.round(r / 2, 2);
- var rs = d3.round(r, 2);
- return 'M-' + rt + ',-' + r2 + 'H' + rt + 'L0,' + rs + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rt = round(r * 2 / sqrt3, 2);
+ var r2 = round(r / 2, 2);
+ var rs = round(r, 2);
+ return align(angle, standoff, 'M-' + rt + ',-' + r2 + 'H' + rt + 'L0,' + rs + 'Z');
}
},
'triangle-left': {
n: 7,
- f: function(r) {
- var rt = d3.round(r * 2 / Math.sqrt(3), 2);
- var r2 = d3.round(r / 2, 2);
- var rs = d3.round(r, 2);
- return 'M' + r2 + ',-' + rt + 'V' + rt + 'L-' + rs + ',0Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rt = round(r * 2 / sqrt3, 2);
+ var r2 = round(r / 2, 2);
+ var rs = round(r, 2);
+ return align(angle, standoff, 'M' + r2 + ',-' + rt + 'V' + rt + 'L-' + rs + ',0Z');
}
},
'triangle-right': {
n: 8,
- f: function(r) {
- var rt = d3.round(r * 2 / Math.sqrt(3), 2);
- var r2 = d3.round(r / 2, 2);
- var rs = d3.round(r, 2);
- return 'M-' + r2 + ',-' + rt + 'V' + rt + 'L' + rs + ',0Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rt = round(r * 2 / sqrt3, 2);
+ var r2 = round(r / 2, 2);
+ var rs = round(r, 2);
+ return align(angle, standoff, 'M-' + r2 + ',-' + rt + 'V' + rt + 'L' + rs + ',0Z');
}
},
'triangle-ne': {
n: 9,
- f: function(r) {
- var r1 = d3.round(r * 0.6, 2);
- var r2 = d3.round(r * 1.2, 2);
- return 'M-' + r2 + ',-' + r1 + 'H' + r1 + 'V' + r2 + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var r1 = round(r * 0.6, 2);
+ var r2 = round(r * 1.2, 2);
+ return align(angle, standoff, 'M-' + r2 + ',-' + r1 + 'H' + r1 + 'V' + r2 + 'Z');
}
},
'triangle-se': {
n: 10,
- f: function(r) {
- var r1 = d3.round(r * 0.6, 2);
- var r2 = d3.round(r * 1.2, 2);
- return 'M' + r1 + ',-' + r2 + 'V' + r1 + 'H-' + r2 + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var r1 = round(r * 0.6, 2);
+ var r2 = round(r * 1.2, 2);
+ return align(angle, standoff, 'M' + r1 + ',-' + r2 + 'V' + r1 + 'H-' + r2 + 'Z');
}
},
'triangle-sw': {
n: 11,
- f: function(r) {
- var r1 = d3.round(r * 0.6, 2);
- var r2 = d3.round(r * 1.2, 2);
- return 'M' + r2 + ',' + r1 + 'H-' + r1 + 'V-' + r2 + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var r1 = round(r * 0.6, 2);
+ var r2 = round(r * 1.2, 2);
+ return align(angle, standoff, 'M' + r2 + ',' + r1 + 'H-' + r1 + 'V-' + r2 + 'Z');
}
},
'triangle-nw': {
n: 12,
- f: function(r) {
- var r1 = d3.round(r * 0.6, 2);
- var r2 = d3.round(r * 1.2, 2);
- return 'M-' + r1 + ',' + r2 + 'V-' + r1 + 'H' + r2 + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var r1 = round(r * 0.6, 2);
+ var r2 = round(r * 1.2, 2);
+ return align(angle, standoff, 'M-' + r1 + ',' + r2 + 'V-' + r1 + 'H' + r2 + 'Z');
}
},
pentagon: {
n: 13,
- f: function(r) {
- var x1 = d3.round(r * 0.951, 2);
- var x2 = d3.round(r * 0.588, 2);
- var y0 = d3.round(-r, 2);
- var y1 = d3.round(r * -0.309, 2);
- var y2 = d3.round(r * 0.809, 2);
- return 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2 + 'H-' + x2 +
- 'L-' + x1 + ',' + y1 + 'L0,' + y0 + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var x1 = round(r * 0.951, 2);
+ var x2 = round(r * 0.588, 2);
+ var y0 = round(-r, 2);
+ var y1 = round(r * -0.309, 2);
+ var y2 = round(r * 0.809, 2);
+ return align(angle, standoff, 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2 + 'H-' + x2 +
+ 'L-' + x1 + ',' + y1 + 'L0,' + y0 + 'Z');
}
},
hexagon: {
n: 14,
- f: function(r) {
- var y0 = d3.round(r, 2);
- var y1 = d3.round(r / 2, 2);
- var x = d3.round(r * Math.sqrt(3) / 2, 2);
- return 'M' + x + ',-' + y1 + 'V' + y1 + 'L0,' + y0 +
- 'L-' + x + ',' + y1 + 'V-' + y1 + 'L0,-' + y0 + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var y0 = round(r, 2);
+ var y1 = round(r / 2, 2);
+ var x = round(r * sqrt3 / 2, 2);
+ return align(angle, standoff, 'M' + x + ',-' + y1 + 'V' + y1 + 'L0,' + y0 +
+ 'L-' + x + ',' + y1 + 'V-' + y1 + 'L0,-' + y0 + 'Z');
}
},
hexagon2: {
n: 15,
- f: function(r) {
- var x0 = d3.round(r, 2);
- var x1 = d3.round(r / 2, 2);
- var y = d3.round(r * Math.sqrt(3) / 2, 2);
- return 'M-' + x1 + ',' + y + 'H' + x1 + 'L' + x0 +
- ',0L' + x1 + ',-' + y + 'H-' + x1 + 'L-' + x0 + ',0Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var x0 = round(r, 2);
+ var x1 = round(r / 2, 2);
+ var y = round(r * sqrt3 / 2, 2);
+ return align(angle, standoff, 'M-' + x1 + ',' + y + 'H' + x1 + 'L' + x0 +
+ ',0L' + x1 + ',-' + y + 'H-' + x1 + 'L-' + x0 + ',0Z');
}
},
octagon: {
n: 16,
- f: function(r) {
- var a = d3.round(r * 0.924, 2);
- var b = d3.round(r * 0.383, 2);
- return 'M-' + b + ',-' + a + 'H' + b + 'L' + a + ',-' + b + 'V' + b +
- 'L' + b + ',' + a + 'H-' + b + 'L-' + a + ',' + b + 'V-' + b + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var a = round(r * 0.924, 2);
+ var b = round(r * 0.383, 2);
+ return align(angle, standoff, 'M-' + b + ',-' + a + 'H' + b + 'L' + a + ',-' + b + 'V' + b +
+ 'L' + b + ',' + a + 'H-' + b + 'L-' + a + ',' + b + 'V-' + b + 'Z');
}
},
star: {
n: 17,
- f: function(r) {
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
var rs = r * 1.4;
- var x1 = d3.round(rs * 0.225, 2);
- var x2 = d3.round(rs * 0.951, 2);
- var x3 = d3.round(rs * 0.363, 2);
- var x4 = d3.round(rs * 0.588, 2);
- var y0 = d3.round(-rs, 2);
- var y1 = d3.round(rs * -0.309, 2);
- var y3 = d3.round(rs * 0.118, 2);
- var y4 = d3.round(rs * 0.809, 2);
- var y5 = d3.round(rs * 0.382, 2);
- return 'M' + x1 + ',' + y1 + 'H' + x2 + 'L' + x3 + ',' + y3 +
+ var x1 = round(rs * 0.225, 2);
+ var x2 = round(rs * 0.951, 2);
+ var x3 = round(rs * 0.363, 2);
+ var x4 = round(rs * 0.588, 2);
+ var y0 = round(-rs, 2);
+ var y1 = round(rs * -0.309, 2);
+ var y3 = round(rs * 0.118, 2);
+ var y4 = round(rs * 0.809, 2);
+ var y5 = round(rs * 0.382, 2);
+ return align(angle, standoff, 'M' + x1 + ',' + y1 + 'H' + x2 + 'L' + x3 + ',' + y3 +
'L' + x4 + ',' + y4 + 'L0,' + y5 + 'L-' + x4 + ',' + y4 +
'L-' + x3 + ',' + y3 + 'L-' + x2 + ',' + y1 + 'H-' + x1 +
- 'L0,' + y0 + 'Z';
+ 'L0,' + y0 + 'Z');
}
},
hexagram: {
n: 18,
- f: function(r) {
- var y = d3.round(r * 0.66, 2);
- var x1 = d3.round(r * 0.38, 2);
- var x2 = d3.round(r * 0.76, 2);
- return 'M-' + x2 + ',0l-' + x1 + ',-' + y + 'h' + x2 +
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var y = round(r * 0.66, 2);
+ var x1 = round(r * 0.38, 2);
+ var x2 = round(r * 0.76, 2);
+ return align(angle, standoff, 'M-' + x2 + ',0l-' + x1 + ',-' + y + 'h' + x2 +
'l' + x1 + ',-' + y + 'l' + x1 + ',' + y + 'h' + x2 +
'l-' + x1 + ',' + y + 'l' + x1 + ',' + y + 'h-' + x2 +
- 'l-' + x1 + ',' + y + 'l-' + x1 + ',-' + y + 'h-' + x2 + 'Z';
+ 'l-' + x1 + ',' + y + 'l-' + x1 + ',-' + y + 'h-' + x2 + 'Z');
}
},
'star-triangle-up': {
n: 19,
- f: function(r) {
- var x = d3.round(r * Math.sqrt(3) * 0.8, 2);
- var y1 = d3.round(r * 0.8, 2);
- var y2 = d3.round(r * 1.6, 2);
- var rc = d3.round(r * 4, 2);
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var x = round(r * sqrt3 * 0.8, 2);
+ var y1 = round(r * 0.8, 2);
+ var y2 = round(r * 1.6, 2);
+ var rc = round(r * 4, 2);
var aPart = 'A ' + rc + ',' + rc + ' 0 0 1 ';
- return 'M-' + x + ',' + y1 + aPart + x + ',' + y1 +
- aPart + '0,-' + y2 + aPart + '-' + x + ',' + y1 + 'Z';
+ return align(angle, standoff, 'M-' + x + ',' + y1 + aPart + x + ',' + y1 +
+ aPart + '0,-' + y2 + aPart + '-' + x + ',' + y1 + 'Z');
}
},
'star-triangle-down': {
n: 20,
- f: function(r) {
- var x = d3.round(r * Math.sqrt(3) * 0.8, 2);
- var y1 = d3.round(r * 0.8, 2);
- var y2 = d3.round(r * 1.6, 2);
- var rc = d3.round(r * 4, 2);
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var x = round(r * sqrt3 * 0.8, 2);
+ var y1 = round(r * 0.8, 2);
+ var y2 = round(r * 1.6, 2);
+ var rc = round(r * 4, 2);
var aPart = 'A ' + rc + ',' + rc + ' 0 0 1 ';
- return 'M' + x + ',-' + y1 + aPart + '-' + x + ',-' + y1 +
- aPart + '0,' + y2 + aPart + x + ',-' + y1 + 'Z';
+ return align(angle, standoff, 'M' + x + ',-' + y1 + aPart + '-' + x + ',-' + y1 +
+ aPart + '0,' + y2 + aPart + x + ',-' + y1 + 'Z');
}
},
'star-square': {
n: 21,
- f: function(r) {
- var rp = d3.round(r * 1.1, 2);
- var rc = d3.round(r * 2, 2);
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rp = round(r * 1.1, 2);
+ var rc = round(r * 2, 2);
var aPart = 'A ' + rc + ',' + rc + ' 0 0 1 ';
- return 'M-' + rp + ',-' + rp + aPart + '-' + rp + ',' + rp +
+ return align(angle, standoff, 'M-' + rp + ',-' + rp + aPart + '-' + rp + ',' + rp +
aPart + rp + ',' + rp + aPart + rp + ',-' + rp +
- aPart + '-' + rp + ',-' + rp + 'Z';
+ aPart + '-' + rp + ',-' + rp + 'Z');
}
},
'star-diamond': {
n: 22,
- f: function(r) {
- var rp = d3.round(r * 1.4, 2);
- var rc = d3.round(r * 1.9, 2);
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rp = round(r * 1.4, 2);
+ var rc = round(r * 1.9, 2);
var aPart = 'A ' + rc + ',' + rc + ' 0 0 1 ';
- return 'M-' + rp + ',0' + aPart + '0,' + rp +
+ return align(angle, standoff, 'M-' + rp + ',0' + aPart + '0,' + rp +
aPart + rp + ',0' + aPart + '0,-' + rp +
- aPart + '-' + rp + ',0' + 'Z';
+ aPart + '-' + rp + ',0' + 'Z');
}
},
'diamond-tall': {
n: 23,
- f: function(r) {
- var x = d3.round(r * 0.7, 2);
- var y = d3.round(r * 1.4, 2);
- return 'M0,' + y + 'L' + x + ',0L0,-' + y + 'L-' + x + ',0Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var x = round(r * 0.7, 2);
+ var y = round(r * 1.4, 2);
+ return align(angle, standoff, 'M0,' + y + 'L' + x + ',0L0,-' + y + 'L-' + x + ',0Z');
}
},
'diamond-wide': {
n: 24,
- f: function(r) {
- var x = d3.round(r * 1.4, 2);
- var y = d3.round(r * 0.7, 2);
- return 'M0,' + y + 'L' + x + ',0L0,-' + y + 'L-' + x + ',0Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var x = round(r * 1.4, 2);
+ var y = round(r * 0.7, 2);
+ return align(angle, standoff, 'M0,' + y + 'L' + x + ',0L0,-' + y + 'L-' + x + ',0Z');
}
},
hourglass: {
n: 25,
- f: function(r) {
- var rs = d3.round(r, 2);
- return 'M' + rs + ',' + rs + 'H-' + rs + 'L' + rs + ',-' + rs + 'H-' + rs + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rs = round(r, 2);
+ return align(angle, standoff, 'M' + rs + ',' + rs + 'H-' + rs + 'L' + rs + ',-' + rs + 'H-' + rs + 'Z');
},
noDot: true
},
bowtie: {
n: 26,
- f: function(r) {
- var rs = d3.round(r, 2);
- return 'M' + rs + ',' + rs + 'V-' + rs + 'L-' + rs + ',' + rs + 'V-' + rs + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rs = round(r, 2);
+ return align(angle, standoff, 'M' + rs + ',' + rs + 'V-' + rs + 'L-' + rs + ',' + rs + 'V-' + rs + 'Z');
},
noDot: true
},
'circle-cross': {
n: 27,
- f: function(r) {
- var rs = d3.round(r, 2);
- return 'M0,' + rs + 'V-' + rs + 'M' + rs + ',0H-' + rs +
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rs = round(r, 2);
+ return align(angle, standoff, 'M0,' + rs + 'V-' + rs + 'M' + rs + ',0H-' + rs +
'M' + rs + ',0A' + rs + ',' + rs + ' 0 1,1 0,-' + rs +
- 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z';
+ 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z');
},
needLine: true,
noDot: true
},
'circle-x': {
n: 28,
- f: function(r) {
- var rs = d3.round(r, 2);
- var rc = d3.round(r / Math.sqrt(2), 2);
- return 'M' + rc + ',' + rc + 'L-' + rc + ',-' + rc +
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rs = round(r, 2);
+ var rc = round(r / sqrt2, 2);
+ return align(angle, standoff, 'M' + rc + ',' + rc + 'L-' + rc + ',-' + rc +
'M' + rc + ',-' + rc + 'L-' + rc + ',' + rc +
'M' + rs + ',0A' + rs + ',' + rs + ' 0 1,1 0,-' + rs +
- 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z';
+ 'A' + rs + ',' + rs + ' 0 0,1 ' + rs + ',0Z');
},
needLine: true,
noDot: true
},
'square-cross': {
n: 29,
- f: function(r) {
- var rs = d3.round(r, 2);
- return 'M0,' + rs + 'V-' + rs + 'M' + rs + ',0H-' + rs +
- 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rs = round(r, 2);
+ return align(angle, standoff, 'M0,' + rs + 'V-' + rs + 'M' + rs + ',0H-' + rs +
+ 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z');
},
needLine: true,
noDot: true
},
'square-x': {
n: 30,
- f: function(r) {
- var rs = d3.round(r, 2);
- return 'M' + rs + ',' + rs + 'L-' + rs + ',-' + rs +
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rs = round(r, 2);
+ return align(angle, standoff, 'M' + rs + ',' + rs + 'L-' + rs + ',-' + rs +
'M' + rs + ',-' + rs + 'L-' + rs + ',' + rs +
- 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z';
+ 'M' + rs + ',' + rs + 'H-' + rs + 'V-' + rs + 'H' + rs + 'Z');
},
needLine: true,
noDot: true
},
'diamond-cross': {
n: 31,
- f: function(r) {
- var rd = d3.round(r * 1.3, 2);
- return 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z' +
- 'M0,-' + rd + 'V' + rd + 'M-' + rd + ',0H' + rd;
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rd = round(r * 1.3, 2);
+ return align(angle, standoff, 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z' +
+ 'M0,-' + rd + 'V' + rd + 'M-' + rd + ',0H' + rd);
},
needLine: true,
noDot: true
},
'diamond-x': {
n: 32,
- f: function(r) {
- var rd = d3.round(r * 1.3, 2);
- var r2 = d3.round(r * 0.65, 2);
- return 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z' +
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rd = round(r * 1.3, 2);
+ var r2 = round(r * 0.65, 2);
+ return align(angle, standoff, 'M' + rd + ',0L0,' + rd + 'L-' + rd + ',0L0,-' + rd + 'Z' +
'M-' + r2 + ',-' + r2 + 'L' + r2 + ',' + r2 +
- 'M-' + r2 + ',' + r2 + 'L' + r2 + ',-' + r2;
+ 'M-' + r2 + ',' + r2 + 'L' + r2 + ',-' + r2);
},
needLine: true,
noDot: true
},
'cross-thin': {
n: 33,
- f: function(r) {
- var rc = d3.round(r * 1.4, 2);
- return 'M0,' + rc + 'V-' + rc + 'M' + rc + ',0H-' + rc;
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rc = round(r * 1.4, 2);
+ return align(angle, standoff, 'M0,' + rc + 'V-' + rc + 'M' + rc + ',0H-' + rc);
},
needLine: true,
noDot: true,
@@ -351,10 +428,12 @@ module.exports = {
},
'x-thin': {
n: 34,
- f: function(r) {
- var rx = d3.round(r, 2);
- return 'M' + rx + ',' + rx + 'L-' + rx + ',-' + rx +
- 'M' + rx + ',-' + rx + 'L-' + rx + ',' + rx;
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rx = round(r, 2);
+ return align(angle, standoff, 'M' + rx + ',' + rx + 'L-' + rx + ',-' + rx +
+ 'M' + rx + ',-' + rx + 'L-' + rx + ',' + rx);
},
needLine: true,
noDot: true,
@@ -362,12 +441,14 @@ module.exports = {
},
asterisk: {
n: 35,
- f: function(r) {
- var rc = d3.round(r * 1.2, 2);
- var rs = d3.round(r * 0.85, 2);
- return 'M0,' + rc + 'V-' + rc + 'M' + rc + ',0H-' + rc +
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rc = round(r * 1.2, 2);
+ var rs = round(r * 0.85, 2);
+ return align(angle, standoff, 'M0,' + rc + 'V-' + rc + 'M' + rc + ',0H-' + rc +
'M' + rs + ',' + rs + 'L-' + rs + ',-' + rs +
- 'M' + rs + ',-' + rs + 'L-' + rs + ',' + rs;
+ 'M' + rs + ',-' + rs + 'L-' + rs + ',' + rs);
},
needLine: true,
noDot: true,
@@ -375,24 +456,29 @@ module.exports = {
},
hash: {
n: 36,
- f: function(r) {
- var r1 = d3.round(r / 2, 2);
- var r2 = d3.round(r, 2);
- return 'M' + r1 + ',' + r2 + 'V-' + r2 +
- 'm-' + r2 + ',0V' + r2 +
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var r1 = round(r / 2, 2);
+ var r2 = round(r, 2);
+
+ return align(angle, standoff, 'M' + r1 + ',' + r2 + 'V-' + r2 +
+ 'M' + (r1 - r2) + ',-' + r2 + 'V' + r2 +
'M' + r2 + ',' + r1 + 'H-' + r2 +
- 'm0,-' + r2 + 'H' + r2;
+ 'M-' + r2 + ',' + (r1 - r2) + 'H' + r2);
},
needLine: true,
noFill: true
},
'y-up': {
n: 37,
- f: function(r) {
- var x = d3.round(r * 1.2, 2);
- var y0 = d3.round(r * 1.6, 2);
- var y1 = d3.round(r * 0.8, 2);
- return 'M-' + x + ',' + y1 + 'L0,0M' + x + ',' + y1 + 'L0,0M0,-' + y0 + 'L0,0';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var x = round(r * 1.2, 2);
+ var y0 = round(r * 1.6, 2);
+ var y1 = round(r * 0.8, 2);
+ return align(angle, standoff, 'M-' + x + ',' + y1 + 'L0,0M' + x + ',' + y1 + 'L0,0M0,-' + y0 + 'L0,0');
},
needLine: true,
noDot: true,
@@ -400,11 +486,13 @@ module.exports = {
},
'y-down': {
n: 38,
- f: function(r) {
- var x = d3.round(r * 1.2, 2);
- var y0 = d3.round(r * 1.6, 2);
- var y1 = d3.round(r * 0.8, 2);
- return 'M-' + x + ',-' + y1 + 'L0,0M' + x + ',-' + y1 + 'L0,0M0,' + y0 + 'L0,0';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var x = round(r * 1.2, 2);
+ var y0 = round(r * 1.6, 2);
+ var y1 = round(r * 0.8, 2);
+ return align(angle, standoff, 'M-' + x + ',-' + y1 + 'L0,0M' + x + ',-' + y1 + 'L0,0M0,' + y0 + 'L0,0');
},
needLine: true,
noDot: true,
@@ -412,11 +500,13 @@ module.exports = {
},
'y-left': {
n: 39,
- f: function(r) {
- var y = d3.round(r * 1.2, 2);
- var x0 = d3.round(r * 1.6, 2);
- var x1 = d3.round(r * 0.8, 2);
- return 'M' + x1 + ',' + y + 'L0,0M' + x1 + ',-' + y + 'L0,0M-' + x0 + ',0L0,0';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var y = round(r * 1.2, 2);
+ var x0 = round(r * 1.6, 2);
+ var x1 = round(r * 0.8, 2);
+ return align(angle, standoff, 'M' + x1 + ',' + y + 'L0,0M' + x1 + ',-' + y + 'L0,0M-' + x0 + ',0L0,0');
},
needLine: true,
noDot: true,
@@ -424,11 +514,13 @@ module.exports = {
},
'y-right': {
n: 40,
- f: function(r) {
- var y = d3.round(r * 1.2, 2);
- var x0 = d3.round(r * 1.6, 2);
- var x1 = d3.round(r * 0.8, 2);
- return 'M-' + x1 + ',' + y + 'L0,0M-' + x1 + ',-' + y + 'L0,0M' + x0 + ',0L0,0';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var y = round(r * 1.2, 2);
+ var x0 = round(r * 1.6, 2);
+ var x1 = round(r * 0.8, 2);
+ return align(angle, standoff, 'M-' + x1 + ',' + y + 'L0,0M-' + x1 + ',-' + y + 'L0,0M' + x0 + ',0L0,0');
},
needLine: true,
noDot: true,
@@ -436,9 +528,11 @@ module.exports = {
},
'line-ew': {
n: 41,
- f: function(r) {
- var rc = d3.round(r * 1.4, 2);
- return 'M' + rc + ',0H-' + rc;
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rc = round(r * 1.4, 2);
+ return align(angle, standoff, 'M' + rc + ',0H-' + rc);
},
needLine: true,
noDot: true,
@@ -446,9 +540,11 @@ module.exports = {
},
'line-ns': {
n: 42,
- f: function(r) {
- var rc = d3.round(r * 1.4, 2);
- return 'M0,' + rc + 'V-' + rc;
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rc = round(r * 1.4, 2);
+ return align(angle, standoff, 'M0,' + rc + 'V-' + rc);
},
needLine: true,
noDot: true,
@@ -456,9 +552,11 @@ module.exports = {
},
'line-ne': {
n: 43,
- f: function(r) {
- var rx = d3.round(r, 2);
- return 'M' + rx + ',-' + rx + 'L-' + rx + ',' + rx;
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rx = round(r, 2);
+ return align(angle, standoff, 'M' + rx + ',-' + rx + 'L-' + rx + ',' + rx);
},
needLine: true,
noDot: true,
@@ -466,9 +564,11 @@ module.exports = {
},
'line-nw': {
n: 44,
- f: function(r) {
- var rx = d3.round(r, 2);
- return 'M' + rx + ',' + rx + 'L-' + rx + ',-' + rx;
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rx = round(r, 2);
+ return align(angle, standoff, 'M' + rx + ',' + rx + 'L-' + rx + ',-' + rx);
},
needLine: true,
noDot: true,
@@ -476,78 +576,235 @@ module.exports = {
},
'arrow-up': {
n: 45,
- f: function(r) {
- var rx = d3.round(r, 2);
- var ry = d3.round(r * 2, 2);
- return 'M0,0L-' + rx + ',' + ry + 'H' + rx + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rx = round(r, 2);
+ var ry = round(r * 2, 2);
+ return align(angle, standoff, 'M0,0L-' + rx + ',' + ry + 'H' + rx + 'Z');
},
+ backoff: 1,
noDot: true
},
'arrow-down': {
n: 46,
- f: function(r) {
- var rx = d3.round(r, 2);
- var ry = d3.round(r * 2, 2);
- return 'M0,0L-' + rx + ',-' + ry + 'H' + rx + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rx = round(r, 2);
+ var ry = round(r * 2, 2);
+ return align(angle, standoff, 'M0,0L-' + rx + ',-' + ry + 'H' + rx + 'Z');
},
noDot: true
},
'arrow-left': {
n: 47,
- f: function(r) {
- var rx = d3.round(r * 2, 2);
- var ry = d3.round(r, 2);
- return 'M0,0L' + rx + ',-' + ry + 'V' + ry + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rx = round(r * 2, 2);
+ var ry = round(r, 2);
+ return align(angle, standoff, 'M0,0L' + rx + ',-' + ry + 'V' + ry + 'Z');
},
noDot: true
},
'arrow-right': {
n: 48,
- f: function(r) {
- var rx = d3.round(r * 2, 2);
- var ry = d3.round(r, 2);
- return 'M0,0L-' + rx + ',-' + ry + 'V' + ry + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rx = round(r * 2, 2);
+ var ry = round(r, 2);
+ return align(angle, standoff, 'M0,0L-' + rx + ',-' + ry + 'V' + ry + 'Z');
},
noDot: true
},
'arrow-bar-up': {
n: 49,
- f: function(r) {
- var rx = d3.round(r, 2);
- var ry = d3.round(r * 2, 2);
- return 'M-' + rx + ',0H' + rx + 'M0,0L-' + rx + ',' + ry + 'H' + rx + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rx = round(r, 2);
+ var ry = round(r * 2, 2);
+ return align(angle, standoff, 'M-' + rx + ',0H' + rx + 'M0,0L-' + rx + ',' + ry + 'H' + rx + 'Z');
},
+ backoff: 1,
needLine: true,
noDot: true
},
'arrow-bar-down': {
n: 50,
- f: function(r) {
- var rx = d3.round(r, 2);
- var ry = d3.round(r * 2, 2);
- return 'M-' + rx + ',0H' + rx + 'M0,0L-' + rx + ',-' + ry + 'H' + rx + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rx = round(r, 2);
+ var ry = round(r * 2, 2);
+ return align(angle, standoff, 'M-' + rx + ',0H' + rx + 'M0,0L-' + rx + ',-' + ry + 'H' + rx + 'Z');
},
needLine: true,
noDot: true
},
'arrow-bar-left': {
n: 51,
- f: function(r) {
- var rx = d3.round(r * 2, 2);
- var ry = d3.round(r, 2);
- return 'M0,-' + ry + 'V' + ry + 'M0,0L' + rx + ',-' + ry + 'V' + ry + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rx = round(r * 2, 2);
+ var ry = round(r, 2);
+ return align(angle, standoff, 'M0,-' + ry + 'V' + ry + 'M0,0L' + rx + ',-' + ry + 'V' + ry + 'Z');
},
needLine: true,
noDot: true
},
'arrow-bar-right': {
n: 52,
- f: function(r) {
- var rx = d3.round(r * 2, 2);
- var ry = d3.round(r, 2);
- return 'M0,-' + ry + 'V' + ry + 'M0,0L-' + rx + ',-' + ry + 'V' + ry + 'Z';
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var rx = round(r * 2, 2);
+ var ry = round(r, 2);
+ return align(angle, standoff, 'M0,-' + ry + 'V' + ry + 'M0,0L-' + rx + ',-' + ry + 'V' + ry + 'Z');
},
needLine: true,
noDot: true
+ },
+ 'arrow': {
+ n: 53,
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var headAngle = PI / 2.5; // 36 degrees - golden ratio
+ var x = 2 * r * cos(headAngle);
+ var y = 2 * r * sin(headAngle);
+
+ return align(angle, standoff,
+ 'M0,0' +
+ 'L' + -x + ',' + y +
+ 'L' + x + ',' + y +
+ 'Z'
+ );
+ },
+ backoff: 0.9,
+ noDot: true
+ },
+ 'arrow-wide': {
+ n: 54,
+ f: function(r, angle, standoff) {
+ if(skipAngle(angle)) return emptyPath;
+
+ var headAngle = PI / 4; // 90 degrees
+ var x = 2 * r * cos(headAngle);
+ var y = 2 * r * sin(headAngle);
+
+ return align(angle, standoff,
+ 'M0,0' +
+ 'L' + -x + ',' + y +
+ 'A ' + 2 * r + ',' + 2 * r + ' 0 0 1 ' + x + ',' + y +
+ 'Z'
+ );
+ },
+ backoff: 0.4,
+ noDot: true
}
};
+
+function skipAngle(angle) {
+ return angle === null;
+}
+
+var lastPathIn, lastPathOut;
+var lastAngle, lastStandoff;
+
+function align(angle, standoff, path) {
+ if((!angle || angle % 360 === 0) && !standoff) return path;
+
+ if(
+ lastAngle === angle &&
+ lastStandoff === standoff &&
+ lastPathIn === path
+ ) return lastPathOut;
+
+ lastAngle = angle;
+ lastStandoff = standoff;
+ lastPathIn = path;
+
+ function rotate(t, xy) {
+ var cosT = cos(t);
+ var sinT = sin(t);
+
+ var x = xy[0];
+ var y = xy[1] + (standoff || 0);
+ return [
+ x * cosT - y * sinT,
+ x * sinT + y * cosT
+ ];
+ }
+
+ var t = angle / 180 * PI;
+
+ var x = 0;
+ var y = 0;
+ var cmd = parseSvgPath(path);
+ var str = '';
+
+ for(var i = 0; i < cmd.length; i++) {
+ var cmdI = cmd[i];
+ var op = cmdI[0];
+
+ var x0 = x;
+ var y0 = y;
+
+ if(op === 'M' || op === 'L') {
+ x = +cmdI[1];
+ y = +cmdI[2];
+ } else if(op === 'm' || op === 'l') {
+ x += +cmdI[1];
+ y += +cmdI[2];
+ } else if(op === 'H') {
+ x = +cmdI[1];
+ } else if(op === 'h') {
+ x += +cmdI[1];
+ } else if(op === 'V') {
+ y = +cmdI[1];
+ } else if(op === 'v') {
+ y += +cmdI[1];
+ } else if(op === 'A') {
+ x = +cmdI[1];
+ y = +cmdI[2];
+
+ var E = rotate(t, [+cmdI[6], +cmdI[7]]);
+ cmdI[6] = E[0];
+ cmdI[7] = E[1];
+ cmdI[3] = +cmdI[3] + angle;
+ }
+
+ // change from H, V, h, v to L or l
+ if(op === 'H' || op === 'V') op = 'L';
+ if(op === 'h' || op === 'v') op = 'l';
+
+ if(op === 'm' || op === 'l') {
+ x -= x0;
+ y -= y0;
+ }
+
+ var B = rotate(t, [x, y]);
+
+ if(op === 'H' || op === 'V') op = 'L';
+
+
+ if(
+ op === 'M' || op === 'L' ||
+ op === 'm' || op === 'l'
+ ) {
+ cmdI[1] = B[0];
+ cmdI[2] = B[1];
+ }
+ cmdI[0] = op;
+
+ str += cmdI[0] + cmdI.slice(1).join(',');
+ }
+
+ lastPathOut = str;
+
+ return str;
+}
diff --git a/src/components/selections/select.js b/src/components/selections/select.js
index 9155f5417cd..e2c94201fa7 100644
--- a/src/components/selections/select.js
+++ b/src/components/selections/select.js
@@ -1155,13 +1155,13 @@ function reselect(gd, mayEmitSelected, selectionTesters, searchTraces, dragOptio
if(_selectionTesters) {
var _searchTraces = searchTraces;
if(!hadSearchTraces) {
- var _xaxis = getFromId(gd, _xRef, 'x');
- var _yaxis = getFromId(gd, _yRef, 'y');
+ var _xA = getFromId(gd, _xRef, 'x');
+ var _yA = getFromId(gd, _yRef, 'y');
_searchTraces = determineSearchTraces(
gd,
- [_xaxis],
- [_yaxis],
+ [_xA],
+ [_yA],
subplot
);
@@ -1178,8 +1178,8 @@ function reselect(gd, mayEmitSelected, selectionTesters, searchTraces, dragOptio
cd0.t.xpx = [];
cd0.t.ypx = [];
for(var j = 0; j < len; j++) {
- cd0.t.xpx[j] = _xaxis.c2p(x[j]);
- cd0.t.ypx[j] = _yaxis.c2p(y[j]);
+ cd0.t.xpx[j] = _xA.c2p(x[j]);
+ cd0.t.ypx[j] = _yA.c2p(y[j]);
}
}
diff --git a/src/lib/coerce.js b/src/lib/coerce.js
index 731b16bb631..44a56c2323e 100644
--- a/src/lib/coerce.js
+++ b/src/lib/coerce.js
@@ -171,7 +171,7 @@ exports.valObjectMeta = {
'A number (in degree) between -180 and 180.'
].join(' '),
requiredOpts: [],
- otherOpts: ['dflt'],
+ otherOpts: ['dflt', 'arrayOk'],
coerceFunction: function(v, propOut, dflt) {
if(v === 'auto') propOut.set('auto');
else if(!isNumeric(v)) propOut.set(dflt);
diff --git a/src/plots/geo/geo.js b/src/plots/geo/geo.js
index 8665e0162f4..3c057de94b2 100644
--- a/src/plots/geo/geo.js
+++ b/src/plots/geo/geo.js
@@ -67,8 +67,13 @@ module.exports = function createGeo(opts) {
return new Geo(opts);
};
-proto.plot = function(geoCalcData, fullLayout, promises) {
+proto.plot = function(geoCalcData, fullLayout, promises, replot) {
var _this = this;
+ if(replot) return _this.update(geoCalcData, fullLayout, true);
+
+ _this._geoCalcData = geoCalcData;
+ _this._fullLayout = fullLayout;
+
var geoLayout = fullLayout[this.id];
var geoPromises = [];
@@ -79,12 +84,24 @@ proto.plot = function(geoCalcData, fullLayout, promises) {
break;
}
}
+
+ var hasMarkerAngles = false;
for(var i = 0; i < geoCalcData.length; i++) {
- if(geoCalcData[0][0].trace.locationmode) {
+ var trace = geoCalcData[0][0].trace;
+ trace._geo = _this;
+
+ if(trace.locationmode) {
needsTopojson = true;
- break;
+ }
+
+ var marker = trace.marker;
+ if(marker) {
+ var angle = marker.angle;
+ var angleref = marker.angleref;
+ if(angle || angleref === 'north' || angleref === 'previous') hasMarkerAngles = true;
}
}
+ this._hasMarkerAngles = hasMarkerAngles;
if(needsTopojson) {
var topojsonNameNew = topojsonUtils.getTopojsonName(geoLayout);
@@ -137,7 +154,7 @@ proto.fetchTopojson = function() {
});
};
-proto.update = function(geoCalcData, fullLayout) {
+proto.update = function(geoCalcData, fullLayout, replot) {
var geoLayout = fullLayout[this.id];
// important: maps with choropleth traces have a different layer order
@@ -155,11 +172,13 @@ proto.update = function(geoCalcData, fullLayout) {
}
}
- var hasInvalidBounds = this.updateProjection(geoCalcData, fullLayout);
- if(hasInvalidBounds) return;
+ if(!replot) {
+ var hasInvalidBounds = this.updateProjection(geoCalcData, fullLayout);
+ if(hasInvalidBounds) return;
- if(!this.viewInitial || this.scope !== geoLayout.scope) {
- this.saveViewInitial(geoLayout);
+ if(!this.viewInitial || this.scope !== geoLayout.scope) {
+ this.saveViewInitial(geoLayout);
+ }
}
this.scope = geoLayout.scope;
@@ -177,7 +196,7 @@ proto.update = function(geoCalcData, fullLayout) {
var choroplethLayer = this.layers.backplot.select('.choroplethlayer');
this.dataPaths.choropleth = choroplethLayer.selectAll('path');
- this.render();
+ this._render();
};
proto.updateProjection = function(geoCalcData, fullLayout) {
@@ -591,8 +610,16 @@ proto.saveViewInitial = function(geoLayout) {
Lib.extendFlat(this.viewInitial, extra);
};
+proto.render = function(mayRedrawOnUpdates) {
+ if(this._hasMarkerAngles && mayRedrawOnUpdates) {
+ this.plot(this._geoCalcData, this._fullLayout, [], true);
+ } else {
+ this._render();
+ }
+};
+
// [hot code path] (re)draw all paths which depend on the projection
-proto.render = function() {
+proto._render = function() {
var projection = this.projection;
var pathFn = projection.getPath();
var k;
@@ -619,7 +646,7 @@ proto.render = function() {
for(k in this.dataPoints) {
this.dataPoints[k]
.attr('display', hideShowPoints)
- .attr('transform', translatePoints);
+ .attr('transform', translatePoints); // TODO: need to redraw points with marker angle instead of calling translatePoints
}
};
diff --git a/src/plots/geo/zoom.js b/src/plots/geo/zoom.js
index d486122ddbc..2d79d69f581 100644
--- a/src/plots/geo/zoom.js
+++ b/src/plots/geo/zoom.js
@@ -77,7 +77,7 @@ function zoomScoped(geo, projection) {
projection
.scale(d3.event.scale)
.translate(d3.event.translate);
- geo.render();
+ geo.render(true);
var center = projection.invert(geo.midPt);
geo.graphDiv.emit('plotly_relayouting', {
@@ -162,7 +162,7 @@ function zoomNonClipped(geo, projection) {
}
didZoom = true;
- geo.render();
+ geo.render(true);
var rotate = projection.rotate();
var center = projection.invert(geo.midPt);
@@ -268,7 +268,7 @@ function zoomClipped(geo, projection) {
sync(geo, projection, syncCb);
})
.on('zoom.redraw', function() {
- geo.render();
+ geo.render(true);
var _rotate = projection.rotate();
geo.graphDiv.emit('plotly_relayouting', {
diff --git a/src/traces/box/attributes.js b/src/traces/box/attributes.js
index 0d540a40a74..81fdce06524 100644
--- a/src/traces/box/attributes.js
+++ b/src/traces/box/attributes.js
@@ -312,6 +312,8 @@ module.exports = {
{arrayOk: false, editType: 'plot'}),
opacity: extendFlat({}, scatterMarkerAttrs.opacity,
{arrayOk: false, dflt: 1, editType: 'style'}),
+ angle: extendFlat({}, scatterMarkerAttrs.angle,
+ {arrayOk: false, editType: 'calc'}),
size: extendFlat({}, scatterMarkerAttrs.size,
{arrayOk: false, editType: 'calc'}),
color: extendFlat({}, scatterMarkerAttrs.color,
diff --git a/src/traces/box/defaults.js b/src/traces/box/defaults.js
index ad037009559..1a8980d0a64 100644
--- a/src/traces/box/defaults.js
+++ b/src/traces/box/defaults.js
@@ -251,6 +251,8 @@ function handlePointsDefaults(traceIn, traceOut, coerce, opts) {
coerce('marker.symbol');
coerce('marker.opacity');
coerce('marker.size');
+ coerce('marker.angle');
+
coerce('marker.color', traceOut.line.color);
coerce('marker.line.color');
coerce('marker.line.width');
diff --git a/src/traces/choropleth/style.js b/src/traces/choropleth/style.js
index 4ca8671a64d..cbf27d7a89c 100644
--- a/src/traces/choropleth/style.js
+++ b/src/traces/choropleth/style.js
@@ -26,7 +26,7 @@ function styleTrace(gd, calcTrace) {
.style('opacity', marker.opacity);
});
- Drawing.selectedPointStyle(locs, trace, gd);
+ Drawing.selectedPointStyle(locs, trace);
}
function styleOnSelect(gd, calcTrace) {
@@ -34,7 +34,7 @@ function styleOnSelect(gd, calcTrace) {
var trace = calcTrace[0].trace;
if(trace.selectedpoints) {
- Drawing.selectedPointStyle(s.selectAll('.choroplethlocation'), trace, gd);
+ Drawing.selectedPointStyle(s.selectAll('.choroplethlocation'), trace);
} else {
styleTrace(gd, calcTrace);
}
diff --git a/src/traces/scatter/arrays_to_calcdata.js b/src/traces/scatter/arrays_to_calcdata.js
index 44f63d81609..94dfbd06813 100644
--- a/src/traces/scatter/arrays_to_calcdata.js
+++ b/src/traces/scatter/arrays_to_calcdata.js
@@ -24,6 +24,8 @@ module.exports = function arraysToCalcdata(cd, trace) {
Lib.mergeArrayCastPositive(marker.size, cd, 'ms');
Lib.mergeArrayCastPositive(marker.opacity, cd, 'mo');
Lib.mergeArray(marker.symbol, cd, 'mx');
+ Lib.mergeArray(marker.angle, cd, 'ma');
+ Lib.mergeArray(marker.standoff, cd, 'mf');
Lib.mergeArray(marker.color, cd, 'mc');
var markerLine = marker.line;
diff --git a/src/traces/scatter/attributes.js b/src/traces/scatter/attributes.js
index ad59a800fb1..cce2de0cd7d 100644
--- a/src/traces/scatter/attributes.js
+++ b/src/traces/scatter/attributes.js
@@ -292,6 +292,18 @@ module.exports = {
].join(' ')
},
dash: extendFlat({}, dash, {editType: 'style'}),
+ backoff: { // we want to have a similar option for the start of the line
+ valType: 'number',
+ min: 0,
+ dflt: 'auto',
+ arrayOk: true,
+ editType: 'plot',
+ description: [
+ 'Sets the line back off from the end point of the nth line segment (in px).',
+ 'This option is useful e.g. to avoid overlap with arrowhead markers.',
+ 'With *auto* the lines would trim before markers if `marker.angleref` is set to *previous*.'
+ ].join(' ')
+ },
simplify: {
valType: 'boolean',
dflt: true,
@@ -389,6 +401,41 @@ module.exports = {
anim: true,
description: 'Sets the marker opacity.'
},
+ angle: {
+ valType: 'angle',
+ dflt: 0,
+ arrayOk: true,
+ editType: 'plot',
+ anim: false, // TODO: possibly set to true in future
+ description: [
+ 'Sets the marker angle in respect to `angleref`.'
+ ].join(' ')
+ },
+ angleref: {
+ valType: 'enumerated',
+ values: ['previous', 'up'],
+ dflt: 'up',
+ editType: 'plot',
+ anim: false,
+ description: [
+ 'Sets the reference for marker angle.',
+ 'With *previous*, angle 0 points along the line from the previous point to this one.',
+ 'With *up*, angle 0 points toward the top of the screen.'
+ ].join(' ')
+ },
+ standoff: {
+ valType: 'number',
+ min: 0,
+ dflt: 0,
+ arrayOk: true,
+ editType: 'plot',
+ anim: true,
+ description: [
+ 'Moves the marker away from the data point in the direction of `angle` (in px).',
+ 'This can be useful for example if you have another marker at this',
+ 'location and you want to point an arrowhead marker at it.'
+ ].join(' ')
+ },
size: {
valType: 'number',
min: 0,
diff --git a/src/traces/scatter/calc.js b/src/traces/scatter/calc.js
index 2c2ac558a84..a7471c0d85b 100644
--- a/src/traces/scatter/calc.js
+++ b/src/traces/scatter/calc.js
@@ -14,8 +14,8 @@ var calcSelection = require('./calc_selection');
function calc(gd, trace) {
var fullLayout = gd._fullLayout;
- var xa = Axes.getFromId(gd, trace.xaxis || 'x');
- var ya = Axes.getFromId(gd, trace.yaxis || 'y');
+ var xa = trace._xA = Axes.getFromId(gd, trace.xaxis || 'x', 'x');
+ var ya = trace._yA = Axes.getFromId(gd, trace.yaxis || 'y', 'y');
var origX = xa.makeCalcdata(trace, 'x');
var origY = ya.makeCalcdata(trace, 'y');
var xObj = alignPeriod(trace, xa, 'x', origX);
diff --git a/src/traces/scatter/defaults.js b/src/traces/scatter/defaults.js
index 0d47c52c216..33ac037c920 100644
--- a/src/traces/scatter/defaults.js
+++ b/src/traces/scatter/defaults.js
@@ -39,7 +39,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
coerce('mode', defaultMode);
if(subTypes.hasLines(traceOut)) {
- handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
+ handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce, {backoff: true});
handleLineShapeDefaults(traceIn, traceOut, coerce);
coerce('connectgaps');
coerce('line.simplify');
diff --git a/src/traces/scatter/line_defaults.js b/src/traces/scatter/line_defaults.js
index 1812112a077..fe70e8f847a 100644
--- a/src/traces/scatter/line_defaults.js
+++ b/src/traces/scatter/line_defaults.js
@@ -5,6 +5,8 @@ var hasColorscale = require('../../components/colorscale/helpers').hasColorscale
var colorscaleDefaults = require('../../components/colorscale/defaults');
module.exports = function lineDefaults(traceIn, traceOut, defaultColor, layout, coerce, opts) {
+ if(!opts) opts = {};
+
var markerColor = (traceIn.marker || {}).color;
coerce('line.color', defaultColor);
@@ -17,5 +19,7 @@ module.exports = function lineDefaults(traceIn, traceOut, defaultColor, layout,
}
coerce('line.width');
- if(!(opts || {}).noDash) coerce('line.dash');
+
+ if(!opts.noDash) coerce('line.dash');
+ if(opts.backoff) coerce('line.backoff');
};
diff --git a/src/traces/scatter/line_points.js b/src/traces/scatter/line_points.js
index 58c9436dc59..3ae36f952c3 100644
--- a/src/traces/scatter/line_points.js
+++ b/src/traces/scatter/line_points.js
@@ -1,5 +1,6 @@
'use strict';
+var Drawing = require('../../components/drawing');
var numConstants = require('../../constants/numerical');
var BADNUM = numConstants.BADNUM;
var LOG_CLIP = numConstants.LOG_CLIP;
@@ -12,17 +13,20 @@ var constants = require('./constants');
module.exports = function linePoints(d, opts) {
+ var trace = opts.trace || {};
var xa = opts.xaxis;
var ya = opts.yaxis;
var xLog = xa.type === 'log';
var yLog = ya.type === 'log';
var xLen = xa._length;
var yLen = ya._length;
+ var backoff = opts.backoff;
+ var marker = trace.marker;
var connectGaps = opts.connectGaps;
var baseTolerance = opts.baseTolerance;
var shape = opts.shape;
var linear = shape === 'linear';
- var fill = opts.fill && opts.fill !== 'none';
+ var fill = trace.fill && trace.fill !== 'none';
var segments = [];
var minTolerance = constants.minTolerance;
var len = d.length;
@@ -275,7 +279,17 @@ module.exports = function linePoints(d, opts) {
lastXEdge = lastYEdge = 0;
}
+ var arrayMarker = Lib.isArrayOrTypedArray(marker);
+
function addPt(pt) {
+ if(pt && backoff) {
+ pt.i = i;
+ pt.d = d;
+ pt.trace = trace;
+ pt.marker = arrayMarker ? marker[pt.i] : marker;
+ pt.backoff = backoff;
+ }
+
latestXFrac = pt[0] / xLen;
latestYFrac = pt[1] / yLen;
// Are we more than maxScreensAway off-screen any direction?
@@ -446,5 +460,36 @@ module.exports = function linePoints(d, opts) {
segments.push(pts.slice(0, pti));
}
+
+ var lastShapeChar = shape.slice(shape.length - 1);
+ if(backoff && lastShapeChar !== 'h' && lastShapeChar !== 'v') {
+ var trimmed = false;
+ var n = -1;
+ var newSegments = [];
+
+ for(var j = 0; j < segments.length; j++) {
+ for(var k = 0; k < segments[j].length - 1; k++) {
+ var start = segments[j][k];
+ var end = segments[j][k + 1];
+
+ var xy = Drawing.applyBackoff(end, start);
+ if(
+ xy[0] !== end[0] ||
+ xy[1] !== end[1]
+ ) {
+ trimmed = true;
+ }
+ if(!newSegments[n + 1]) {
+ n++;
+ newSegments[n] = [
+ start, [xy[0], xy[1]]
+ ];
+ }
+ }
+ }
+
+ return trimmed ? newSegments : segments;
+ }
+
return segments;
};
diff --git a/src/traces/scatter/marker_defaults.js b/src/traces/scatter/marker_defaults.js
index a881cc7cf3c..c4358730534 100644
--- a/src/traces/scatter/marker_defaults.js
+++ b/src/traces/scatter/marker_defaults.js
@@ -25,6 +25,16 @@ module.exports = function markerDefaults(traceIn, traceOut, defaultColor, layout
coerce('marker.symbol');
coerce('marker.opacity', isBubble ? 0.7 : 1);
coerce('marker.size');
+ if(!opts.noAngle) {
+ coerce('marker.angle');
+ if(!opts.noAngleRef) {
+ coerce('marker.angleref');
+ }
+
+ if(!opts.noStandOff) {
+ coerce('marker.standoff');
+ }
+ }
coerce('marker.color', defaultColor);
if(hasColorscale(traceIn, 'marker')) {
diff --git a/src/traces/scatter/plot.js b/src/traces/scatter/plot.js
index 7fb3e6c3cc9..3a63470687e 100644
--- a/src/traces/scatter/plot.js
+++ b/src/traces/scatter/plot.js
@@ -209,9 +209,11 @@ function plotOne(gd, idx, plotinfo, cdscatter, cdscatterAll, element, transition
segments = linePoints(cdscatter, {
xaxis: xa,
yaxis: ya,
+ trace: trace,
connectGaps: trace.connectgaps,
baseTolerance: Math.max(line.width || 1, 3) / 4,
shape: line.shape,
+ backoff: line.backoff,
simplify: line.simplify,
fill: trace.fill
});
diff --git a/src/traces/scatter3d/defaults.js b/src/traces/scatter3d/defaults.js
index eb9e130565b..2cb922e5be6 100644
--- a/src/traces/scatter3d/defaults.js
+++ b/src/traces/scatter3d/defaults.js
@@ -36,7 +36,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
}
if(subTypes.hasMarkers(traceOut)) {
- handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {noSelect: true});
+ handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {noSelect: true, noAngle: true});
}
if(subTypes.hasText(traceOut)) {
diff --git a/src/traces/scattercarpet/attributes.js b/src/traces/scattercarpet/attributes.js
index 54a81e80b37..6022878cc9a 100644
--- a/src/traces/scattercarpet/attributes.js
+++ b/src/traces/scattercarpet/attributes.js
@@ -61,6 +61,7 @@ module.exports = {
color: scatterLineAttrs.color,
width: scatterLineAttrs.width,
dash: scatterLineAttrs.dash,
+ backoff: scatterLineAttrs.backoff,
shape: extendFlat({}, scatterLineAttrs.shape,
{values: ['linear', 'spline']}),
smoothing: scatterLineAttrs.smoothing,
@@ -87,6 +88,9 @@ module.exports = {
symbol: scatterMarkerAttrs.symbol,
opacity: scatterMarkerAttrs.opacity,
maxdisplayed: scatterMarkerAttrs.maxdisplayed,
+ angle: scatterMarkerAttrs.angle,
+ angleref: scatterMarkerAttrs.angleref,
+ standoff: scatterMarkerAttrs.standoff,
size: scatterMarkerAttrs.size,
sizeref: scatterMarkerAttrs.sizeref,
sizemin: scatterMarkerAttrs.sizemin,
diff --git a/src/traces/scattercarpet/defaults.js b/src/traces/scattercarpet/defaults.js
index 29986064fde..b21f4e956df 100644
--- a/src/traces/scattercarpet/defaults.js
+++ b/src/traces/scattercarpet/defaults.js
@@ -42,7 +42,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
coerce('mode', defaultMode);
if(subTypes.hasLines(traceOut)) {
- handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
+ handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce, {backoff: true});
handleLineShapeDefaults(traceIn, traceOut, coerce);
coerce('connectgaps');
}
diff --git a/src/traces/scattercarpet/plot.js b/src/traces/scattercarpet/plot.js
index d94ae5d6c51..6d7de9cacd1 100644
--- a/src/traces/scattercarpet/plot.js
+++ b/src/traces/scattercarpet/plot.js
@@ -8,13 +8,24 @@ module.exports = function plot(gd, plotinfoproxy, data, layer) {
var i, trace, node;
var carpet = data[0][0].carpet;
+
+ var xaxis = Axes.getFromId(gd, carpet.xaxis || 'x');
+ var yaxis = Axes.getFromId(gd, carpet.yaxis || 'y');
+
// mimic cartesian plotinfo
var plotinfo = {
- xaxis: Axes.getFromId(gd, carpet.xaxis || 'x'),
- yaxis: Axes.getFromId(gd, carpet.yaxis || 'y'),
+ xaxis: xaxis,
+ yaxis: yaxis,
plot: plotinfoproxy.plot,
};
+ for(i = 0; i < data.length; i++) {
+ trace = data[i][0].trace;
+
+ trace._xA = xaxis;
+ trace._yA = yaxis;
+ }
+
scatterPlot(gd, plotinfo, data, layer);
for(i = 0; i < data.length; i++) {
diff --git a/src/traces/scattergeo/attributes.js b/src/traces/scattergeo/attributes.js
index 7a9b7509d21..d80b62c7735 100644
--- a/src/traces/scattergeo/attributes.js
+++ b/src/traces/scattergeo/attributes.js
@@ -114,6 +114,17 @@ module.exports = overrideAll({
marker: extendFlat({
symbol: scatterMarkerAttrs.symbol,
opacity: scatterMarkerAttrs.opacity,
+ angle: scatterMarkerAttrs.angle,
+ angleref: extendFlat({}, scatterMarkerAttrs.angleref, {
+ values: ['previous', 'up', 'north'],
+ description: [
+ 'Sets the reference for marker angle.',
+ 'With *previous*, angle 0 points along the line from the previous point to this one.',
+ 'With *up*, angle 0 points toward the top of the screen.',
+ 'With *north*, angle 0 points north based on the current map projection.',
+ ].join(' ')
+ }),
+ standoff: scatterMarkerAttrs.standoff,
size: scatterMarkerAttrs.size,
sizeref: scatterMarkerAttrs.sizeref,
sizemin: scatterMarkerAttrs.sizemin,
diff --git a/src/traces/scattergl/attributes.js b/src/traces/scattergl/attributes.js
index cf49750ed4f..f458b27086b 100644
--- a/src/traces/scattergl/attributes.js
+++ b/src/traces/scattergl/attributes.js
@@ -67,6 +67,7 @@ var attrs = module.exports = overrideAll({
},
marker: extendFlat({}, colorScaleAttrs('marker'), {
symbol: scatterMarkerAttrs.symbol,
+ angle: scatterMarkerAttrs.angle,
size: scatterMarkerAttrs.size,
sizeref: scatterMarkerAttrs.sizeref,
sizemin: scatterMarkerAttrs.sizemin,
diff --git a/src/traces/scattergl/calc.js b/src/traces/scattergl/calc.js
index d27f12e5fc4..240418b07af 100644
--- a/src/traces/scattergl/calc.js
+++ b/src/traces/scattergl/calc.js
@@ -20,8 +20,9 @@ var TOO_MANY_POINTS = require('./constants').TOO_MANY_POINTS;
module.exports = function calc(gd, trace) {
var fullLayout = gd._fullLayout;
- var xa = AxisIDs.getFromId(gd, trace.xaxis);
- var ya = AxisIDs.getFromId(gd, trace.yaxis);
+ var xa = trace._xA = AxisIDs.getFromId(gd, trace.xaxis, 'x');
+ var ya = trace._yA = AxisIDs.getFromId(gd, trace.yaxis, 'y');
+
var subplot = fullLayout._plots[trace.xaxis + trace.yaxis];
var len = trace._length;
var hasTooManyPoints = len >= TOO_MANY_POINTS;
diff --git a/src/traces/scattergl/convert.js b/src/traces/scattergl/convert.js
index 3a42dc4050c..66c43d753cb 100644
--- a/src/traces/scattergl/convert.js
+++ b/src/traces/scattergl/convert.js
@@ -50,9 +50,9 @@ function convertStyle(gd, trace) {
}
if(subTypes.hasMarkers(trace)) {
- opts.marker = convertMarkerStyle(trace);
- opts.markerSel = convertMarkerSelection(trace, trace.selected);
- opts.markerUnsel = convertMarkerSelection(trace, trace.unselected);
+ opts.marker = convertMarkerStyle(gd, trace);
+ opts.markerSel = convertMarkerSelection(gd, trace, trace.selected);
+ opts.markerUnsel = convertMarkerSelection(gd, trace, trace.unselected);
if(!trace.unselected && Lib.isArrayOrTypedArray(trace.marker.opacity)) {
var mo = trace.marker.opacity;
@@ -207,13 +207,14 @@ function convertTextStyle(gd, trace) {
}
-function convertMarkerStyle(trace) {
+function convertMarkerStyle(gd, trace) {
var count = trace._length;
var optsIn = trace.marker;
var optsOut = {};
var i;
var multiSymbol = Lib.isArrayOrTypedArray(optsIn.symbol);
+ var multiAngle = Lib.isArrayOrTypedArray(optsIn.angle);
var multiColor = Lib.isArrayOrTypedArray(optsIn.color);
var multiLineColor = Lib.isArrayOrTypedArray(optsIn.line.color);
var multiOpacity = Lib.isArrayOrTypedArray(optsIn.opacity);
@@ -224,10 +225,14 @@ function convertMarkerStyle(trace) {
if(!multiSymbol) isOpen = helpers.isOpenSymbol(optsIn.symbol);
// prepare colors
- if(multiSymbol || multiColor || multiLineColor || multiOpacity) {
+ if(multiSymbol || multiColor || multiLineColor || multiOpacity || multiAngle) {
+ optsOut.symbols = new Array(count);
+ optsOut.angles = new Array(count);
optsOut.colors = new Array(count);
optsOut.borderColors = new Array(count);
+ var symbols = optsIn.symbol;
+ var angles = optsIn.angle;
var colors = formatColor(optsIn, optsIn.opacity, count);
var borderColors = formatColor(optsIn.line, optsIn.opacity, count);
@@ -245,14 +250,29 @@ function convertMarkerStyle(trace) {
colors[i] = color;
}
}
+ if(!Array.isArray(symbols)) {
+ var symbol = symbols;
+ symbols = Array(count);
+ for(i = 0; i < count; i++) {
+ symbols[i] = symbol;
+ }
+ }
+ if(!Array.isArray(angles)) {
+ var angle = angles;
+ angles = Array(count);
+ for(i = 0; i < count; i++) {
+ angles[i] = angle;
+ }
+ }
+ optsOut.symbols = symbols;
+ optsOut.angles = angles;
optsOut.colors = colors;
optsOut.borderColors = borderColors;
for(i = 0; i < count; i++) {
if(multiSymbol) {
- var symbol = optsIn.symbol[i];
- isOpen = helpers.isOpenSymbol(symbol);
+ isOpen = helpers.isOpenSymbol(optsIn.symbol[i]);
}
if(isOpen) {
borderColors[i] = colors[i].slice();
@@ -262,6 +282,14 @@ function convertMarkerStyle(trace) {
}
optsOut.opacity = trace.opacity;
+
+ optsOut.markers = new Array(count);
+ for(i = 0; i < count; i++) {
+ optsOut.markers[i] = getSymbolSdf({
+ mx: optsOut.symbols[i],
+ ma: optsOut.angles[i]
+ }, trace);
+ }
} else {
if(isOpen) {
optsOut.color = rgba(optsIn.color, 'uint8');
@@ -273,16 +301,11 @@ function convertMarkerStyle(trace) {
}
optsOut.opacity = trace.opacity * optsIn.opacity;
- }
- // prepare symbols
- if(multiSymbol) {
- optsOut.markers = new Array(count);
- for(i = 0; i < count; i++) {
- optsOut.markers[i] = getSymbolSdf(optsIn.symbol[i]);
- }
- } else {
- optsOut.marker = getSymbolSdf(optsIn.symbol);
+ optsOut.marker = getSymbolSdf({
+ mx: optsIn.symbol,
+ ma: optsIn.angle
+ }, trace);
}
// prepare sizes
@@ -330,14 +353,14 @@ function convertMarkerStyle(trace) {
return optsOut;
}
-function convertMarkerSelection(trace, target) {
+function convertMarkerSelection(gd, trace, target) {
var optsIn = trace.marker;
var optsOut = {};
if(!target) return optsOut;
if(target.marker && target.marker.symbol) {
- optsOut = convertMarkerStyle(Lib.extendFlat({}, optsIn, target.marker));
+ optsOut = convertMarkerStyle(gd, Lib.extendFlat({}, optsIn, target.marker));
} else if(target.marker) {
if(target.marker.size) optsOut.size = target.marker.size;
if(target.marker.color) optsOut.colors = target.marker.color;
@@ -389,7 +412,8 @@ var SYMBOL_STROKE = constants.SYMBOL_STROKE;
var SYMBOL_SDF = {};
var SYMBOL_SVG_CIRCLE = Drawing.symbolFuncs[0](SYMBOL_SIZE * 0.05);
-function getSymbolSdf(symbol) {
+function getSymbolSdf(d, trace) {
+ var symbol = d.mx;
if(symbol === 'circle') return null;
var symbolPath, symbolSdf;
@@ -400,13 +424,17 @@ function getSymbolSdf(symbol) {
var isDot = helpers.isDotSymbol(symbol);
+ // until we may handle angles in shader?
+ if(d.ma) symbol += '_' + d.ma;
+
// get symbol sdf from cache or generate it
if(SYMBOL_SDF[symbol]) return SYMBOL_SDF[symbol];
+ var angle = Drawing.getMarkerAngle(d, trace);
if(isDot && !symbolNoDot) {
- symbolPath = symbolFunc(SYMBOL_SIZE * 1.1) + SYMBOL_SVG_CIRCLE;
+ symbolPath = symbolFunc(SYMBOL_SIZE * 1.1, angle) + SYMBOL_SVG_CIRCLE;
} else {
- symbolPath = symbolFunc(SYMBOL_SIZE);
+ symbolPath = symbolFunc(SYMBOL_SIZE, angle);
}
symbolSdf = svgSdf(symbolPath, {
@@ -415,6 +443,7 @@ function getSymbolSdf(symbol) {
viewBox: [-SYMBOL_SIZE, -SYMBOL_SIZE, SYMBOL_SIZE, SYMBOL_SIZE],
stroke: symbolNoFill ? SYMBOL_STROKE : -SYMBOL_STROKE
});
+
SYMBOL_SDF[symbol] = symbolSdf;
return symbolSdf || null;
@@ -545,8 +574,8 @@ function convertLinePositions(gd, trace, positions) {
function convertErrorBarPositions(gd, trace, positions, x, y) {
var makeComputeError = Registry.getComponentMethod('errorbars', 'makeComputeError');
- var xa = AxisIDs.getFromId(gd, trace.xaxis);
- var ya = AxisIDs.getFromId(gd, trace.yaxis);
+ var xa = AxisIDs.getFromId(gd, trace.xaxis, 'x');
+ var ya = AxisIDs.getFromId(gd, trace.yaxis, 'y');
var count = positions.length / 2;
var out = {};
diff --git a/src/traces/scattergl/defaults.js b/src/traces/scattergl/defaults.js
index b4cce07a5d7..a15ff09e254 100644
--- a/src/traces/scattergl/defaults.js
+++ b/src/traces/scattergl/defaults.js
@@ -46,7 +46,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
}
if(subTypes.hasMarkers(traceOut)) {
- handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce);
+ handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {noAngleRef: true, noStandOff: true});
coerce('marker.line.width', isOpen || isBubble ? 1 : 0);
}
diff --git a/src/traces/scattergl/hover.js b/src/traces/scattergl/hover.js
index 41e25458f6f..74efc4776b3 100644
--- a/src/traces/scattergl/hover.js
+++ b/src/traces/scattergl/hover.js
@@ -139,6 +139,7 @@ function calcHover(pointData, x, y, trace) {
di.ms = Lib.isArrayOrTypedArray(marker.size) ? marker.size[id] : marker.size;
di.mo = Lib.isArrayOrTypedArray(marker.opacity) ? marker.opacity[id] : marker.opacity;
di.mx = Lib.isArrayOrTypedArray(marker.symbol) ? marker.symbol[id] : marker.symbol;
+ di.ma = Lib.isArrayOrTypedArray(marker.angle) ? marker.angle[id] : marker.angle;
di.mc = Lib.isArrayOrTypedArray(marker.color) ? marker.color[id] : marker.color;
}
diff --git a/src/traces/scattermapbox/defaults.js b/src/traces/scattermapbox/defaults.js
index 7d6747783ad..e3b87adc3df 100644
--- a/src/traces/scattermapbox/defaults.js
+++ b/src/traces/scattermapbox/defaults.js
@@ -33,7 +33,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
}
if(subTypes.hasMarkers(traceOut)) {
- handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {noLine: true});
+ handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {noLine: true, noAngle: true});
coerce('marker.allowoverlap');
coerce('marker.angle');
diff --git a/src/traces/scatterpolar/attributes.js b/src/traces/scatterpolar/attributes.js
index 81b6ae72482..f5d0321c519 100644
--- a/src/traces/scatterpolar/attributes.js
+++ b/src/traces/scatterpolar/attributes.js
@@ -82,6 +82,7 @@ module.exports = {
color: lineAttrs.color,
width: lineAttrs.width,
dash: lineAttrs.dash,
+ backoff: lineAttrs.backoff,
shape: extendFlat({}, lineAttrs.shape, {
values: ['linear', 'spline']
}),
diff --git a/src/traces/scatterpolar/defaults.js b/src/traces/scatterpolar/defaults.js
index 0d18056ba38..5bf2c5e97b9 100644
--- a/src/traces/scatterpolar/defaults.js
+++ b/src/traces/scatterpolar/defaults.js
@@ -30,7 +30,7 @@ function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
if(traceOut.hoveron !== 'fills') coerce('hovertemplate');
if(subTypes.hasLines(traceOut)) {
- handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
+ handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce, {backoff: true});
handleLineShapeDefaults(traceIn, traceOut, coerce);
coerce('connectgaps');
}
diff --git a/src/traces/scatterpolar/plot.js b/src/traces/scatterpolar/plot.js
index a62ff1bdd48..a456701c160 100644
--- a/src/traces/scatterpolar/plot.js
+++ b/src/traces/scatterpolar/plot.js
@@ -6,9 +6,12 @@ var BADNUM = require('../../constants/numerical').BADNUM;
module.exports = function plot(gd, subplot, moduleCalcData) {
var mlayer = subplot.layers.frontplot.select('g.scatterlayer');
+ var xa = subplot.xaxis;
+ var ya = subplot.yaxis;
+
var plotinfo = {
- xaxis: subplot.xaxis,
- yaxis: subplot.yaxis,
+ xaxis: xa,
+ yaxis: ya,
plot: subplot.framework,
layerClipId: subplot._hasClipOnAxisFalse ? subplot.clipIds.forTraces : null
};
@@ -22,6 +25,11 @@ module.exports = function plot(gd, subplot, moduleCalcData) {
var cdi = moduleCalcData[i];
for(var j = 0; j < cdi.length; j++) {
+ if(j === 0) {
+ cdi[0].trace._xA = xa;
+ cdi[0].trace._yA = ya;
+ }
+
var cd = cdi[j];
var r = cd.r;
diff --git a/src/traces/scatterpolargl/defaults.js b/src/traces/scatterpolargl/defaults.js
index 65c25f26a06..6b64bcb3179 100644
--- a/src/traces/scatterpolargl/defaults.js
+++ b/src/traces/scatterpolargl/defaults.js
@@ -35,7 +35,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
}
if(subTypes.hasMarkers(traceOut)) {
- handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce);
+ handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {noAngleRef: true, noStandOff: true});
}
if(subTypes.hasText(traceOut)) {
diff --git a/src/traces/scattersmith/attributes.js b/src/traces/scattersmith/attributes.js
index 90311398341..2344a5fc2a5 100644
--- a/src/traces/scattersmith/attributes.js
+++ b/src/traces/scattersmith/attributes.js
@@ -38,6 +38,7 @@ module.exports = {
color: lineAttrs.color,
width: lineAttrs.width,
dash: lineAttrs.dash,
+ backoff: lineAttrs.backoff,
shape: extendFlat({}, lineAttrs.shape, {
values: ['linear', 'spline']
}),
diff --git a/src/traces/scattersmith/defaults.js b/src/traces/scattersmith/defaults.js
index ad00da49fd4..d1001487803 100644
--- a/src/traces/scattersmith/defaults.js
+++ b/src/traces/scattersmith/defaults.js
@@ -29,7 +29,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
if(traceOut.hoveron !== 'fills') coerce('hovertemplate');
if(subTypes.hasLines(traceOut)) {
- handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
+ handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce, {backoff: true});
handleLineShapeDefaults(traceIn, traceOut, coerce);
coerce('connectgaps');
}
diff --git a/src/traces/scattersmith/plot.js b/src/traces/scattersmith/plot.js
index 5a9c12a3bcf..7bd853abc98 100644
--- a/src/traces/scattersmith/plot.js
+++ b/src/traces/scattersmith/plot.js
@@ -8,9 +8,12 @@ var smith = helpers.smith;
module.exports = function plot(gd, subplot, moduleCalcData) {
var mlayer = subplot.layers.frontplot.select('g.scatterlayer');
+ var xa = subplot.xaxis;
+ var ya = subplot.yaxis;
+
var plotinfo = {
- xaxis: subplot.xaxis,
- yaxis: subplot.yaxis,
+ xaxis: xa,
+ yaxis: ya,
plot: subplot.framework,
layerClipId: subplot._hasClipOnAxisFalse ? subplot.clipIds.forTraces : null
};
@@ -21,6 +24,11 @@ module.exports = function plot(gd, subplot, moduleCalcData) {
var cdi = moduleCalcData[i];
for(var j = 0; j < cdi.length; j++) {
+ if(j === 0) {
+ cdi[0].trace._xA = xa;
+ cdi[0].trace._yA = ya;
+ }
+
var cd = cdi[j];
var real = cd.real;
diff --git a/src/traces/scatterternary/attributes.js b/src/traces/scatterternary/attributes.js
index 1b87b52ff01..23c0bba0621 100644
--- a/src/traces/scatterternary/attributes.js
+++ b/src/traces/scatterternary/attributes.js
@@ -89,6 +89,7 @@ module.exports = {
color: scatterLineAttrs.color,
width: scatterLineAttrs.width,
dash: dash,
+ backoff: scatterLineAttrs.backoff,
shape: extendFlat({}, scatterLineAttrs.shape,
{values: ['linear', 'spline']}),
smoothing: scatterLineAttrs.smoothing,
@@ -115,6 +116,9 @@ module.exports = {
marker: extendFlat({
symbol: scatterMarkerAttrs.symbol,
opacity: scatterMarkerAttrs.opacity,
+ angle: scatterMarkerAttrs.angle,
+ angleref: scatterMarkerAttrs.angleref,
+ standoff: scatterMarkerAttrs.standoff,
maxdisplayed: scatterMarkerAttrs.maxdisplayed,
size: scatterMarkerAttrs.size,
sizeref: scatterMarkerAttrs.sizeref,
diff --git a/src/traces/scatterternary/defaults.js b/src/traces/scatterternary/defaults.js
index 3e1569f0482..cff521b24b9 100644
--- a/src/traces/scatterternary/defaults.js
+++ b/src/traces/scatterternary/defaults.js
@@ -56,7 +56,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
coerce('mode', defaultMode);
if(subTypes.hasLines(traceOut)) {
- handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
+ handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce, {backoff: true});
handleLineShapeDefaults(traceIn, traceOut, coerce);
coerce('connectgaps');
}
diff --git a/src/traces/scatterternary/plot.js b/src/traces/scatterternary/plot.js
index a3d0e4172b5..cac38c11635 100644
--- a/src/traces/scatterternary/plot.js
+++ b/src/traces/scatterternary/plot.js
@@ -9,14 +9,25 @@ module.exports = function plot(gd, ternary, moduleCalcData) {
plotContainer.select('.scatterlayer').selectAll('*').remove();
// mimic cartesian plotinfo
+ var xa = ternary.xaxis;
+ var ya = ternary.yaxis;
+
var plotinfo = {
- xaxis: ternary.xaxis,
- yaxis: ternary.yaxis,
+ xaxis: xa,
+ yaxis: ya,
plot: plotContainer,
layerClipId: ternary._hasClipOnAxisFalse ? ternary.clipIdRelative : null
};
var scatterLayer = ternary.layers.frontplot.select('g.scatterlayer');
+ for(var i = 0; i < moduleCalcData.length; i++) {
+ var cdi = moduleCalcData[i];
+ if(cdi.length) {
+ cdi[0].trace._xA = xa;
+ cdi[0].trace._yA = ya;
+ }
+ }
+
scatterPlot(gd, plotinfo, moduleCalcData, scatterLayer);
};
diff --git a/src/traces/splom/attributes.js b/src/traces/splom/attributes.js
index dfbb585255a..0c1c09b8457 100644
--- a/src/traces/splom/attributes.js
+++ b/src/traces/splom/attributes.js
@@ -19,6 +19,7 @@ var markerLineAttrs = extendFlat(colorScaleAttrs('marker.line', {editTypeOverrid
var markerAttrs = extendFlat(colorScaleAttrs('marker'), {
symbol: scatterMarkerAttrs.symbol,
+ angle: scatterMarkerAttrs.angle,
size: extendFlat({}, scatterMarkerAttrs.size, {editType: 'markerSize'}),
sizeref: scatterMarkerAttrs.sizeref,
sizemin: scatterMarkerAttrs.sizemin,
diff --git a/src/traces/splom/calc.js b/src/traces/splom/calc.js
index c7544278866..5cdb35bcad1 100644
--- a/src/traces/splom/calc.js
+++ b/src/traces/splom/calc.js
@@ -67,7 +67,7 @@ module.exports = function calc(gd, trace) {
}
calcColorscale(gd, trace);
- Lib.extendFlat(opts, convertMarkerStyle(trace));
+ Lib.extendFlat(opts, convertMarkerStyle(gd, trace));
var visibleLength = cdata.length;
var hasTooManyPoints = (visibleLength * commonLength) > TOO_MANY_POINTS;
@@ -94,8 +94,8 @@ module.exports = function calc(gd, trace) {
if(!scene.matrix) scene.matrix = true;
scene.matrixOptions = opts;
- scene.selectedOptions = convertMarkerSelection(trace, trace.selected);
- scene.unselectedOptions = convertMarkerSelection(trace, trace.unselected);
+ scene.selectedOptions = convertMarkerSelection(gd, trace, trace.selected);
+ scene.unselectedOptions = convertMarkerSelection(gd, trace, trace.unselected);
return [{x: false, y: false, t: {}, trace: trace}];
};
diff --git a/src/traces/splom/defaults.js b/src/traces/splom/defaults.js
index 8e450badf07..72cb247733a 100644
--- a/src/traces/splom/defaults.js
+++ b/src/traces/splom/defaults.js
@@ -36,7 +36,7 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
coerce('xhoverformat');
coerce('yhoverformat');
- handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce);
+ handleMarkerDefaults(traceIn, traceOut, defaultColor, layout, coerce, {noAngleRef: true, noStandOff: true});
var isOpen = isOpenSymbol(traceOut.marker.symbol);
var isBubble = subTypes.isBubble(traceOut);
diff --git a/src/traces/splom/edit_style.js b/src/traces/splom/edit_style.js
index f53071295a9..c3abca799ea 100644
--- a/src/traces/splom/edit_style.js
+++ b/src/traces/splom/edit_style.js
@@ -11,7 +11,7 @@ module.exports = function editStyle(gd, cd0) {
if(scene) {
calcColorscale(gd, trace);
- Lib.extendFlat(scene.matrixOptions, convertMarkerStyle(trace));
+ Lib.extendFlat(scene.matrixOptions, convertMarkerStyle(gd, trace));
// TODO [un]selected styles?
var opts = Lib.extendFlat({}, scene.matrixOptions, scene.viewOpts);
diff --git a/src/traces/violin/plot.js b/src/traces/violin/plot.js
index 62f46650266..b46292d319d 100644
--- a/src/traces/violin/plot.js
+++ b/src/traces/violin/plot.js
@@ -13,10 +13,11 @@ module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) {
var xa = plotinfo.xaxis;
var ya = plotinfo.yaxis;
- function makePath(pts) {
+ function makePath(pts, trace) {
var segments = linePoints(pts, {
xaxis: xa,
yaxis: ya,
+ trace: trace,
connectGaps: true,
baseTolerance: 0.75,
shape: 'spline',
@@ -80,7 +81,7 @@ module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) {
pt[t.posLetter] = posCenter + (density[i].v / scale);
pt[t.valLetter] = valAxis.c2l(density[i].t, true);
}
- pathPos = makePath(pts);
+ pathPos = makePath(pts, trace);
}
if(hasNegativeSide) {
@@ -90,7 +91,7 @@ module.exports = function plot(gd, plotinfo, cdViolins, violinLayer) {
pt[t.posLetter] = posCenter - (density[i].v / scale);
pt[t.valLetter] = valAxis.c2l(density[i].t, true);
}
- pathNeg = makePath(pts);
+ pathNeg = makePath(pts, trace);
}
if(hasBothSides) {
diff --git a/test/image/baselines/19.png b/test/image/baselines/19.png
index e98f113080f..1baf427a06c 100644
Binary files a/test/image/baselines/19.png and b/test/image/baselines/19.png differ
diff --git a/test/image/baselines/box_grouped_horz.png b/test/image/baselines/box_grouped_horz.png
index d3c07ef0049..f904a3757cb 100644
Binary files a/test/image/baselines/box_grouped_horz.png and b/test/image/baselines/box_grouped_horz.png differ
diff --git a/test/image/baselines/geo_canadian-cities.png b/test/image/baselines/geo_canadian-cities.png
index 2415bf9248e..aeedf21e9fb 100644
Binary files a/test/image/baselines/geo_canadian-cities.png and b/test/image/baselines/geo_canadian-cities.png differ
diff --git a/test/image/baselines/geo_conic-conformal.png b/test/image/baselines/geo_conic-conformal.png
index b6a6ad20a2d..b4900e61c1c 100644
Binary files a/test/image/baselines/geo_conic-conformal.png and b/test/image/baselines/geo_conic-conformal.png differ
diff --git a/test/image/baselines/geo_scattergeo-out-of-usa.png b/test/image/baselines/geo_scattergeo-out-of-usa.png
index a5679ab2c38..623f7d08cf0 100644
Binary files a/test/image/baselines/geo_scattergeo-out-of-usa.png and b/test/image/baselines/geo_scattergeo-out-of-usa.png differ
diff --git a/test/image/baselines/geo_text_chart_arrays.png b/test/image/baselines/geo_text_chart_arrays.png
index 36d3459582c..0f4a3b5e05a 100644
Binary files a/test/image/baselines/geo_text_chart_arrays.png and b/test/image/baselines/geo_text_chart_arrays.png differ
diff --git a/test/image/baselines/gl2d_marker_symbols.png b/test/image/baselines/gl2d_marker_symbols.png
index 56246eea2ac..c25f6b7fe13 100644
Binary files a/test/image/baselines/gl2d_marker_symbols.png and b/test/image/baselines/gl2d_marker_symbols.png differ
diff --git a/test/image/baselines/glpolar_subplots.png b/test/image/baselines/glpolar_subplots.png
index e603cdaa040..e25d4eb6913 100644
Binary files a/test/image/baselines/glpolar_subplots.png and b/test/image/baselines/glpolar_subplots.png differ
diff --git a/test/image/baselines/marker_symbols.png b/test/image/baselines/marker_symbols.png
index 8a902aabd21..f7ceb938ac2 100644
Binary files a/test/image/baselines/marker_symbols.png and b/test/image/baselines/marker_symbols.png differ
diff --git a/test/image/baselines/polar_direction.png b/test/image/baselines/polar_direction.png
index 17620d34c69..abb99d44401 100644
Binary files a/test/image/baselines/polar_direction.png and b/test/image/baselines/polar_direction.png differ
diff --git a/test/image/baselines/scattercarpet-on-two-carpets.png b/test/image/baselines/scattercarpet-on-two-carpets.png
index 1bca750da1e..c86c3857cb9 100644
Binary files a/test/image/baselines/scattercarpet-on-two-carpets.png and b/test/image/baselines/scattercarpet-on-two-carpets.png differ
diff --git a/test/image/baselines/smith_gaps.png b/test/image/baselines/smith_gaps.png
index 0b5efb1a5d5..25eaa1f3f80 100644
Binary files a/test/image/baselines/smith_gaps.png and b/test/image/baselines/smith_gaps.png differ
diff --git a/test/image/baselines/splom_log.png b/test/image/baselines/splom_log.png
index 39c842cc11d..d12325b9700 100644
Binary files a/test/image/baselines/splom_log.png and b/test/image/baselines/splom_log.png differ
diff --git a/test/image/baselines/ternary_markers.png b/test/image/baselines/ternary_markers.png
index 41740a11fb2..aeed01798be 100644
Binary files a/test/image/baselines/ternary_markers.png and b/test/image/baselines/ternary_markers.png differ
diff --git a/test/image/baselines/violin_ridgeplot.png b/test/image/baselines/violin_ridgeplot.png
index 66d3edbeb37..cb1de0b284c 100644
Binary files a/test/image/baselines/violin_ridgeplot.png and b/test/image/baselines/violin_ridgeplot.png differ
diff --git a/test/image/baselines/z-gl2d_marker_symbols-angle.png b/test/image/baselines/z-gl2d_marker_symbols-angle.png
new file mode 100644
index 00000000000..001d27f695f
Binary files /dev/null and b/test/image/baselines/z-gl2d_marker_symbols-angle.png differ
diff --git a/test/image/baselines/z-line-shape-arrow.png b/test/image/baselines/z-line-shape-arrow.png
new file mode 100644
index 00000000000..8037c4d4625
Binary files /dev/null and b/test/image/baselines/z-line-shape-arrow.png differ
diff --git a/test/image/baselines/z-line-shape-arrow_backoff-auto.png b/test/image/baselines/z-line-shape-arrow_backoff-auto.png
new file mode 100644
index 00000000000..ac2811e4d84
Binary files /dev/null and b/test/image/baselines/z-line-shape-arrow_backoff-auto.png differ
diff --git a/test/image/baselines/z-line-shape-arrow_backoff.png b/test/image/baselines/z-line-shape-arrow_backoff.png
new file mode 100644
index 00000000000..bcab37977e9
Binary files /dev/null and b/test/image/baselines/z-line-shape-arrow_backoff.png differ
diff --git a/test/image/baselines/z-marker-standoff.png b/test/image/baselines/z-marker-standoff.png
new file mode 100644
index 00000000000..54db57a75a5
Binary files /dev/null and b/test/image/baselines/z-marker-standoff.png differ
diff --git a/test/image/baselines/z-marker-standoff_auto-backoff.png b/test/image/baselines/z-marker-standoff_auto-backoff.png
new file mode 100644
index 00000000000..34abdddae0c
Binary files /dev/null and b/test/image/baselines/z-marker-standoff_auto-backoff.png differ
diff --git a/test/image/baselines/z-marker_symbols-angle.png b/test/image/baselines/z-marker_symbols-angle.png
new file mode 100644
index 00000000000..cac234aabbb
Binary files /dev/null and b/test/image/baselines/z-marker_symbols-angle.png differ
diff --git a/test/image/mocks/19.json b/test/image/mocks/19.json
index 007d414dc63..8d645078d05 100644
--- a/test/image/mocks/19.json
+++ b/test/image/mocks/19.json
@@ -1,6 +1,11 @@
{
"data": [
{
+ "marker": {
+ "size": 10,
+ "symbol": "arrow-wide",
+ "angleref": "previous"
+ },
"x": [
1,
2,
@@ -15,6 +20,12 @@
"type": "scatter"
},
{
+ "marker": {
+ "size": 10,
+ "symbol": "arrow",
+ "angleref": "up",
+ "angle": [180, 0, 180]
+ },
"x": [
20,
30,
diff --git a/test/image/mocks/box_grouped_horz.json b/test/image/mocks/box_grouped_horz.json
index 0f9dedb0d9d..fdc0c85eb02 100644
--- a/test/image/mocks/box_grouped_horz.json
+++ b/test/image/mocks/box_grouped_horz.json
@@ -3,7 +3,7 @@
"y": ["day 1", "day 1", "day 1", "day 1", "day 1", "day 1",
"day 2", "day 2", "day 2", "day 2", "day 2", "day 2"],
"name": "kale",
- "marker": {"color": "#3D9970"},
+ "marker": {"color": "#3D9970", "symbol": "arrow-wide", "angle": 0, "size": 10},
"type": "box",
"orientation": "h",
"pointpos": -1.5,
@@ -16,7 +16,7 @@
"y": ["day 1", "day 1", "day 1", "day 1", "day 1", "day 1",
"day 2", "day 2", "day 2", "day 2", "day 2", "day 2"],
"name": "radishes",
- "marker": {"color": "#FF4136"},
+ "marker": {"color": "#FF4136", "symbol": "arrow", "angle": -90, "size": 10},
"type": "box",
"orientation": "h",
"pointpos": -1.5,
@@ -29,7 +29,7 @@
"y": ["day 1", "day 1", "day 1", "day 1", "day 1", "day 1",
"day 2", "day 2", "day 2", "day 2", "day 2", "day 2"],
"name": "carrots",
- "marker": {"color": "#FF851B"},
+ "marker": {"color": "#FF851B", "symbol": "arrow", "angle": 90, "size": 10},
"type": "box",
"orientation": "h",
"pointpos": -1.5,
diff --git a/test/image/mocks/geo_canadian-cities.json b/test/image/mocks/geo_canadian-cities.json
index 11058db5e39..75db415dfdd 100644
--- a/test/image/mocks/geo_canadian-cities.json
+++ b/test/image/mocks/geo_canadian-cities.json
@@ -2,7 +2,7 @@
"data": [
{
"type": "scattergeo",
- "mode": "markers+text",
+ "mode": "markers+lines+text",
"lon": [
-73.57,
-79.24,
@@ -39,7 +39,13 @@
"Winnepeg",
"Regina"
],
+ "line": {
+ "color": "green",
+ "dash": "dot"
+ },
"marker": {
+ "symbol": "arrow-wide",
+ "angleref": "previous",
"size": 10,
"color": [
"#bebada",
diff --git a/test/image/mocks/geo_conic-conformal.json b/test/image/mocks/geo_conic-conformal.json
index e5da3ed1933..60d74a42b56 100644
--- a/test/image/mocks/geo_conic-conformal.json
+++ b/test/image/mocks/geo_conic-conformal.json
@@ -10,6 +10,9 @@
"FRA"
],
"marker": {
+ "symbol": "arrow",
+ "angleref": "north",
+ "angle": [0, -90, 180, 90, 0],
"color": [
80,
20,
diff --git a/test/image/mocks/geo_scattergeo-out-of-usa.json b/test/image/mocks/geo_scattergeo-out-of-usa.json
index 6ed41dc33ec..37d407649ec 100644
--- a/test/image/mocks/geo_scattergeo-out-of-usa.json
+++ b/test/image/mocks/geo_scattergeo-out-of-usa.json
@@ -20009,7 +20009,12 @@
],
"mode": "markers",
"marker": {
- "color": "#19d3f3"
+ "symbol": "arrow",
+ "angleref": "north",
+ "angle": -90,
+ "size": 12,
+ "opacity": 0.1,
+ "color": "blue"
},
"type": "scattergeo"
}
diff --git a/test/image/mocks/geo_text_chart_arrays.json b/test/image/mocks/geo_text_chart_arrays.json
index b6b5a763827..a12e4b2efd3 100644
--- a/test/image/mocks/geo_text_chart_arrays.json
+++ b/test/image/mocks/geo_text_chart_arrays.json
@@ -40,7 +40,9 @@
"Regina"
],
"marker": {
- "size": 10,
+ "symbol": "arrow",
+ "angleref": "north",
+ "size": 20,
"color": [
"#bebada",
"#fdb462",
diff --git a/test/image/mocks/gl2d_marker_symbols.json b/test/image/mocks/gl2d_marker_symbols.json
index 8460619f1b4..a805c471405 100644
--- a/test/image/mocks/gl2d_marker_symbols.json
+++ b/test/image/mocks/gl2d_marker_symbols.json
@@ -8,14 +8,18 @@
1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3,
- 4, 4, 4, 4, 4, 4, 4, 4, 4
+ 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5,
+ 7
],
"y": [
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
- 0, 1, 2, 3, 4, 5, 6, 7, 8
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
],
"marker": {
"symbol": [
@@ -63,7 +67,17 @@
"line-ew",
"line-ns",
"line-ne",
- "line-nw"
+ "line-nw",
+ "arrow-up",
+ "arrow-down",
+ "arrow-left",
+ "arrow-right",
+ "arrow-bar-up",
+ "arrow-bar-down",
+ "arrow-bar-left",
+ "arrow-bar-right",
+ "arrow",
+ "arrow-wide"
],
"color": "blue",
"size": 20,
@@ -117,7 +131,17 @@
"marker symbol: line-ew
number: 41",
"marker symbol: line-ns
number: 42",
"marker symbol: line-ne
number: 43",
- "marker symbol: line-nw
number: 44"
+ "marker symbol: line-nw
number: 44",
+ "marker symbol: arrow-up
number: 45",
+ "marker symbol: arrow-down
number: 46",
+ "marker symbol: arrow-left
number: 47",
+ "marker symbol: arrow-right
number: 48",
+ "marker symbol: arrow-bar-up
number: 49",
+ "marker symbol: arrow-bar-down
number: 50",
+ "marker symbol: arrow-bar-left
number: 51",
+ "marker symbol: arrow-bar-right
number: 52",
+ "marker symbol: arrow
number: 53",
+ "marker symbol: arrow-wide
number: 54"
],
"hoverinfo": "text"
},
@@ -125,18 +149,22 @@
"type": "scattergl",
"mode": "markers",
"x": [
- 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 9, 9, 9, 9, 9, 9, 9, 9, 9
+ 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 14.5, 14.5, 14.5, 14.5, 14.5, 14.5, 14.5, 14.5, 14.5,
+ 16
],
"y": [
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
- 0, 1, 2, 3, 4, 5, 6, 7, 8
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
],
"marker": {
"symbol": [
@@ -184,7 +212,17 @@
"line-ew-open",
"line-ns-open",
"line-ne-open",
- "line-nw-open"
+ "line-nw-open",
+ "arrow-up-open",
+ "arrow-down-open",
+ "arrow-left-open",
+ "arrow-right-open",
+ "arrow-bar-up-open",
+ "arrow-bar-down-open",
+ "arrow-bar-left-open",
+ "arrow-bar-right-open",
+ "arrow-open",
+ "arrow-wide-open"
],
"color": "blue",
"size": 20,
@@ -238,7 +276,17 @@
"marker symbol: line-ew-open
number: 141",
"marker symbol: line-ns-open
number: 142",
"marker symbol: line-ne-open
number: 143",
- "marker symbol: line-nw-open
number: 144"
+ "marker symbol: line-nw-open
number: 144",
+ "marker symbol: arrow-up-open
number: 145",
+ "marker symbol: arrow-down-open
number: 146",
+ "marker symbol: arrow-left-open
number: 147",
+ "marker symbol: arrow-right-open
number: 148",
+ "marker symbol: arrow-bar-up-open
number: 149",
+ "marker symbol: arrow-bar-down-open
number: 150",
+ "marker symbol: arrow-bar-left-open
number: 151",
+ "marker symbol: arrow-bar-right-open
number: 152",
+ "marker symbol: arrow-open
number: 153",
+ "marker symbol: arrow-wide-open
number: 154"
],
"hoverinfo": "text"
},
@@ -246,18 +294,22 @@
"type": "scattergl",
"mode": "markers",
"x": [
- 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 14, 14, 14, 14, 14, 14, 14, 14, 14
+ 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23.5, 23.5, 23.5, 23.5, 23.5, 23.5, 23.5, 23.5, 23.5,
+ 25
],
"y": [
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
- 0, 1, 2, 3, 4, 5, 6, 7, 8
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
],
"marker": {
"symbol": [
@@ -305,7 +357,17 @@
"line-ew-dot",
"line-ns-dot",
"line-ne-dot",
- "line-nw-dot"
+ "line-nw-dot",
+ "arrow-up-dot",
+ "arrow-down-dot",
+ "arrow-left-dot",
+ "arrow-right-dot",
+ "arrow-bar-up-dot",
+ "arrow-bar-down-dot",
+ "arrow-bar-left-dot",
+ "arrow-bar-right-dot",
+ "arrow-dot",
+ "arrow-wide-dot"
],
"color": "blue",
"size": 20,
@@ -359,7 +421,17 @@
"marker symbol: line-ew-dot
number: 241",
"marker symbol: line-ns-dot
number: 242",
"marker symbol: line-ne-dot
number: 243",
- "marker symbol: line-nw-dot
number: 244"
+ "marker symbol: line-nw-dot
number: 244",
+ "marker symbol: arrow-up-dot
number: 245",
+ "marker symbol: arrow-down-dot
number: 246",
+ "marker symbol: arrow-left-dot
number: 247",
+ "marker symbol: arrow-right-dot
number: 248",
+ "marker symbol: arrow-bar-up-dot
number: 249",
+ "marker symbol: arrow-bar-down-dot
number: 250",
+ "marker symbol: arrow-bar-left-dot
number: 251",
+ "marker symbol: arrow-bar-right-dot
number: 252",
+ "marker symbol: arrow-dot
number: 253",
+ "marker symbol: arrow-wide-dot
number: 254"
],
"hoverinfo": "text"
},
@@ -367,18 +439,22 @@
"type": "scattergl",
"mode": "markers",
"x": [
- 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 19, 19, 19, 19, 19, 19, 19, 19, 19
+ 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 30, 30, 30, 30, 30, 30, 30, 30, 30,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 32.5, 32.5, 32.5, 32.5, 32.5, 32.5, 32.5, 32.5, 32.5,
+ 34
],
"y": [
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
- 0, 1, 2, 3, 4, 5, 6, 7, 8
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
],
"marker": {
"symbol": [
@@ -426,7 +502,17 @@
"line-ew-open-dot",
"line-ns-open-dot",
"line-ne-open-dot",
- "line-nw-open-dot"
+ "line-nw-open-dot",
+ "arrow-up-open-dot",
+ "arrow-down-open-dot",
+ "arrow-left-open-dot",
+ "arrow-right-open-dot",
+ "arrow-bar-up-open-dot",
+ "arrow-bar-down-open-dot",
+ "arrow-bar-left-open-dot",
+ "arrow-bar-right-open-dot",
+ "arrow-open-dot",
+ "arrow-wide-open-dot"
],
"color": "blue",
"size": 20,
@@ -480,7 +566,18 @@
"marker symbol: line-ew-open-dot
number: 341",
"marker symbol: line-ns-open-dot
number: 342",
"marker symbol: line-ne-open-dot
number: 343",
- "marker symbol: line-nw-open-dot
number: 344"
+ "marker symbol: line-nw-open-dot
number: 344",
+ "marker symbol: line-nw-open-dot
number: 344",
+ "marker symbol: arrow-up-open-dot
number: 345",
+ "marker symbol: arrow-down-open-dot
number: 346",
+ "marker symbol: arrow-left-open-dot
number: 347",
+ "marker symbol: arrow-right-open-dot
number: 348",
+ "marker symbol: arrow-bar-up-open-dot
number: 349",
+ "marker symbol: arrow-bar-down-open-dot
number: 350",
+ "marker symbol: arrow-bar-left-open-dot
number: 351",
+ "marker symbol: arrow-bar-right-open-dot
number: 352",
+ "marker symbol: arrow-open-dot
number: 353",
+ "marker symbol: arrow-wide-open-dot
number: 354"
],
"hoverinfo": "text"
}
@@ -492,7 +589,7 @@
"b": 0,
"t": 0
},
- "width": 800,
+ "width": 1500,
"height": 500,
"xaxis": {
"showgrid": false,
diff --git a/test/image/mocks/glpolar_subplots.json b/test/image/mocks/glpolar_subplots.json
index 78a58cbda8d..888d36ae69f 100644
--- a/test/image/mocks/glpolar_subplots.json
+++ b/test/image/mocks/glpolar_subplots.json
@@ -6,7 +6,7 @@
"theta": [0, 45, 180],
"text": ["A0", "B0", "C0"],
"hovertext": ["hover A0", "hover B0", "hover C0"],
- "marker": {"symbol": "square", "size": 15},
+ "marker": {"symbol": "arrow", "angle": [0, 135, 180], "size": 15},
"textfont": {
"color": ["red", "green", "blue"],
"size": 20
diff --git a/test/image/mocks/marker_symbols.json b/test/image/mocks/marker_symbols.json
index 7509fa7547f..197af9d1f9b 100644
--- a/test/image/mocks/marker_symbols.json
+++ b/test/image/mocks/marker_symbols.json
@@ -7,14 +7,18 @@
1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3,
- 4, 4, 4, 4, 4, 4, 4, 4, 4
+ 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5,
+ 7
],
"y": [
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
- 0, 1, 2, 3, 4, 5, 6, 7, 8
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
],
"marker": {
"symbol": [
@@ -62,7 +66,17 @@
"line-ew",
"line-ns",
"line-ne",
- "line-nw"
+ "line-nw",
+ "arrow-up",
+ "arrow-down",
+ "arrow-left",
+ "arrow-right",
+ "arrow-bar-up",
+ "arrow-bar-down",
+ "arrow-bar-left",
+ "arrow-bar-right",
+ "arrow",
+ "arrow-wide"
],
"color": "blue",
"size": 20,
@@ -116,25 +130,39 @@
"marker symbol: line-ew
number: 41",
"marker symbol: line-ns
number: 42",
"marker symbol: line-ne
number: 43",
- "marker symbol: line-nw
number: 44"
+ "marker symbol: line-nw
number: 44",
+ "marker symbol: arrow-up
number: 45",
+ "marker symbol: arrow-down
number: 46",
+ "marker symbol: arrow-left
number: 47",
+ "marker symbol: arrow-right
number: 48",
+ "marker symbol: arrow-bar-up
number: 49",
+ "marker symbol: arrow-bar-down
number: 50",
+ "marker symbol: arrow-bar-left
number: 51",
+ "marker symbol: arrow-bar-right
number: 52",
+ "marker symbol: arrow
number: 53",
+ "marker symbol: arrow-wide
number: 54"
],
"hoverinfo": "text"
},
{
"mode": "markers",
"x": [
- 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 9, 9, 9, 9, 9, 9, 9, 9, 9
+ 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 14.5, 14.5, 14.5, 14.5, 14.5, 14.5, 14.5, 14.5, 14.5,
+ 16
],
"y": [
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
- 0, 1, 2, 3, 4, 5, 6, 7, 8
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
],
"marker": {
"symbol": [
@@ -182,7 +210,17 @@
"line-ew-open",
"line-ns-open",
"line-ne-open",
- "line-nw-open"
+ "line-nw-open",
+ "arrow-up-open",
+ "arrow-down-open",
+ "arrow-left-open",
+ "arrow-right-open",
+ "arrow-bar-up-open",
+ "arrow-bar-down-open",
+ "arrow-bar-left-open",
+ "arrow-bar-right-open",
+ "arrow-open",
+ "arrow-wide-open"
],
"color": "blue",
"size": 20,
@@ -236,25 +274,39 @@
"marker symbol: line-ew-open
number: 141",
"marker symbol: line-ns-open
number: 142",
"marker symbol: line-ne-open
number: 143",
- "marker symbol: line-nw-open
number: 144"
+ "marker symbol: line-nw-open
number: 144",
+ "marker symbol: arrow-up-open
number: 145",
+ "marker symbol: arrow-down-open
number: 146",
+ "marker symbol: arrow-left-open
number: 147",
+ "marker symbol: arrow-right-open
number: 148",
+ "marker symbol: arrow-bar-up-open
number: 149",
+ "marker symbol: arrow-bar-down-open
number: 150",
+ "marker symbol: arrow-bar-left-open
number: 151",
+ "marker symbol: arrow-bar-right-open
number: 152",
+ "marker symbol: arrow-open
number: 153",
+ "marker symbol: arrow-wide-open
number: 154"
],
"hoverinfo": "text"
},
{
"mode": "markers",
"x": [
- 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 14, 14, 14, 14, 14, 14, 14, 14, 14
+ 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23.5, 23.5, 23.5, 23.5, 23.5, 23.5, 23.5, 23.5, 23.5,
+ 25
],
"y": [
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
- 0, 1, 2, 3, 4, 5, 6, 7, 8
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
],
"marker": {
"symbol": [
@@ -302,7 +354,17 @@
"line-ew-dot",
"line-ns-dot",
"line-ne-dot",
- "line-nw-dot"
+ "line-nw-dot",
+ "arrow-up-dot",
+ "arrow-down-dot",
+ "arrow-left-dot",
+ "arrow-right-dot",
+ "arrow-bar-up-dot",
+ "arrow-bar-down-dot",
+ "arrow-bar-left-dot",
+ "arrow-bar-right-dot",
+ "arrow-dot",
+ "arrow-wide-dot"
],
"color": "blue",
"size": 20,
@@ -356,25 +418,39 @@
"marker symbol: line-ew-dot
number: 241",
"marker symbol: line-ns-dot
number: 242",
"marker symbol: line-ne-dot
number: 243",
- "marker symbol: line-nw-dot
number: 244"
+ "marker symbol: line-nw-dot
number: 244",
+ "marker symbol: arrow-up-dot
number: 245",
+ "marker symbol: arrow-down-dot
number: 246",
+ "marker symbol: arrow-left-dot
number: 247",
+ "marker symbol: arrow-right-dot
number: 248",
+ "marker symbol: arrow-bar-up-dot
number: 249",
+ "marker symbol: arrow-bar-down-dot
number: 250",
+ "marker symbol: arrow-bar-left-dot
number: 251",
+ "marker symbol: arrow-bar-right-dot
number: 252",
+ "marker symbol: arrow-dot
number: 253",
+ "marker symbol: arrow-wide-dot
number: 254"
],
"hoverinfo": "text"
},
{
"mode": "markers",
"x": [
- 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 19, 19, 19, 19, 19, 19, 19, 19, 19
+ 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 30, 30, 30, 30, 30, 30, 30, 30, 30,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 32.5, 32.5, 32.5, 32.5, 32.5, 32.5, 32.5, 32.5, 32.5,
+ 34
],
"y": [
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
0, 1, 2, 3, 4, 5, 6, 7, 8,
- 0, 1, 2, 3, 4, 5, 6, 7, 8
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
],
"marker": {
"symbol": [
@@ -422,7 +498,17 @@
"line-ew-open-dot",
"line-ns-open-dot",
"line-ne-open-dot",
- "line-nw-open-dot"
+ "line-nw-open-dot",
+ "arrow-up-open-dot",
+ "arrow-down-open-dot",
+ "arrow-left-open-dot",
+ "arrow-right-open-dot",
+ "arrow-bar-up-open-dot",
+ "arrow-bar-down-open-dot",
+ "arrow-bar-left-open-dot",
+ "arrow-bar-right-open-dot",
+ "arrow-open-dot",
+ "arrow-wide-open-dot"
],
"color": "blue",
"size": 20,
@@ -476,7 +562,18 @@
"marker symbol: line-ew-open-dot
number: 341",
"marker symbol: line-ns-open-dot
number: 342",
"marker symbol: line-ne-open-dot
number: 343",
- "marker symbol: line-nw-open-dot
number: 344"
+ "marker symbol: line-nw-open-dot
number: 344",
+ "marker symbol: line-nw-open-dot
number: 344",
+ "marker symbol: arrow-up-open-dot
number: 345",
+ "marker symbol: arrow-down-open-dot
number: 346",
+ "marker symbol: arrow-left-open-dot
number: 347",
+ "marker symbol: arrow-right-open-dot
number: 348",
+ "marker symbol: arrow-bar-up-open-dot
number: 349",
+ "marker symbol: arrow-bar-down-open-dot
number: 350",
+ "marker symbol: arrow-bar-left-open-dot
number: 351",
+ "marker symbol: arrow-bar-right-open-dot
number: 352",
+ "marker symbol: arrow-open-dot
number: 353",
+ "marker symbol: arrow-wide-open-dot
number: 354"
],
"hoverinfo": "text"
}
@@ -488,7 +585,7 @@
"b": 0,
"t": 0
},
- "width": 800,
+ "width": 1500,
"height": 500,
"xaxis": {
"showgrid": false,
diff --git a/test/image/mocks/polar_direction.json b/test/image/mocks/polar_direction.json
index bf044ab7011..6c017abba78 100644
--- a/test/image/mocks/polar_direction.json
+++ b/test/image/mocks/polar_direction.json
@@ -21,8 +21,9 @@
},
"marker": {
"color": "#8090c7",
- "symbol": "square",
- "size": 8
+ "symbol": "arrow",
+ "angleref": "previous",
+ "size": 12
},
"subplot": "polar",
"text": "sector: 0->360
rotation: -90
direction: clockwise"
@@ -48,8 +49,9 @@
},
"marker": {
"color": "#8090c7",
- "symbol": "square",
- "size": 8
+ "symbol": "arrow",
+ "angleref": "previous",
+ "size": 12
},
"subplot": "polar2",
"text": "sector: 0->360
rotation: 90
direction: clockwise"
@@ -75,8 +77,9 @@
},
"marker": {
"color": "#8090c7",
- "symbol": "square",
- "size": 8
+ "symbol": "arrow",
+ "angleref": "previous",
+ "size": 12
},
"subplot": "polar3",
"text": "sector: 45->135
rotation: 90
direction: clockwise"
@@ -102,8 +105,9 @@
},
"marker": {
"color": "#8090c7",
- "symbol": "square",
- "size": 8
+ "symbol": "arrow",
+ "angleref": "previous",
+ "size": 12
},
"subplot": "polar4",
"text": "sector: 135->225
rotation: 90
direction: clockwise"
@@ -129,8 +133,9 @@
},
"marker": {
"color": "#8090c7",
- "symbol": "square",
- "size": 8
+ "symbol": "arrow",
+ "angleref": "previous",
+ "size": 12
},
"subplot": "polar5",
"text": "sector: 135->225
rotation: 90
direction: counterclockwise"
@@ -156,8 +161,9 @@
},
"marker": {
"color": "#8090c7",
- "symbol": "square",
- "size": 8
+ "symbol": "arrow",
+ "angleref": "previous",
+ "size": 12
},
"subplot": "polar6",
"text": "sector: 45->135
rotation: 90
direction: counterclockwise"
@@ -183,8 +189,9 @@
},
"marker": {
"color": "#8090c7",
- "symbol": "square",
- "size": 8
+ "symbol": "arrow",
+ "angleref": "previous",
+ "size": 12
},
"subplot": "polar7",
"text": "sector: 0->360
rotation: 90
direction: counterclockwise"
@@ -210,8 +217,9 @@
},
"marker": {
"color": "#8090c7",
- "symbol": "square",
- "size": 8
+ "symbol": "arrow",
+ "angleref": "previous",
+ "size": 12
},
"subplot": "polar8",
"text": "sector: 0->360
rotation: 0
direction: clockwise"
@@ -237,8 +245,9 @@
},
"marker": {
"color": "#8090c7",
- "symbol": "square",
- "size": 8
+ "symbol": "arrow",
+ "angleref": "previous",
+ "size": 12
},
"subplot": "polar9",
"text": "sector: 0->360
rotation: 0
direction: counterclockwise"
@@ -271,12 +280,12 @@
},
"radialaxis": {
"tickfont": {
- "size": 8
+ "size": 12
}
},
"angularaxis": {
"tickfont": {
- "size": 8
+ "size": 12
},
"rotation": -90,
"direction": "clockwise"
@@ -299,12 +308,12 @@
},
"radialaxis": {
"tickfont": {
- "size": 8
+ "size": 12
}
},
"angularaxis": {
"tickfont": {
- "size": 8
+ "size": 12
},
"rotation": 90,
"direction": "clockwise"
@@ -327,12 +336,12 @@
},
"radialaxis": {
"tickfont": {
- "size": 8
+ "size": 12
}
},
"angularaxis": {
"tickfont": {
- "size": 8
+ "size": 12
},
"rotation": 90,
"direction": "clockwise"
@@ -355,12 +364,12 @@
},
"radialaxis": {
"tickfont": {
- "size": 8
+ "size": 12
}
},
"angularaxis": {
"tickfont": {
- "size": 8
+ "size": 12
},
"rotation": 90,
"direction": "clockwise"
@@ -383,12 +392,12 @@
},
"radialaxis": {
"tickfont": {
- "size": 8
+ "size": 12
}
},
"angularaxis": {
"tickfont": {
- "size": 8
+ "size": 12
},
"rotation": 90,
"direction": "counterclockwise"
@@ -411,12 +420,12 @@
},
"radialaxis": {
"tickfont": {
- "size": 8
+ "size": 12
}
},
"angularaxis": {
"tickfont": {
- "size": 8
+ "size": 12
},
"rotation": 90,
"direction": "counterclockwise"
@@ -439,12 +448,12 @@
},
"radialaxis": {
"tickfont": {
- "size": 8
+ "size": 12
}
},
"angularaxis": {
"tickfont": {
- "size": 8
+ "size": 12
},
"rotation": 90,
"direction": "counterclockwise"
@@ -467,12 +476,12 @@
},
"radialaxis": {
"tickfont": {
- "size": 8
+ "size": 12
}
},
"angularaxis": {
"tickfont": {
- "size": 8
+ "size": 12
},
"rotation": 0,
"direction": "clockwise"
@@ -495,12 +504,12 @@
},
"radialaxis": {
"tickfont": {
- "size": 8
+ "size": 12
}
},
"angularaxis": {
"tickfont": {
- "size": 8
+ "size": 12
},
"rotation": 0,
"direction": "counterclockwise"
diff --git a/test/image/mocks/scattercarpet-on-two-carpets.json b/test/image/mocks/scattercarpet-on-two-carpets.json
index dbac1ca27b8..2e52c1d5e90 100644
--- a/test/image/mocks/scattercarpet-on-two-carpets.json
+++ b/test/image/mocks/scattercarpet-on-two-carpets.json
@@ -47,7 +47,12 @@
"smoothing": 1,
"color": "blue"
},
- "mode": "lines",
+ "mode": "lines+markers",
+ "marker": {
+ "size": 15,
+ "symbol": "arrow",
+ "angleref": "previous"
+ },
"carpet": "c0"
},
{
@@ -59,7 +64,13 @@
"smoothing": 1,
"color": "red"
},
- "mode": "lines",
+ "mode": "lines+markers",
+ "marker": {
+ "size": 15,
+ "symbol": "arrow",
+ "angle": 90,
+ "angleref": "previous"
+ },
"carpet": "c1"
}
]
diff --git a/test/image/mocks/smith_gaps.json b/test/image/mocks/smith_gaps.json
index f1c64de8cd1..11b5136f919 100644
--- a/test/image/mocks/smith_gaps.json
+++ b/test/image/mocks/smith_gaps.json
@@ -10,6 +10,7 @@
0, 0.2, 0.4, null, 0.8, 1, null, 2, 3, null, 5
],
"mode": "markers+lines",
+ "marker": { "size": 10, "symbol": "arrow-wide", "angleref": "previous" },
"line": { "shape": "spline" }
},
{
@@ -23,6 +24,7 @@
0, 0.2, 0.4, null, 0.8, 1, null, 2, 3, null, 5
],
"mode": "markers+lines",
+ "marker": { "size": 20, "symbol": "arrow", "angleref": "previous", "angle": -90 },
"line": { "shape": "spline" },
"subplot": "smith2"
}
diff --git a/test/image/mocks/splom_log.json b/test/image/mocks/splom_log.json
index 8ec446f0c26..75618cd4fe2 100644
--- a/test/image/mocks/splom_log.json
+++ b/test/image/mocks/splom_log.json
@@ -9,6 +9,8 @@
"label": "B"
}],
"marker": {
+ "symbol": "arrow",
+ "angle": 180,
"size": 20,
"line": {"width": 2, "color": "#444"},
"color": [10, 40, 100],
diff --git a/test/image/mocks/ternary_markers.json b/test/image/mocks/ternary_markers.json
index 6283daa5d29..c7cd6f851a9 100644
--- a/test/image/mocks/ternary_markers.json
+++ b/test/image/mocks/ternary_markers.json
@@ -72,9 +72,10 @@
"color": "#DB7365"
},
"marker": {
- "symbol": 100,
+ "symbol": "arrow",
+ "angleref": "previous",
"color": "#DB7365",
- "size": 14,
+ "size": 10,
"line": {
"width": 2
}
diff --git a/test/image/mocks/violin_ridgeplot.json b/test/image/mocks/violin_ridgeplot.json
index 1cccf678e1b..988fe62eb70 100644
--- a/test/image/mocks/violin_ridgeplot.json
+++ b/test/image/mocks/violin_ridgeplot.json
@@ -11,7 +11,7 @@
"hovertemplate": "day=%{y}
total_bill=%{x}",
"legendgroup": "day=Fri",
"marker": {
- "color": "#636efa"
+ "color": "#636efa", "symbol": "arrow", "angle": 180, "size": 20
},
"name": "day=Fri",
"offsetgroup": "day=Fri",
@@ -80,7 +80,7 @@
"hovertemplate": "day=%{y}
total_bill=%{x}",
"legendgroup": "day=Sat",
"marker": {
- "color": "#EF553B"
+ "color": "#EF553B", "symbol": "arrow", "angle": 45, "size": 20
},
"name": "day=Sat",
"offsetgroup": "day=Sat",
@@ -285,7 +285,7 @@
"hovertemplate": "day=%{y}
total_bill=%{x}",
"legendgroup": "day=Sun",
"marker": {
- "color": "#00cc96"
+ "color": "#00cc96", "symbol": "arrow", "angle": 0, "size": 20
},
"name": "day=Sun",
"offsetgroup": "day=Sun",
@@ -468,7 +468,7 @@
"hovertemplate": "day=%{y}
total_bill=%{x}",
"legendgroup": "day=Thur",
"marker": {
- "color": "#ab63fa"
+ "color": "#ab63fa", "symbol": "arrow", "angle": -45, "size": 20
},
"name": "day=Thur",
"offsetgroup": "day=Thur",
diff --git a/test/image/mocks/z-gl2d_marker_symbols-angle.json b/test/image/mocks/z-gl2d_marker_symbols-angle.json
new file mode 100644
index 00000000000..2b24b4d1eb7
--- /dev/null
+++ b/test/image/mocks/z-gl2d_marker_symbols-angle.json
@@ -0,0 +1,607 @@
+{
+ "data": [
+ {
+ "type": "scattergl",
+ "mode": "markers",
+ "x": [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5,
+ 7
+ ],
+ "y": [
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
+ ],
+ "marker": { "angle": 15,
+ "symbol": [
+ "circle",
+ "square",
+ "diamond",
+ "cross",
+ "x",
+ "triangle-up",
+ "triangle-down",
+ "triangle-left",
+ "triangle-right",
+ "triangle-ne",
+ "triangle-se",
+ "triangle-sw",
+ "triangle-nw",
+ "pentagon",
+ "hexagon",
+ "hexagon2",
+ "octagon",
+ "star",
+ "hexagram",
+ "star-triangle-up",
+ "star-triangle-down",
+ "star-square",
+ "star-diamond",
+ "diamond-tall",
+ "diamond-wide",
+ "hourglass",
+ "bowtie",
+ "circle-cross",
+ "circle-x",
+ "square-cross",
+ "square-x",
+ "diamond-cross",
+ "diamond-x",
+ "cross-thin",
+ "x-thin",
+ "asterisk",
+ "hash",
+ "y-up",
+ "y-down",
+ "y-left",
+ "y-right",
+ "line-ew",
+ "line-ns",
+ "line-ne",
+ "line-nw",
+ "arrow-up",
+ "arrow-down",
+ "arrow-left",
+ "arrow-right",
+ "arrow-bar-up",
+ "arrow-bar-down",
+ "arrow-bar-left",
+ "arrow-bar-right",
+ "arrow",
+ "arrow-wide"
+ ],
+ "color": "blue",
+ "size": 20,
+ "line": {
+ "color": "orange",
+ "width": 1.5
+ }
+ },
+ "text": [
+ "marker symbol: circle
number: 0",
+ "marker symbol: square
number: 1",
+ "marker symbol: diamond
number: 2",
+ "marker symbol: cross
number: 3",
+ "marker symbol: x
number: 4",
+ "marker symbol: triangle-up
number: 5",
+ "marker symbol: triangle-down
number: 6",
+ "marker symbol: triangle-left
number: 7",
+ "marker symbol: triangle-right
number: 8",
+ "marker symbol: triangle-ne
number: 9",
+ "marker symbol: triangle-se
number: 10",
+ "marker symbol: triangle-sw
number: 11",
+ "marker symbol: triangle-nw
number: 12",
+ "marker symbol: pentagon
number: 13",
+ "marker symbol: hexagon
number: 14",
+ "marker symbol: hexagon2
number: 15",
+ "marker symbol: octagon
number: 16",
+ "marker symbol: star
number: 17",
+ "marker symbol: hexagram
number: 18",
+ "marker symbol: star-triangle-up
number: 19",
+ "marker symbol: star-triangle-down
number: 20",
+ "marker symbol: star-square
number: 21",
+ "marker symbol: star-diamond
number: 22",
+ "marker symbol: diamond-tall
number: 23",
+ "marker symbol: diamond-wide
number: 24",
+ "marker symbol: hourglass
number: 25",
+ "marker symbol: bowtie
number: 26",
+ "marker symbol: circle-cross
number: 27",
+ "marker symbol: circle-x
number: 28",
+ "marker symbol: square-cross
number: 29",
+ "marker symbol: square-x
number: 30",
+ "marker symbol: diamond-cross
number: 31",
+ "marker symbol: diamond-x
number: 32",
+ "marker symbol: cross-thin
number: 33",
+ "marker symbol: x-thin
number: 34",
+ "marker symbol: asterisk
number: 35",
+ "marker symbol: hash
number: 36",
+ "marker symbol: y-up
number: 37",
+ "marker symbol: y-down
number: 38",
+ "marker symbol: y-left
number: 39",
+ "marker symbol: y-right
number: 40",
+ "marker symbol: line-ew
number: 41",
+ "marker symbol: line-ns
number: 42",
+ "marker symbol: line-ne
number: 43",
+ "marker symbol: line-nw
number: 44",
+ "marker symbol: arrow-up
number: 45",
+ "marker symbol: arrow-down
number: 46",
+ "marker symbol: arrow-left
number: 47",
+ "marker symbol: arrow-right
number: 48",
+ "marker symbol: arrow-bar-up
number: 49",
+ "marker symbol: arrow-bar-down
number: 50",
+ "marker symbol: arrow-bar-left
number: 51",
+ "marker symbol: arrow-bar-right
number: 52",
+ "marker symbol: arrow
number: 53",
+ "marker symbol: arrow-wide
number: 54"
+ ],
+ "hoverinfo": "text"
+ },
+ {
+ "type": "scattergl",
+ "mode": "markers",
+ "x": [
+ 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 14.5, 14.5, 14.5, 14.5, 14.5, 14.5, 14.5, 14.5, 14.5,
+ 16
+ ],
+ "y": [
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
+ ],
+ "marker": { "angle": 15,
+ "symbol": [
+ "circle-open",
+ "square-open",
+ "diamond-open",
+ "cross-open",
+ "x-open",
+ "triangle-up-open",
+ "triangle-down-open",
+ "triangle-left-open",
+ "triangle-right-open",
+ "triangle-ne-open",
+ "triangle-se-open",
+ "triangle-sw-open",
+ "triangle-nw-open",
+ "pentagon-open",
+ "hexagon-open",
+ "hexagon2-open",
+ "octagon-open",
+ "star-open",
+ "hexagram-open",
+ "star-triangle-up-open",
+ "star-triangle-down-open",
+ "star-square-open",
+ "star-diamond-open",
+ "diamond-tall-open",
+ "diamond-wide-open",
+ "hourglass-open",
+ "bowtie-open",
+ "circle-cross-open",
+ "circle-x-open",
+ "square-cross-open",
+ "square-x-open",
+ "diamond-cross-open",
+ "diamond-x-open",
+ "cross-thin-open",
+ "x-thin-open",
+ "asterisk-open",
+ "hash-open",
+ "y-up-open",
+ "y-down-open",
+ "y-left-open",
+ "y-right-open",
+ "line-ew-open",
+ "line-ns-open",
+ "line-ne-open",
+ "line-nw-open",
+ "arrow-up-open",
+ "arrow-down-open",
+ "arrow-left-open",
+ "arrow-right-open",
+ "arrow-bar-up-open",
+ "arrow-bar-down-open",
+ "arrow-bar-left-open",
+ "arrow-bar-right-open",
+ "arrow-open",
+ "arrow-wide-open"
+ ],
+ "color": "blue",
+ "size": 20,
+ "line": {
+ "color": "orange",
+ "width": 1.5
+ }
+ },
+ "text": [
+ "marker symbol: circle-open
number: 100",
+ "marker symbol: square-open
number: 101",
+ "marker symbol: diamond-open
number: 102",
+ "marker symbol: cross-open
number: 103",
+ "marker symbol: x-open
number: 104",
+ "marker symbol: triangle-up-open
number: 105",
+ "marker symbol: triangle-down-open
number: 106",
+ "marker symbol: triangle-left-open
number: 107",
+ "marker symbol: triangle-right-open
number: 108",
+ "marker symbol: triangle-ne-open
number: 109",
+ "marker symbol: triangle-se-open
number: 110",
+ "marker symbol: triangle-sw-open
number: 111",
+ "marker symbol: triangle-nw-open
number: 112",
+ "marker symbol: pentagon-open
number: 113",
+ "marker symbol: hexagon-open
number: 114",
+ "marker symbol: hexagon2-open
number: 115",
+ "marker symbol: octagon-open
number: 116",
+ "marker symbol: star-open
number: 117",
+ "marker symbol: hexagram-open
number: 118",
+ "marker symbol: star-triangle-up-open
number: 119",
+ "marker symbol: star-triangle-down-open
number: 120",
+ "marker symbol: star-square-open
number: 121",
+ "marker symbol: star-diamond-open
number: 122",
+ "marker symbol: diamond-tall-open
number: 123",
+ "marker symbol: diamond-wide-open
number: 124",
+ "marker symbol: hourglass-open
number: 125",
+ "marker symbol: bowtie-open
number: 126",
+ "marker symbol: circle-cross-open
number: 127",
+ "marker symbol: circle-x-open
number: 128",
+ "marker symbol: square-cross-open
number: 129",
+ "marker symbol: square-x-open
number: 130",
+ "marker symbol: diamond-cross-open
number: 131",
+ "marker symbol: diamond-x-open
number: 132",
+ "marker symbol: cross-thin-open
number: 133",
+ "marker symbol: x-thin-open
number: 134",
+ "marker symbol: asterisk-open
number: 135",
+ "marker symbol: hash-open
number: 136",
+ "marker symbol: y-up-open
number: 137",
+ "marker symbol: y-down-open
number: 138",
+ "marker symbol: y-left-open
number: 139",
+ "marker symbol: y-right-open
number: 140",
+ "marker symbol: line-ew-open
number: 141",
+ "marker symbol: line-ns-open
number: 142",
+ "marker symbol: line-ne-open
number: 143",
+ "marker symbol: line-nw-open
number: 144",
+ "marker symbol: arrow-up-open
number: 145",
+ "marker symbol: arrow-down-open
number: 146",
+ "marker symbol: arrow-left-open
number: 147",
+ "marker symbol: arrow-right-open
number: 148",
+ "marker symbol: arrow-bar-up-open
number: 149",
+ "marker symbol: arrow-bar-down-open
number: 150",
+ "marker symbol: arrow-bar-left-open
number: 151",
+ "marker symbol: arrow-bar-right-open
number: 152",
+ "marker symbol: arrow-open
number: 153",
+ "marker symbol: arrow-wide-open
number: 154"
+ ],
+ "hoverinfo": "text"
+ },
+ {
+ "type": "scattergl",
+ "mode": "markers",
+ "x": [
+ 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23.5, 23.5, 23.5, 23.5, 23.5, 23.5, 23.5, 23.5, 23.5,
+ 25
+ ],
+ "y": [
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
+ ],
+ "marker": { "angle": 15,
+ "symbol": [
+ "circle-dot",
+ "square-dot",
+ "diamond-dot",
+ "cross-dot",
+ "x-dot",
+ "triangle-up-dot",
+ "triangle-down-dot",
+ "triangle-left-dot",
+ "triangle-right-dot",
+ "triangle-ne-dot",
+ "triangle-se-dot",
+ "triangle-sw-dot",
+ "triangle-nw-dot",
+ "pentagon-dot",
+ "hexagon-dot",
+ "hexagon2-dot",
+ "octagon-dot",
+ "star-dot",
+ "hexagram-dot",
+ "star-triangle-up-dot",
+ "star-triangle-down-dot",
+ "star-square-dot",
+ "star-diamond-dot",
+ "diamond-tall-dot",
+ "diamond-wide-dot",
+ "hourglass-dot",
+ "bowtie-dot",
+ "circle-cross-dot",
+ "circle-x-dot",
+ "square-cross-dot",
+ "square-x-dot",
+ "diamond-cross-dot",
+ "diamond-x-dot",
+ "cross-thin-dot",
+ "x-thin-dot",
+ "asterisk-dot",
+ "hash-dot",
+ "y-up-dot",
+ "y-down-dot",
+ "y-left-dot",
+ "y-right-dot",
+ "line-ew-dot",
+ "line-ns-dot",
+ "line-ne-dot",
+ "line-nw-dot",
+ "arrow-up-dot",
+ "arrow-down-dot",
+ "arrow-left-dot",
+ "arrow-right-dot",
+ "arrow-bar-up-dot",
+ "arrow-bar-down-dot",
+ "arrow-bar-left-dot",
+ "arrow-bar-right-dot",
+ "arrow-dot",
+ "arrow-wide-dot"
+ ],
+ "color": "blue",
+ "size": 20,
+ "line": {
+ "color": "orange",
+ "width": 1.5
+ }
+ },
+ "text": [
+ "marker symbol: circle-dot
number: 200",
+ "marker symbol: square-dot
number: 201",
+ "marker symbol: diamond-dot
number: 202",
+ "marker symbol: cross-dot
number: 203",
+ "marker symbol: x-dot
number: 204",
+ "marker symbol: triangle-up-dot
number: 205",
+ "marker symbol: triangle-down-dot
number: 206",
+ "marker symbol: triangle-left-dot
number: 207",
+ "marker symbol: triangle-right-dot
number: 208",
+ "marker symbol: triangle-ne-dot
number: 209",
+ "marker symbol: triangle-se-dot
number: 210",
+ "marker symbol: triangle-sw-dot
number: 211",
+ "marker symbol: triangle-nw-dot
number: 212",
+ "marker symbol: pentagon-dot
number: 213",
+ "marker symbol: hexagon-dot
number: 214",
+ "marker symbol: hexagon2-dot
number: 215",
+ "marker symbol: octagon-dot
number: 216",
+ "marker symbol: star-dot
number: 217",
+ "marker symbol: hexagram-dot
number: 218",
+ "marker symbol: star-triangle-up-dot
number: 219",
+ "marker symbol: star-triangle-down-dot
number: 220",
+ "marker symbol: star-square-dot
number: 221",
+ "marker symbol: star-diamond-dot
number: 222",
+ "marker symbol: diamond-tall-dot
number: 223",
+ "marker symbol: diamond-wide-dot
number: 224",
+ "marker symbol: hourglass-dot
number: 225",
+ "marker symbol: bowtie-dot
number: 226",
+ "marker symbol: circle-cross-dot
number: 227",
+ "marker symbol: circle-x-dot
number: 228",
+ "marker symbol: square-cross-dot
number: 229",
+ "marker symbol: square-x-dot
number: 230",
+ "marker symbol: diamond-cross-dot
number: 231",
+ "marker symbol: diamond-x-dot
number: 232",
+ "marker symbol: cross-thin-dot
number: 233",
+ "marker symbol: x-thin-dot
number: 234",
+ "marker symbol: asterisk-dot
number: 235",
+ "marker symbol: hash-dot
number: 236",
+ "marker symbol: y-up-dot
number: 237",
+ "marker symbol: y-down-dot
number: 238",
+ "marker symbol: y-left-dot
number: 239",
+ "marker symbol: y-right-dot
number: 240",
+ "marker symbol: line-ew-dot
number: 241",
+ "marker symbol: line-ns-dot
number: 242",
+ "marker symbol: line-ne-dot
number: 243",
+ "marker symbol: line-nw-dot
number: 244",
+ "marker symbol: arrow-up-dot
number: 245",
+ "marker symbol: arrow-down-dot
number: 246",
+ "marker symbol: arrow-left-dot
number: 247",
+ "marker symbol: arrow-right-dot
number: 248",
+ "marker symbol: arrow-bar-up-dot
number: 249",
+ "marker symbol: arrow-bar-down-dot
number: 250",
+ "marker symbol: arrow-bar-left-dot
number: 251",
+ "marker symbol: arrow-bar-right-dot
number: 252",
+ "marker symbol: arrow-dot
number: 253",
+ "marker symbol: arrow-wide-dot
number: 254"
+ ],
+ "hoverinfo": "text"
+ },
+ {
+ "type": "scattergl",
+ "mode": "markers",
+ "x": [
+ 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 30, 30, 30, 30, 30, 30, 30, 30, 30,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 32.5, 32.5, 32.5, 32.5, 32.5, 32.5, 32.5, 32.5, 32.5,
+ 34
+ ],
+ "y": [
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
+ ],
+ "marker": { "angle": 15,
+ "symbol": [
+ "circle-open-dot",
+ "square-open-dot",
+ "diamond-open-dot",
+ "cross-open-dot",
+ "x-open-dot",
+ "triangle-up-open-dot",
+ "triangle-down-open-dot",
+ "triangle-left-open-dot",
+ "triangle-right-open-dot",
+ "triangle-ne-open-dot",
+ "triangle-se-open-dot",
+ "triangle-sw-open-dot",
+ "triangle-nw-open-dot",
+ "pentagon-open-dot",
+ "hexagon-open-dot",
+ "hexagon2-open-dot",
+ "octagon-open-dot",
+ "star-open-dot",
+ "hexagram-open-dot",
+ "star-triangle-up-open-dot",
+ "star-triangle-down-open-dot",
+ "star-square-open-dot",
+ "star-diamond-open-dot",
+ "diamond-tall-open-dot",
+ "diamond-wide-open-dot",
+ "hourglass-open-dot",
+ "bowtie-open-dot",
+ "circle-cross-open-dot",
+ "circle-x-open-dot",
+ "square-cross-open-dot",
+ "square-x-open-dot",
+ "diamond-cross-open-dot",
+ "diamond-x-open-dot",
+ "cross-thin-open-dot",
+ "x-thin-open-dot",
+ "asterisk-open-dot",
+ "hash-open-dot",
+ "y-up-open-dot",
+ "y-down-open-dot",
+ "y-left-open-dot",
+ "y-right-open-dot",
+ "line-ew-open-dot",
+ "line-ns-open-dot",
+ "line-ne-open-dot",
+ "line-nw-open-dot",
+ "arrow-up-open-dot",
+ "arrow-down-open-dot",
+ "arrow-left-open-dot",
+ "arrow-right-open-dot",
+ "arrow-bar-up-open-dot",
+ "arrow-bar-down-open-dot",
+ "arrow-bar-left-open-dot",
+ "arrow-bar-right-open-dot",
+ "arrow-open-dot",
+ "arrow-wide-open-dot"
+ ],
+ "color": "blue",
+ "size": 20,
+ "line": {
+ "color": "orange",
+ "width": 1.5
+ }
+ },
+ "text": [
+ "marker symbol: circle-open-dot
number: 300",
+ "marker symbol: square-open-dot
number: 301",
+ "marker symbol: diamond-open-dot
number: 302",
+ "marker symbol: cross-open-dot
number: 303",
+ "marker symbol: x-open-dot
number: 304",
+ "marker symbol: triangle-up-open-dot
number: 305",
+ "marker symbol: triangle-down-open-dot
number: 306",
+ "marker symbol: triangle-left-open-dot
number: 307",
+ "marker symbol: triangle-right-open-dot
number: 308",
+ "marker symbol: triangle-ne-open-dot
number: 309",
+ "marker symbol: triangle-se-open-dot
number: 310",
+ "marker symbol: triangle-sw-open-dot
number: 311",
+ "marker symbol: triangle-nw-open-dot
number: 312",
+ "marker symbol: pentagon-open-dot
number: 313",
+ "marker symbol: hexagon-open-dot
number: 314",
+ "marker symbol: hexagon2-open-dot
number: 315",
+ "marker symbol: octagon-open-dot
number: 316",
+ "marker symbol: star-open-dot
number: 317",
+ "marker symbol: hexagram-open-dot
number: 318",
+ "marker symbol: star-triangle-up-open-dot
number: 319",
+ "marker symbol: star-triangle-down-open-dot
number: 320",
+ "marker symbol: star-square-open-dot
number: 321",
+ "marker symbol: star-diamond-open-dot
number: 322",
+ "marker symbol: diamond-tall-open-dot
number: 323",
+ "marker symbol: diamond-wide-open-dot
number: 324",
+ "marker symbol: hourglass-open-dot
number: 325",
+ "marker symbol: bowtie-open-dot
number: 326",
+ "marker symbol: circle-cross-open-dot
number: 327",
+ "marker symbol: circle-x-open-dot
number: 328",
+ "marker symbol: square-cross-open-dot
number: 329",
+ "marker symbol: square-x-open-dot
number: 330",
+ "marker symbol: diamond-cross-open-dot
number: 331",
+ "marker symbol: diamond-x-open-dot
number: 332",
+ "marker symbol: cross-thin-open-dot
number: 333",
+ "marker symbol: x-thin-open-dot
number: 334",
+ "marker symbol: asterisk-open-dot
number: 335",
+ "marker symbol: hash-open-dot
number: 336",
+ "marker symbol: y-up-open-dot
number: 337",
+ "marker symbol: y-down-open-dot
number: 338",
+ "marker symbol: y-left-open-dot
number: 339",
+ "marker symbol: y-right-open-dot
number: 340",
+ "marker symbol: line-ew-open-dot
number: 341",
+ "marker symbol: line-ns-open-dot
number: 342",
+ "marker symbol: line-ne-open-dot
number: 343",
+ "marker symbol: line-nw-open-dot
number: 344",
+ "marker symbol: line-nw-open-dot
number: 344",
+ "marker symbol: arrow-up-open-dot
number: 345",
+ "marker symbol: arrow-down-open-dot
number: 346",
+ "marker symbol: arrow-left-open-dot
number: 347",
+ "marker symbol: arrow-right-open-dot
number: 348",
+ "marker symbol: arrow-bar-up-open-dot
number: 349",
+ "marker symbol: arrow-bar-down-open-dot
number: 350",
+ "marker symbol: arrow-bar-left-open-dot
number: 351",
+ "marker symbol: arrow-bar-right-open-dot
number: 352",
+ "marker symbol: arrow-open-dot
number: 353",
+ "marker symbol: arrow-wide-open-dot
number: 354"
+ ],
+ "hoverinfo": "text"
+ }
+ ],
+ "layout": {
+ "margin": {
+ "l": 0,
+ "r": 0,
+ "b": 0,
+ "t": 0
+ },
+ "width": 1500,
+ "height": 500,
+ "xaxis": {
+ "showgrid": false,
+ "zeroline": false
+ },
+ "yaxis": {
+ "showgrid": false,
+ "zeroline": false,
+ "autorange": "reversed"
+ },
+ "showlegend": false,
+ "plot_bgcolor": "#d3d3d3",
+ "hovermode": "closest"
+ }
+}
diff --git a/test/image/mocks/z-line-shape-arrow.json b/test/image/mocks/z-line-shape-arrow.json
new file mode 100644
index 00000000000..d4951d6b0f8
--- /dev/null
+++ b/test/image/mocks/z-line-shape-arrow.json
@@ -0,0 +1,176 @@
+{
+ "data": [
+ {
+ "line": {
+ "shape": "linear"
+ },
+ "mode": "lines+markers",
+ "name": "'linear'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 10
+ },
+ "x": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "y": [
+ 1,
+ 3,
+ 2,
+ 3,
+ 1
+ ]
+ },
+ {
+ "line": {
+ "shape": "spline"
+ },
+ "mode": "lines+markers",
+ "name": "'spline'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 10
+ },
+ "x": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "y": [
+ 6,
+ 8,
+ 7,
+ 8,
+ 6
+ ]
+ },
+ {
+ "line": {
+ "shape": "vhv"
+ },
+ "mode": "lines+markers",
+ "name": "'vhv'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 10
+ },
+ "x": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "y": [
+ 11,
+ 13,
+ 12,
+ 13,
+ 11
+ ]
+ },
+ {
+ "line": {
+ "shape": "hvh"
+ },
+ "mode": "lines+markers",
+ "name": "'hvh'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 10
+ },
+ "x": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "y": [
+ 16,
+ 18,
+ 17,
+ 18,
+ 16
+ ]
+ },
+ {
+ "line": {
+ "shape": "vh"
+ },
+ "mode": "lines+markers",
+ "name": "'vh'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 10
+ },
+ "x": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "y": [
+ 21,
+ 23,
+ 22,
+ 23,
+ 21
+ ]
+ },
+ {
+ "line": {
+ "shape": "hv"
+ },
+ "mode": "lines+markers",
+ "name": "'hv'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 10
+ },
+ "x": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "y": [
+ 26,
+ 28,
+ 27,
+ 28,
+ 26
+ ]
+ }
+ ],
+ "layout": {
+ "title": {
+ "text" : "line shape and arrows"
+ },
+ "legend": {
+ "orientation": "h"
+ },
+ "height": 700,
+ "width": 700
+ }
+}
diff --git a/test/image/mocks/z-line-shape-arrow_backoff-auto.json b/test/image/mocks/z-line-shape-arrow_backoff-auto.json
new file mode 100644
index 00000000000..977cd481758
--- /dev/null
+++ b/test/image/mocks/z-line-shape-arrow_backoff-auto.json
@@ -0,0 +1,242 @@
+{
+ "data": [
+ {
+ "line": {
+ "width": 5,
+ "shape": "linear"
+ },
+ "mode": "lines+markers",
+ "name": "'linear'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "x": [
+ 1,
+ 2,
+ null,
+ 2,
+ 3,
+ null,
+ 3,
+ 4,
+ null,
+ 4,
+ 5
+ ],
+ "y": [
+ 1,
+ 3,
+ null,
+ 3,
+ 2,
+ null,
+ 2,
+ 3,
+ null,
+ 3,
+ 1
+ ]
+ },
+ {
+ "line": {
+ "width": 5,
+ "shape": "spline"
+ },
+ "mode": "lines+markers",
+ "name": "'spline'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "x": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "y": [
+ 6,
+ 8,
+ 7,
+ 8,
+ 6
+ ]
+ },
+ {
+ "line": {
+ "width": 5,
+ "shape": "vhv"
+ },
+ "mode": "lines+markers",
+ "name": "'vhv'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "x": [
+ 1,
+ 2,
+ null,
+ 2,
+ 3,
+ null,
+ 3,
+ 4,
+ null,
+ 4,
+ 5
+ ],
+ "y": [
+ 11,
+ 13,
+ null,
+ 13,
+ 12,
+ null,
+ 12,
+ 13,
+ null,
+ 13,
+ 11
+ ]
+ },
+ {
+ "line": {
+ "width": 5,
+ "shape": "hvh"
+ },
+ "mode": "lines+markers",
+ "name": "'hvh'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "x": [
+ 1,
+ 2,
+ null,
+ 2,
+ 3,
+ null,
+ 3,
+ 4,
+ null,
+ 4,
+ 5
+ ],
+ "y": [
+ 16,
+ 18,
+ null,
+ 18,
+ 17,
+ null,
+ 17,
+ 18,
+ null,
+ 18,
+ 16
+ ]
+ },
+ {
+ "line": {
+ "width": 5,
+ "shape": "vh"
+ },
+ "mode": "lines+markers",
+ "name": "'vh'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "x": [
+ 1,
+ 2,
+ null,
+ 2,
+ 3,
+ null,
+ 3,
+ 4,
+ null,
+ 4,
+ 5
+ ],
+ "y": [
+ 21,
+ 23,
+ null,
+ 23,
+ 22,
+ null,
+ 22,
+ 23,
+ null,
+ 23,
+ 21
+ ]
+ },
+ {
+ "line": {
+ "width": 5,
+ "shape": "hv"
+ },
+ "mode": "lines+markers",
+ "name": "'hv'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "x": [
+ 1,
+ 2,
+ null,
+ 2,
+ 3,
+ null,
+ 3,
+ 4,
+ null,
+ 4,
+ 5
+ ],
+ "y": [
+ 26,
+ 28,
+ null,
+ 28,
+ 27,
+ null,
+ 27,
+ 28,
+ null,
+ 28,
+ 26
+ ]
+ }
+ ],
+ "layout": {
+ "title": {
+ "text" : "line shape and arrows with auto backoff"
+ },
+ "legend": {
+ "orientation": "h"
+ },
+ "height": 700,
+ "width": 700
+ }
+}
diff --git a/test/image/mocks/z-line-shape-arrow_backoff.json b/test/image/mocks/z-line-shape-arrow_backoff.json
new file mode 100644
index 00000000000..b10bd07187a
--- /dev/null
+++ b/test/image/mocks/z-line-shape-arrow_backoff.json
@@ -0,0 +1,188 @@
+{
+ "data": [
+ {
+ "line": {
+ "backoff": 10,
+ "width": 5,
+ "shape": "linear"
+ },
+ "mode": "lines+markers",
+ "name": "'linear'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "x": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "y": [
+ 1,
+ 3,
+ 2,
+ 3,
+ 1
+ ]
+ },
+ {
+ "line": {
+ "backoff": 10,
+ "width": 5,
+ "shape": "spline"
+ },
+ "mode": "lines+markers",
+ "name": "'spline'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "x": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "y": [
+ 6,
+ 8,
+ 7,
+ 8,
+ 6
+ ]
+ },
+ {
+ "line": {
+ "backoff": 10,
+ "width": 5,
+ "shape": "vhv"
+ },
+ "mode": "lines+markers",
+ "name": "'vhv'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "x": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "y": [
+ 11,
+ 13,
+ 12,
+ 13,
+ 11
+ ]
+ },
+ {
+ "line": {
+ "backoff": 10,
+ "width": 5,
+ "shape": "hvh"
+ },
+ "mode": "lines+markers",
+ "name": "'hvh'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "x": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "y": [
+ 16,
+ 18,
+ 17,
+ 18,
+ 16
+ ]
+ },
+ {
+ "line": {
+ "backoff": 10,
+ "width": 5,
+ "shape": "vh"
+ },
+ "mode": "lines+markers",
+ "name": "'vh'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "x": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "y": [
+ 21,
+ 23,
+ 22,
+ 23,
+ 21
+ ]
+ },
+ {
+ "line": {
+ "backoff": 10,
+ "width": 5,
+ "shape": "hv"
+ },
+ "mode": "lines+markers",
+ "name": "'hv'",
+ "type": "scatter",
+ "marker": {
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "x": [
+ 1,
+ 2,
+ 3,
+ 4,
+ 5
+ ],
+ "y": [
+ 26,
+ 28,
+ 27,
+ 28,
+ 26
+ ]
+ }
+ ],
+ "layout": {
+ "title": {
+ "text" : "line shape and arrows with backoff"
+ },
+ "legend": {
+ "orientation": "h"
+ },
+ "height": 700,
+ "width": 700
+ }
+}
diff --git a/test/image/mocks/z-marker-standoff.json b/test/image/mocks/z-marker-standoff.json
new file mode 100644
index 00000000000..cd4925f7c9e
--- /dev/null
+++ b/test/image/mocks/z-marker-standoff.json
@@ -0,0 +1,403 @@
+{
+ "data": [
+ {
+ "mode": "markers+lines",
+ "line": {
+ "width": 5,
+ "backoff": [30, 20]
+ },
+ "marker": {
+ "standoff": [5, 20, null, 20, 10],
+ "angleref": "previous",
+ "symbol": "arrow",
+ "size": 20
+ },
+ "x": [
+ 1,
+ 2,
+ null,
+ 2,
+ 3
+ ],
+ "y": [
+ 3,
+ 1,
+ null,
+ 1,
+ 2
+ ]
+ },
+ {
+ "mode": "markers+text",
+ "marker": {
+ "opacity": 1,
+ "size": [10, 40, 20]
+ },
+ "text": [10, 40, 20],
+ "textposition": ["right", "center", "top"],
+ "x": [
+ 1,
+ 2,
+ 3
+ ],
+ "y": [
+ 3,
+ 1,
+ 2
+ ]
+ },
+ {
+ "type": "scattergeo",
+ "mode": "markers+lines",
+ "line": { "width": 5 },
+ "marker": {
+ "standoff": [5, 20, 10, 2.5],
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "lon": [
+ -30,
+ 0,
+ 30,
+ 15
+ ],
+ "lat": [
+ 20,
+ -5,
+ 10,
+ -20
+ ]
+ },
+ {
+ "type": "scattergeo",
+ "mode": "markers+text",
+ "marker": {
+ "opacity": 1,
+ "size": [10, 40, 20, 5]
+ },
+ "text": [10, 40, 20, 5],
+ "textposition": ["right", "center", "top", "bottom"],
+ "lon": [
+ -30,
+ 0,
+ 30,
+ 15
+ ],
+ "lat": [
+ 20,
+ -5,
+ 10,
+ -20
+ ]
+ },
+ {
+ "type": "scatterternary",
+ "mode": "markers+lines",
+ "line": {
+ "width": 5,
+ "backoff": [30, 20]
+ },
+ "marker": {
+ "standoff": [5, 20, null, 20, 10],
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "a": [
+ 2,
+ 1,
+ null,
+ 1,
+ 1
+ ],
+ "b": [
+ 1,
+ 2,
+ null,
+ 2,
+ 1
+ ],
+ "c": [
+ 1,
+ 1,
+ null,
+ 1,
+ 2
+ ]
+ },
+ {
+ "type": "scatterternary",
+ "mode": "markers+text",
+ "marker": {
+ "opacity": 1,
+ "size": [10, 40, 20]
+ },
+ "text": [10, 40, 20],
+ "textposition": ["right", "center", "top"],
+ "a": [
+ 2,
+ 1,
+ 1
+ ],
+ "b": [
+ 1,
+ 2,
+ 1
+ ],
+ "c": [
+ 1,
+ 1,
+ 2
+ ]
+ },
+ {
+ "xaxis": "x2",
+ "yaxis": "y2",
+ "type": "carpet",
+ "a": [ 4, 4, 4, 4.5, 4.5, 4.5, 5, 5, 5, 6, 6, 6 ],
+ "b": [ 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3 ],
+ "y": [ 2, 3.5, 4, 3, 4.5, 5, 5.5, 6.5, 7.5, 8, 8.5, 10 ],
+ "aaxis": {
+ "tickprefix": "a = ",
+ "ticksuffix": "m",
+ "smoothing": 1,
+ "minorgridcount": 9
+ },
+ "baxis": {
+ "tickprefix": "b = ",
+ "ticksuffix": "Pa",
+ "smoothing": 1,
+ "minorgridcount": 9
+ },
+ "carpet": "c0"
+ },
+ {
+ "xaxis": "x2",
+ "yaxis": "y2",
+ "type": "scattercarpet",
+ "mode": "markers+lines",
+ "line": {
+ "width": 5,
+ "backoff": [30, 20]
+ },
+ "marker": {
+ "standoff": [5, 20, null, 20, 10],
+ "angleref": "previous",
+ "symbol": "arrow",
+ "size": 20
+ },
+ "a": [ 4, 5, null, 5, 6 ],
+ "b": [ 2.5, 2.5, null, 2.5, 2.5 ],
+ "carpet": "c0"
+ },
+ {
+ "xaxis": "x2",
+ "yaxis": "y2",
+ "type": "scattercarpet",
+ "mode": "markers+text",
+ "marker": {
+ "opacity": 1,
+ "size": [10, 40, 20]
+ },
+ "text": [10, 40, 20],
+ "textposition": ["right", "center", "top"],
+ "a": [ 4, 5, 6 ],
+ "b": [ 2.5, 2.5, 2.5 ],
+ "carpet": "c0"
+ },
+ {
+ "subplot": "polar",
+ "type": "scatterpolar",
+ "mode": "markers+lines",
+ "line": {
+ "width": 5,
+ "backoff": [30, 20]
+ },
+ "marker": {
+ "standoff": [5, 20, null, 20, 10],
+ "angleref": "previous",
+ "symbol": "arrow",
+ "size": 20
+ },
+ "r": [
+ 1,
+ 2,
+ null,
+ 2,
+ 3
+ ],
+ "theta": [
+ 270,
+ 90,
+ null,
+ 90,
+ 180
+ ]
+ },
+ {
+ "subplot": "polar",
+ "type": "scatterpolar",
+ "mode": "markers+text",
+ "marker": {
+ "opacity": 1,
+ "size": [10, 40, 20]
+ },
+ "text": [10, 40, 20],
+ "textposition": ["right", "center", "top"],
+ "r": [
+ 1,
+ 2,
+ 3
+ ],
+ "theta": [
+ 270,
+ 90,
+ 180
+ ]
+ },
+ {
+ "subplot": "smith",
+ "type": "scattersmith",
+ "mode": "markers+lines",
+ "line": {
+ "width": 5,
+ "backoff": [30, 20]
+ },
+ "marker": {
+ "standoff": [5, 20, null, 20, 10],
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "real": [
+ 1,
+ 2,
+ null,
+ 2,
+ 0.5
+ ],
+ "imag": [
+ -0.5,
+ 1,
+ null,
+ 1,
+ 1
+ ]
+ },
+ {
+ "subplot": "smith",
+ "type": "scattersmith",
+ "mode": "markers+text",
+ "marker": {
+ "opacity": 1,
+ "size": [10, 40, 20]
+ },
+ "text": [10, 40, 20],
+ "textposition": ["right", "center", "top"],
+ "real": [
+ 1,
+ 2,
+ 0.5
+ ],
+ "imag": [
+ -0.5,
+ 1,
+ 1
+ ]
+ }
+ ],
+ "layout": {
+ "xaxis": {
+ "domain": [
+ 0,
+ 0.3
+ ]
+ },
+ "yaxis": {
+ "domain": [
+ 0,
+ 0.45
+ ]
+ },
+ "xaxis2": {
+ "anchor": "y2",
+ "domain": [
+ 0.35,
+ 0.65
+ ]
+ },
+ "yaxis2": {
+ "anchor": "x2",
+ "domain": [
+ 0.55,
+ 1
+ ]
+ },
+ "geo": {
+ "projection": {
+ "type": "satellite"
+ },
+ "domain": {
+ "x": [
+ 0.35,
+ 0.65
+ ],
+ "y": [
+ 0,
+ 0.45
+ ]
+ }
+ },
+ "ternary": {
+ "domain": {
+ "x": [
+ 0,
+ 0.3
+ ],
+ "y": [
+ 0.55,
+ 1
+ ]
+ },
+ "aaxis": {
+ "title": {"text": "A"}
+ },
+ "baxis": {
+ "title": {"text": "B"}
+ },
+ "caxis": {
+ "title": {"text": "C"}
+ }
+ },
+ "polar": {
+ "domain": {
+ "x": [
+ 0.7,
+ 1
+ ],
+ "y": [
+ 0,
+ 0.45
+ ]
+ }
+ },
+ "smith": {
+ "domain": {
+ "x": [
+ 0.7,
+ 1
+ ],
+ "y": [
+ 0.55,
+ 1
+ ]
+ }
+ },
+ "height": 900,
+ "width": 1200,
+ "legend": {
+ "orientation": "h"
+ }
+ }
+}
diff --git a/test/image/mocks/z-marker-standoff_auto-backoff.json b/test/image/mocks/z-marker-standoff_auto-backoff.json
new file mode 100644
index 00000000000..fad2bed639b
--- /dev/null
+++ b/test/image/mocks/z-marker-standoff_auto-backoff.json
@@ -0,0 +1,402 @@
+{
+ "data": [
+ {
+ "mode": "markers+lines",
+ "line": {
+ "width": 5
+ },
+ "marker": {
+ "line": {
+ "width": 2,
+ "color": "darkblue"
+ },
+ "standoff": [5, 20, null, 20, 10],
+ "angleref": "previous",
+ "symbol": "arrow-bar-up",
+ "size": 20
+ },
+ "x": [
+ 1,
+ 2,
+ null,
+ 2,
+ 3
+ ],
+ "y": [
+ 3,
+ 1,
+ null,
+ 1,
+ 2
+ ]
+ },
+ {
+ "mode": "markers+text",
+ "marker": {
+ "opacity": 1,
+ "size": [10, 40, 20]
+ },
+ "text": [10, 40, 20],
+ "textposition": ["right", "center", "top"],
+ "x": [
+ 1,
+ 2,
+ 3
+ ],
+ "y": [
+ 3,
+ 1,
+ 2
+ ]
+ },
+ {
+ "type": "scattergeo",
+ "mode": "markers+lines",
+ "line": { "width": 5 },
+ "marker": {
+ "standoff": [5, 20, null, 20, 10],
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "lon": [
+ -30,
+ 0,
+ null,
+ 0,
+ 30
+ ],
+ "lat": [
+ 20,
+ -5,
+ null,
+ -5,
+ 10
+ ]
+ },
+ {
+ "type": "scattergeo",
+ "mode": "markers+text",
+ "marker": {
+ "opacity": 1,
+ "size": [10, 40, 20]
+ },
+ "text": [10, 40, 20],
+ "textposition": ["right", "center", "top"],
+ "lon": [
+ -30,
+ 0,
+ 30
+ ],
+ "lat": [
+ 20,
+ -5,
+ 10
+ ]
+ },
+ {
+ "type": "scatterternary",
+ "mode": "markers+lines",
+ "line": {
+ "width": 5
+ },
+ "marker": {
+ "standoff": [5, 20, null, 20, 10],
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "a": [
+ 2,
+ 1,
+ null,
+ 1,
+ 1
+ ],
+ "b": [
+ 1,
+ 2,
+ null,
+ 2,
+ 1
+ ],
+ "c": [
+ 1,
+ 1,
+ null,
+ 1,
+ 2
+ ]
+ },
+ {
+ "type": "scatterternary",
+ "mode": "markers+text",
+ "marker": {
+ "opacity": 1,
+ "size": [10, 40, 20]
+ },
+ "text": [10, 40, 20],
+ "textposition": ["right", "center", "top"],
+ "a": [
+ 2,
+ 1,
+ 1
+ ],
+ "b": [
+ 1,
+ 2,
+ 1
+ ],
+ "c": [
+ 1,
+ 1,
+ 2
+ ]
+ },
+ {
+ "xaxis": "x2",
+ "yaxis": "y2",
+ "type": "carpet",
+ "a": [ 4, 4, 4, 4.5, 4.5, 4.5, 5, 5, 5, 6, 6, 6 ],
+ "b": [ 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3 ],
+ "y": [ 2, 3.5, 4, 3, 4.5, 5, 5.5, 6.5, 7.5, 8, 8.5, 10 ],
+ "aaxis": {
+ "tickprefix": "a = ",
+ "ticksuffix": "m",
+ "smoothing": 1,
+ "minorgridcount": 9
+ },
+ "baxis": {
+ "tickprefix": "b = ",
+ "ticksuffix": "Pa",
+ "smoothing": 1,
+ "minorgridcount": 9
+ },
+ "carpet": "c0"
+ },
+ {
+ "xaxis": "x2",
+ "yaxis": "y2",
+ "type": "scattercarpet",
+ "mode": "markers+lines",
+ "line": {
+ "width": 5
+ },
+ "marker": {
+ "standoff": [5, 20, null, 20, 10],
+ "angleref": "previous",
+ "symbol": "arrow",
+ "size": 20
+ },
+ "a": [ 4, 5, null, 5, 6 ],
+ "b": [ 2.5, 2.5, null, 2.5, 2.5 ],
+ "carpet": "c0"
+ },
+ {
+ "xaxis": "x2",
+ "yaxis": "y2",
+ "type": "scattercarpet",
+ "mode": "markers+text",
+ "marker": {
+ "opacity": 1,
+ "size": [10, 40, 20]
+ },
+ "text": [10, 40, 20],
+ "textposition": ["right", "center", "top"],
+ "a": [ 4, 5, 6 ],
+ "b": [ 2.5, 2.5, 2.5 ],
+ "carpet": "c0"
+ },
+ {
+ "subplot": "polar",
+ "type": "scatterpolar",
+ "mode": "markers+lines",
+ "line": {
+ "width": 5
+ },
+ "marker": {
+ "standoff": [5, 20, null, 20, 10],
+ "angleref": "previous",
+ "symbol": "arrow-up",
+ "size": 20
+ },
+ "r": [
+ 1,
+ 2,
+ null,
+ 2,
+ 3
+ ],
+ "theta": [
+ 270,
+ 90,
+ null,
+ 90,
+ 180
+ ]
+ },
+ {
+ "subplot": "polar",
+ "type": "scatterpolar",
+ "mode": "markers+text",
+ "marker": {
+ "opacity": 1,
+ "size": [10, 40, 20]
+ },
+ "text": [10, 40, 20],
+ "textposition": ["right", "center", "top"],
+ "r": [
+ 1,
+ 2,
+ 3
+ ],
+ "theta": [
+ 270,
+ 90,
+ 180
+ ]
+ },
+ {
+ "subplot": "smith",
+ "type": "scattersmith",
+ "mode": "markers+lines",
+ "line": {
+ "width": 5
+ },
+ "marker": {
+ "standoff": [5, 20, null, 20, 10],
+ "angleref": "previous",
+ "symbol": "arrow-wide",
+ "size": 20
+ },
+ "real": [
+ 1,
+ 2,
+ null,
+ 2,
+ 0.5
+ ],
+ "imag": [
+ -0.5,
+ 1,
+ null,
+ 1,
+ 1
+ ]
+ },
+ {
+ "subplot": "smith",
+ "type": "scattersmith",
+ "mode": "markers+text",
+ "marker": {
+ "opacity": 1,
+ "size": [10, 40, 20]
+ },
+ "text": [10, 40, 20],
+ "textposition": ["right", "center", "top"],
+ "real": [
+ 1,
+ 2,
+ 0.5
+ ],
+ "imag": [
+ -0.5,
+ 1,
+ 1
+ ]
+ }
+ ],
+ "layout": {
+ "xaxis": {
+ "domain": [
+ 0,
+ 0.3
+ ]
+ },
+ "yaxis": {
+ "domain": [
+ 0,
+ 0.45
+ ]
+ },
+ "xaxis2": {
+ "anchor": "y2",
+ "domain": [
+ 0.35,
+ 0.65
+ ]
+ },
+ "yaxis2": {
+ "anchor": "x2",
+ "domain": [
+ 0.55,
+ 1
+ ]
+ },
+ "geo": {
+ "projection": {
+ "type": "satellite"
+ },
+ "domain": {
+ "x": [
+ 0.35,
+ 0.65
+ ],
+ "y": [
+ 0,
+ 0.45
+ ]
+ }
+ },
+ "ternary": {
+ "domain": {
+ "x": [
+ 0,
+ 0.3
+ ],
+ "y": [
+ 0.55,
+ 1
+ ]
+ },
+ "aaxis": {
+ "title": {"text": "A"}
+ },
+ "baxis": {
+ "title": {"text": "B"}
+ },
+ "caxis": {
+ "title": {"text": "C"}
+ }
+ },
+ "polar": {
+ "domain": {
+ "x": [
+ 0.7,
+ 1
+ ],
+ "y": [
+ 0,
+ 0.45
+ ]
+ }
+ },
+ "smith": {
+ "domain": {
+ "x": [
+ 0.7,
+ 1
+ ],
+ "y": [
+ 0.55,
+ 1
+ ]
+ }
+ },
+ "height": 900,
+ "width": 1200,
+ "legend": {
+ "orientation": "h"
+ }
+ }
+}
diff --git a/test/image/mocks/z-marker_symbols-angle.json b/test/image/mocks/z-marker_symbols-angle.json
new file mode 100644
index 00000000000..57485c39cfa
--- /dev/null
+++ b/test/image/mocks/z-marker_symbols-angle.json
@@ -0,0 +1,603 @@
+{
+ "data": [
+ {
+ "mode": "markers",
+ "x": [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5,
+ 7
+ ],
+ "y": [
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
+ ],
+ "marker": { "angle": 15,
+ "symbol": [
+ "circle",
+ "square",
+ "diamond",
+ "cross",
+ "x",
+ "triangle-up",
+ "triangle-down",
+ "triangle-left",
+ "triangle-right",
+ "triangle-ne",
+ "triangle-se",
+ "triangle-sw",
+ "triangle-nw",
+ "pentagon",
+ "hexagon",
+ "hexagon2",
+ "octagon",
+ "star",
+ "hexagram",
+ "star-triangle-up",
+ "star-triangle-down",
+ "star-square",
+ "star-diamond",
+ "diamond-tall",
+ "diamond-wide",
+ "hourglass",
+ "bowtie",
+ "circle-cross",
+ "circle-x",
+ "square-cross",
+ "square-x",
+ "diamond-cross",
+ "diamond-x",
+ "cross-thin",
+ "x-thin",
+ "asterisk",
+ "hash",
+ "y-up",
+ "y-down",
+ "y-left",
+ "y-right",
+ "line-ew",
+ "line-ns",
+ "line-ne",
+ "line-nw",
+ "arrow-up",
+ "arrow-down",
+ "arrow-left",
+ "arrow-right",
+ "arrow-bar-up",
+ "arrow-bar-down",
+ "arrow-bar-left",
+ "arrow-bar-right",
+ "arrow",
+ "arrow-wide"
+ ],
+ "color": "blue",
+ "size": 20,
+ "line": {
+ "color": "orange",
+ "width": 1.5
+ }
+ },
+ "text": [
+ "marker symbol: circle
number: 0",
+ "marker symbol: square
number: 1",
+ "marker symbol: diamond
number: 2",
+ "marker symbol: cross
number: 3",
+ "marker symbol: x
number: 4",
+ "marker symbol: triangle-up
number: 5",
+ "marker symbol: triangle-down
number: 6",
+ "marker symbol: triangle-left
number: 7",
+ "marker symbol: triangle-right
number: 8",
+ "marker symbol: triangle-ne
number: 9",
+ "marker symbol: triangle-se
number: 10",
+ "marker symbol: triangle-sw
number: 11",
+ "marker symbol: triangle-nw
number: 12",
+ "marker symbol: pentagon
number: 13",
+ "marker symbol: hexagon
number: 14",
+ "marker symbol: hexagon2
number: 15",
+ "marker symbol: octagon
number: 16",
+ "marker symbol: star
number: 17",
+ "marker symbol: hexagram
number: 18",
+ "marker symbol: star-triangle-up
number: 19",
+ "marker symbol: star-triangle-down
number: 20",
+ "marker symbol: star-square
number: 21",
+ "marker symbol: star-diamond
number: 22",
+ "marker symbol: diamond-tall
number: 23",
+ "marker symbol: diamond-wide
number: 24",
+ "marker symbol: hourglass
number: 25",
+ "marker symbol: bowtie
number: 26",
+ "marker symbol: circle-cross
number: 27",
+ "marker symbol: circle-x
number: 28",
+ "marker symbol: square-cross
number: 29",
+ "marker symbol: square-x
number: 30",
+ "marker symbol: diamond-cross
number: 31",
+ "marker symbol: diamond-x
number: 32",
+ "marker symbol: cross-thin
number: 33",
+ "marker symbol: x-thin
number: 34",
+ "marker symbol: asterisk
number: 35",
+ "marker symbol: hash
number: 36",
+ "marker symbol: y-up
number: 37",
+ "marker symbol: y-down
number: 38",
+ "marker symbol: y-left
number: 39",
+ "marker symbol: y-right
number: 40",
+ "marker symbol: line-ew
number: 41",
+ "marker symbol: line-ns
number: 42",
+ "marker symbol: line-ne
number: 43",
+ "marker symbol: line-nw
number: 44",
+ "marker symbol: arrow-up
number: 45",
+ "marker symbol: arrow-down
number: 46",
+ "marker symbol: arrow-left
number: 47",
+ "marker symbol: arrow-right
number: 48",
+ "marker symbol: arrow-bar-up
number: 49",
+ "marker symbol: arrow-bar-down
number: 50",
+ "marker symbol: arrow-bar-left
number: 51",
+ "marker symbol: arrow-bar-right
number: 52",
+ "marker symbol: arrow
number: 53",
+ "marker symbol: arrow-wide
number: 54"
+ ],
+ "hoverinfo": "text"
+ },
+ {
+ "mode": "markers",
+ "x": [
+ 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 14.5, 14.5, 14.5, 14.5, 14.5, 14.5, 14.5, 14.5, 14.5,
+ 16
+ ],
+ "y": [
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
+ ],
+ "marker": { "angle": 15,
+ "symbol": [
+ "circle-open",
+ "square-open",
+ "diamond-open",
+ "cross-open",
+ "x-open",
+ "triangle-up-open",
+ "triangle-down-open",
+ "triangle-left-open",
+ "triangle-right-open",
+ "triangle-ne-open",
+ "triangle-se-open",
+ "triangle-sw-open",
+ "triangle-nw-open",
+ "pentagon-open",
+ "hexagon-open",
+ "hexagon2-open",
+ "octagon-open",
+ "star-open",
+ "hexagram-open",
+ "star-triangle-up-open",
+ "star-triangle-down-open",
+ "star-square-open",
+ "star-diamond-open",
+ "diamond-tall-open",
+ "diamond-wide-open",
+ "hourglass-open",
+ "bowtie-open",
+ "circle-cross-open",
+ "circle-x-open",
+ "square-cross-open",
+ "square-x-open",
+ "diamond-cross-open",
+ "diamond-x-open",
+ "cross-thin-open",
+ "x-thin-open",
+ "asterisk-open",
+ "hash-open",
+ "y-up-open",
+ "y-down-open",
+ "y-left-open",
+ "y-right-open",
+ "line-ew-open",
+ "line-ns-open",
+ "line-ne-open",
+ "line-nw-open",
+ "arrow-up-open",
+ "arrow-down-open",
+ "arrow-left-open",
+ "arrow-right-open",
+ "arrow-bar-up-open",
+ "arrow-bar-down-open",
+ "arrow-bar-left-open",
+ "arrow-bar-right-open",
+ "arrow-open",
+ "arrow-wide-open"
+ ],
+ "color": "blue",
+ "size": 20,
+ "line": {
+ "color": "orange",
+ "width": 1.5
+ }
+ },
+ "text": [
+ "marker symbol: circle-open
number: 100",
+ "marker symbol: square-open
number: 101",
+ "marker symbol: diamond-open
number: 102",
+ "marker symbol: cross-open
number: 103",
+ "marker symbol: x-open
number: 104",
+ "marker symbol: triangle-up-open
number: 105",
+ "marker symbol: triangle-down-open
number: 106",
+ "marker symbol: triangle-left-open
number: 107",
+ "marker symbol: triangle-right-open
number: 108",
+ "marker symbol: triangle-ne-open
number: 109",
+ "marker symbol: triangle-se-open
number: 110",
+ "marker symbol: triangle-sw-open
number: 111",
+ "marker symbol: triangle-nw-open
number: 112",
+ "marker symbol: pentagon-open
number: 113",
+ "marker symbol: hexagon-open
number: 114",
+ "marker symbol: hexagon2-open
number: 115",
+ "marker symbol: octagon-open
number: 116",
+ "marker symbol: star-open
number: 117",
+ "marker symbol: hexagram-open
number: 118",
+ "marker symbol: star-triangle-up-open
number: 119",
+ "marker symbol: star-triangle-down-open
number: 120",
+ "marker symbol: star-square-open
number: 121",
+ "marker symbol: star-diamond-open
number: 122",
+ "marker symbol: diamond-tall-open
number: 123",
+ "marker symbol: diamond-wide-open
number: 124",
+ "marker symbol: hourglass-open
number: 125",
+ "marker symbol: bowtie-open
number: 126",
+ "marker symbol: circle-cross-open
number: 127",
+ "marker symbol: circle-x-open
number: 128",
+ "marker symbol: square-cross-open
number: 129",
+ "marker symbol: square-x-open
number: 130",
+ "marker symbol: diamond-cross-open
number: 131",
+ "marker symbol: diamond-x-open
number: 132",
+ "marker symbol: cross-thin-open
number: 133",
+ "marker symbol: x-thin-open
number: 134",
+ "marker symbol: asterisk-open
number: 135",
+ "marker symbol: hash-open
number: 136",
+ "marker symbol: y-up-open
number: 137",
+ "marker symbol: y-down-open
number: 138",
+ "marker symbol: y-left-open
number: 139",
+ "marker symbol: y-right-open
number: 140",
+ "marker symbol: line-ew-open
number: 141",
+ "marker symbol: line-ns-open
number: 142",
+ "marker symbol: line-ne-open
number: 143",
+ "marker symbol: line-nw-open
number: 144",
+ "marker symbol: arrow-up-open
number: 145",
+ "marker symbol: arrow-down-open
number: 146",
+ "marker symbol: arrow-left-open
number: 147",
+ "marker symbol: arrow-right-open
number: 148",
+ "marker symbol: arrow-bar-up-open
number: 149",
+ "marker symbol: arrow-bar-down-open
number: 150",
+ "marker symbol: arrow-bar-left-open
number: 151",
+ "marker symbol: arrow-bar-right-open
number: 152",
+ "marker symbol: arrow-open
number: 153",
+ "marker symbol: arrow-wide-open
number: 154"
+ ],
+ "hoverinfo": "text"
+ },
+ {
+ "mode": "markers",
+ "x": [
+ 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23.5, 23.5, 23.5, 23.5, 23.5, 23.5, 23.5, 23.5, 23.5,
+ 25
+ ],
+ "y": [
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
+ ],
+ "marker": { "angle": 15,
+ "symbol": [
+ "circle-dot",
+ "square-dot",
+ "diamond-dot",
+ "cross-dot",
+ "x-dot",
+ "triangle-up-dot",
+ "triangle-down-dot",
+ "triangle-left-dot",
+ "triangle-right-dot",
+ "triangle-ne-dot",
+ "triangle-se-dot",
+ "triangle-sw-dot",
+ "triangle-nw-dot",
+ "pentagon-dot",
+ "hexagon-dot",
+ "hexagon2-dot",
+ "octagon-dot",
+ "star-dot",
+ "hexagram-dot",
+ "star-triangle-up-dot",
+ "star-triangle-down-dot",
+ "star-square-dot",
+ "star-diamond-dot",
+ "diamond-tall-dot",
+ "diamond-wide-dot",
+ "hourglass-dot",
+ "bowtie-dot",
+ "circle-cross-dot",
+ "circle-x-dot",
+ "square-cross-dot",
+ "square-x-dot",
+ "diamond-cross-dot",
+ "diamond-x-dot",
+ "cross-thin-dot",
+ "x-thin-dot",
+ "asterisk-dot",
+ "hash-dot",
+ "y-up-dot",
+ "y-down-dot",
+ "y-left-dot",
+ "y-right-dot",
+ "line-ew-dot",
+ "line-ns-dot",
+ "line-ne-dot",
+ "line-nw-dot",
+ "arrow-up-dot",
+ "arrow-down-dot",
+ "arrow-left-dot",
+ "arrow-right-dot",
+ "arrow-bar-up-dot",
+ "arrow-bar-down-dot",
+ "arrow-bar-left-dot",
+ "arrow-bar-right-dot",
+ "arrow-dot",
+ "arrow-wide-dot"
+ ],
+ "color": "blue",
+ "size": 20,
+ "line": {
+ "color": "orange",
+ "width": 1.5
+ }
+ },
+ "text": [
+ "marker symbol: circle-dot
number: 200",
+ "marker symbol: square-dot
number: 201",
+ "marker symbol: diamond-dot
number: 202",
+ "marker symbol: cross-dot
number: 203",
+ "marker symbol: x-dot
number: 204",
+ "marker symbol: triangle-up-dot
number: 205",
+ "marker symbol: triangle-down-dot
number: 206",
+ "marker symbol: triangle-left-dot
number: 207",
+ "marker symbol: triangle-right-dot
number: 208",
+ "marker symbol: triangle-ne-dot
number: 209",
+ "marker symbol: triangle-se-dot
number: 210",
+ "marker symbol: triangle-sw-dot
number: 211",
+ "marker symbol: triangle-nw-dot
number: 212",
+ "marker symbol: pentagon-dot
number: 213",
+ "marker symbol: hexagon-dot
number: 214",
+ "marker symbol: hexagon2-dot
number: 215",
+ "marker symbol: octagon-dot
number: 216",
+ "marker symbol: star-dot
number: 217",
+ "marker symbol: hexagram-dot
number: 218",
+ "marker symbol: star-triangle-up-dot
number: 219",
+ "marker symbol: star-triangle-down-dot
number: 220",
+ "marker symbol: star-square-dot
number: 221",
+ "marker symbol: star-diamond-dot
number: 222",
+ "marker symbol: diamond-tall-dot
number: 223",
+ "marker symbol: diamond-wide-dot
number: 224",
+ "marker symbol: hourglass-dot
number: 225",
+ "marker symbol: bowtie-dot
number: 226",
+ "marker symbol: circle-cross-dot
number: 227",
+ "marker symbol: circle-x-dot
number: 228",
+ "marker symbol: square-cross-dot
number: 229",
+ "marker symbol: square-x-dot
number: 230",
+ "marker symbol: diamond-cross-dot
number: 231",
+ "marker symbol: diamond-x-dot
number: 232",
+ "marker symbol: cross-thin-dot
number: 233",
+ "marker symbol: x-thin-dot
number: 234",
+ "marker symbol: asterisk-dot
number: 235",
+ "marker symbol: hash-dot
number: 236",
+ "marker symbol: y-up-dot
number: 237",
+ "marker symbol: y-down-dot
number: 238",
+ "marker symbol: y-left-dot
number: 239",
+ "marker symbol: y-right-dot
number: 240",
+ "marker symbol: line-ew-dot
number: 241",
+ "marker symbol: line-ns-dot
number: 242",
+ "marker symbol: line-ne-dot
number: 243",
+ "marker symbol: line-nw-dot
number: 244",
+ "marker symbol: arrow-up-dot
number: 245",
+ "marker symbol: arrow-down-dot
number: 246",
+ "marker symbol: arrow-left-dot
number: 247",
+ "marker symbol: arrow-right-dot
number: 248",
+ "marker symbol: arrow-bar-up-dot
number: 249",
+ "marker symbol: arrow-bar-down-dot
number: 250",
+ "marker symbol: arrow-bar-left-dot
number: 251",
+ "marker symbol: arrow-bar-right-dot
number: 252",
+ "marker symbol: arrow-dot
number: 253",
+ "marker symbol: arrow-wide-dot
number: 254"
+ ],
+ "hoverinfo": "text"
+ },
+ {
+ "mode": "markers",
+ "x": [
+ 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 30, 30, 30, 30, 30, 30, 30, 30, 30,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 32.5, 32.5, 32.5, 32.5, 32.5, 32.5, 32.5, 32.5, 32.5,
+ 34
+ ],
+ "y": [
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 0
+ ],
+ "marker": { "angle": 15,
+ "symbol": [
+ "circle-open-dot",
+ "square-open-dot",
+ "diamond-open-dot",
+ "cross-open-dot",
+ "x-open-dot",
+ "triangle-up-open-dot",
+ "triangle-down-open-dot",
+ "triangle-left-open-dot",
+ "triangle-right-open-dot",
+ "triangle-ne-open-dot",
+ "triangle-se-open-dot",
+ "triangle-sw-open-dot",
+ "triangle-nw-open-dot",
+ "pentagon-open-dot",
+ "hexagon-open-dot",
+ "hexagon2-open-dot",
+ "octagon-open-dot",
+ "star-open-dot",
+ "hexagram-open-dot",
+ "star-triangle-up-open-dot",
+ "star-triangle-down-open-dot",
+ "star-square-open-dot",
+ "star-diamond-open-dot",
+ "diamond-tall-open-dot",
+ "diamond-wide-open-dot",
+ "hourglass-open-dot",
+ "bowtie-open-dot",
+ "circle-cross-open-dot",
+ "circle-x-open-dot",
+ "square-cross-open-dot",
+ "square-x-open-dot",
+ "diamond-cross-open-dot",
+ "diamond-x-open-dot",
+ "cross-thin-open-dot",
+ "x-thin-open-dot",
+ "asterisk-open-dot",
+ "hash-open-dot",
+ "y-up-open-dot",
+ "y-down-open-dot",
+ "y-left-open-dot",
+ "y-right-open-dot",
+ "line-ew-open-dot",
+ "line-ns-open-dot",
+ "line-ne-open-dot",
+ "line-nw-open-dot",
+ "arrow-up-open-dot",
+ "arrow-down-open-dot",
+ "arrow-left-open-dot",
+ "arrow-right-open-dot",
+ "arrow-bar-up-open-dot",
+ "arrow-bar-down-open-dot",
+ "arrow-bar-left-open-dot",
+ "arrow-bar-right-open-dot",
+ "arrow-open-dot",
+ "arrow-wide-open-dot"
+ ],
+ "color": "blue",
+ "size": 20,
+ "line": {
+ "color": "orange",
+ "width": 1.5
+ }
+ },
+ "text": [
+ "marker symbol: circle-open-dot
number: 300",
+ "marker symbol: square-open-dot
number: 301",
+ "marker symbol: diamond-open-dot
number: 302",
+ "marker symbol: cross-open-dot
number: 303",
+ "marker symbol: x-open-dot
number: 304",
+ "marker symbol: triangle-up-open-dot
number: 305",
+ "marker symbol: triangle-down-open-dot
number: 306",
+ "marker symbol: triangle-left-open-dot
number: 307",
+ "marker symbol: triangle-right-open-dot
number: 308",
+ "marker symbol: triangle-ne-open-dot
number: 309",
+ "marker symbol: triangle-se-open-dot
number: 310",
+ "marker symbol: triangle-sw-open-dot
number: 311",
+ "marker symbol: triangle-nw-open-dot
number: 312",
+ "marker symbol: pentagon-open-dot
number: 313",
+ "marker symbol: hexagon-open-dot
number: 314",
+ "marker symbol: hexagon2-open-dot
number: 315",
+ "marker symbol: octagon-open-dot
number: 316",
+ "marker symbol: star-open-dot
number: 317",
+ "marker symbol: hexagram-open-dot
number: 318",
+ "marker symbol: star-triangle-up-open-dot
number: 319",
+ "marker symbol: star-triangle-down-open-dot
number: 320",
+ "marker symbol: star-square-open-dot
number: 321",
+ "marker symbol: star-diamond-open-dot
number: 322",
+ "marker symbol: diamond-tall-open-dot
number: 323",
+ "marker symbol: diamond-wide-open-dot
number: 324",
+ "marker symbol: hourglass-open-dot
number: 325",
+ "marker symbol: bowtie-open-dot
number: 326",
+ "marker symbol: circle-cross-open-dot
number: 327",
+ "marker symbol: circle-x-open-dot
number: 328",
+ "marker symbol: square-cross-open-dot
number: 329",
+ "marker symbol: square-x-open-dot
number: 330",
+ "marker symbol: diamond-cross-open-dot
number: 331",
+ "marker symbol: diamond-x-open-dot
number: 332",
+ "marker symbol: cross-thin-open-dot
number: 333",
+ "marker symbol: x-thin-open-dot
number: 334",
+ "marker symbol: asterisk-open-dot
number: 335",
+ "marker symbol: hash-open-dot
number: 336",
+ "marker symbol: y-up-open-dot
number: 337",
+ "marker symbol: y-down-open-dot
number: 338",
+ "marker symbol: y-left-open-dot
number: 339",
+ "marker symbol: y-right-open-dot
number: 340",
+ "marker symbol: line-ew-open-dot
number: 341",
+ "marker symbol: line-ns-open-dot
number: 342",
+ "marker symbol: line-ne-open-dot
number: 343",
+ "marker symbol: line-nw-open-dot
number: 344",
+ "marker symbol: line-nw-open-dot
number: 344",
+ "marker symbol: arrow-up-open-dot
number: 345",
+ "marker symbol: arrow-down-open-dot
number: 346",
+ "marker symbol: arrow-left-open-dot
number: 347",
+ "marker symbol: arrow-right-open-dot
number: 348",
+ "marker symbol: arrow-bar-up-open-dot
number: 349",
+ "marker symbol: arrow-bar-down-open-dot
number: 350",
+ "marker symbol: arrow-bar-left-open-dot
number: 351",
+ "marker symbol: arrow-bar-right-open-dot
number: 352",
+ "marker symbol: arrow-open-dot
number: 353",
+ "marker symbol: arrow-wide-open-dot
number: 354"
+ ],
+ "hoverinfo": "text"
+ }
+ ],
+ "layout": {
+ "margin": {
+ "l": 0,
+ "r": 0,
+ "b": 0,
+ "t": 0
+ },
+ "width": 1500,
+ "height": 500,
+ "xaxis": {
+ "showgrid": false,
+ "zeroline": false
+ },
+ "yaxis": {
+ "showgrid": false,
+ "zeroline": false,
+ "autorange": "reversed"
+ },
+ "showlegend": false,
+ "plot_bgcolor": "#d3d3d3",
+ "hovermode": "closest"
+ }
+}
diff --git a/test/jasmine/tests/geo_test.js b/test/jasmine/tests/geo_test.js
index f28ff0e7d70..11d0f7d9eab 100644
--- a/test/jasmine/tests/geo_test.js
+++ b/test/jasmine/tests/geo_test.js
@@ -2732,6 +2732,43 @@ describe('Test geo zoom/pan/drag interactions:', function() {
});
});
+describe('Test geo interactions update marker angles:', function() {
+ var gd;
+
+ beforeEach(function() { gd = createGraphDiv(); });
+
+ afterEach(destroyGraphDiv);
+
+ function getPath() {
+ return d3Select('.scattergeo .point').node().getAttribute('d');
+ }
+
+ it('update angles when panning', function(done) {
+ var fig = Lib.extendDeep({}, require('@mocks/geo_conic-conformal'));
+ fig.layout.width = 700;
+ fig.layout.height = 500;
+ fig.layout.dragmode = 'pan';
+
+ var initialPath, newPath;
+
+ Plotly.newPlot(gd, fig)
+ .then(function() {
+ initialPath = getPath();
+
+ return drag({path: [[300, 200], [350, 250], [400, 300]], noCover: true});
+ })
+ .then(function() {
+ newPath = getPath();
+ expect(newPath).toEqual('M0,0L18.238949513733473,8.206139204003389L19.579067718529352,-4.081679467234269Z');
+
+ expect(newPath).not.toEqual(initialPath);
+ expect(newPath).toEqual('M0,0L18.238949513733473,8.206139204003389L19.579067718529352,-4.081679467234269Z');
+ expect(initialPath).toEqual('M0,0L-1.5033314641545745,19.94341982983066L10.506227353572104,17.01820163222463Z');
+ })
+ .then(done, done.fail);
+ });
+});
+
describe('plotly_relayouting', function() {
var gd;
var events;
diff --git a/test/jasmine/tests/hover_label_test.js b/test/jasmine/tests/hover_label_test.js
index 66ea5a85b58..a2064d33db1 100644
--- a/test/jasmine/tests/hover_label_test.js
+++ b/test/jasmine/tests/hover_label_test.js
@@ -3999,6 +3999,9 @@ describe('hover distance', function() {
describe('closest hovermode', function() {
var mockCopy = Lib.extendDeep({}, mock);
mockCopy.layout.hovermode = 'closest';
+ // use simple markers here
+ delete mockCopy.data[0].marker;
+ delete mockCopy.data[1].marker;
beforeEach(function(done) {
Plotly.newPlot(createGraphDiv(), mockCopy.data, mockCopy.layout).then(done);
diff --git a/test/jasmine/tests/scatterternary_test.js b/test/jasmine/tests/scatterternary_test.js
index 3d947a02b8b..1b762f981ed 100644
--- a/test/jasmine/tests/scatterternary_test.js
+++ b/test/jasmine/tests/scatterternary_test.js
@@ -455,6 +455,8 @@ describe('Test scatterternary *cliponaxis*', function() {
it('should show/hide point/text/errorbars in clipped and non-clipped layers', function(done) {
var gd = createGraphDiv();
var fig = Lib.extendDeep({}, require('@mocks/ternary_markers.json'));
+ // use simple markers here
+ delete fig.data[0].marker;
function _assert(layerClips, nodeDisplays, lineClips) {
var frontLayer = d3Select('.frontplot');
diff --git a/test/plot-schema.json b/test/plot-schema.json
index 353097973cb..de21dc77c47 100644
--- a/test/plot-schema.json
+++ b/test/plot-schema.json
@@ -435,7 +435,8 @@
"angle": {
"description": "A number (in degree) between -180 and 180.",
"otherOpts": [
- "dflt"
+ "dflt",
+ "arrayOk"
],
"requiredOpts": []
},
@@ -15451,6 +15452,13 @@
"valType": "string"
},
"marker": {
+ "angle": {
+ "arrayOk": false,
+ "description": "Sets the marker angle in respect to `angleref`.",
+ "dflt": 0,
+ "editType": "calc",
+ "valType": "angle"
+ },
"color": {
"arrayOk": false,
"description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `marker.cmin` and `marker.cmax` if set.",
@@ -15993,7 +16001,19 @@
"arrow-bar-right",
152,
"152",
- "arrow-bar-right-open"
+ "arrow-bar-right-open",
+ 53,
+ "53",
+ "arrow",
+ 153,
+ "153",
+ "arrow-open",
+ 54,
+ "54",
+ "arrow-wide",
+ 154,
+ "154",
+ "arrow-wide-open"
]
}
},
@@ -43252,6 +43272,19 @@
"valType": "number"
},
"line": {
+ "backoff": {
+ "arrayOk": true,
+ "description": "Sets the line back off from the end point of the nth line segment (in px). This option is useful e.g. to avoid overlap with arrowhead markers. With *auto* the lines would trim before markers if `marker.angleref` is set to *previous*.",
+ "dflt": "auto",
+ "editType": "plot",
+ "min": 0,
+ "valType": "number"
+ },
+ "backoffsrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `backoff`.",
+ "editType": "none",
+ "valType": "string"
+ },
"color": {
"anim": true,
"description": "Sets the line color.",
@@ -43312,6 +43345,30 @@
}
},
"marker": {
+ "angle": {
+ "anim": false,
+ "arrayOk": true,
+ "description": "Sets the marker angle in respect to `angleref`.",
+ "dflt": 0,
+ "editType": "plot",
+ "valType": "angle"
+ },
+ "angleref": {
+ "anim": false,
+ "description": "Sets the reference for marker angle. With *previous*, angle 0 points along the line from the previous point to this one. With *up*, angle 0 points toward the top of the screen.",
+ "dflt": "up",
+ "editType": "plot",
+ "valType": "enumerated",
+ "values": [
+ "previous",
+ "up"
+ ]
+ },
+ "anglesrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `angle`.",
+ "editType": "none",
+ "valType": "string"
+ },
"autocolorscale": {
"description": "Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. Has an effect only if in `marker.color` is set to a numerical array. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed.",
"dflt": true,
@@ -44060,6 +44117,20 @@
"editType": "none",
"valType": "string"
},
+ "standoff": {
+ "anim": true,
+ "arrayOk": true,
+ "description": "Moves the marker away from the data point in the direction of `angle` (in px). This can be useful for example if you have another marker at this location and you want to point an arrowhead marker at it.",
+ "dflt": 0,
+ "editType": "plot",
+ "min": 0,
+ "valType": "number"
+ },
+ "standoffsrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `standoff`.",
+ "editType": "none",
+ "valType": "string"
+ },
"symbol": {
"arrayOk": true,
"description": "Sets the marker symbol type. Adding 100 is equivalent to appending *-open* to a symbol name. Adding 200 is equivalent to appending *-dot* to a symbol name. Adding 300 is equivalent to appending *-open-dot* or *dot-open* to a symbol name.",
@@ -44540,7 +44611,19 @@
"arrow-bar-right",
152,
"152",
- "arrow-bar-right-open"
+ "arrow-bar-right-open",
+ 53,
+ "53",
+ "arrow",
+ 153,
+ "153",
+ "arrow-open",
+ 54,
+ "54",
+ "arrow-wide",
+ 154,
+ "154",
+ "arrow-wide-open"
]
},
"symbolsrc": {
@@ -47492,6 +47575,19 @@
"valType": "number"
},
"line": {
+ "backoff": {
+ "arrayOk": true,
+ "description": "Sets the line back off from the end point of the nth line segment (in px). This option is useful e.g. to avoid overlap with arrowhead markers. With *auto* the lines would trim before markers if `marker.angleref` is set to *previous*.",
+ "dflt": "auto",
+ "editType": "plot",
+ "min": 0,
+ "valType": "number"
+ },
+ "backoffsrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `backoff`.",
+ "editType": "none",
+ "valType": "string"
+ },
"color": {
"description": "Sets the line color.",
"editType": "style",
@@ -47540,6 +47636,28 @@
}
},
"marker": {
+ "angle": {
+ "arrayOk": true,
+ "description": "Sets the marker angle in respect to `angleref`.",
+ "dflt": 0,
+ "editType": "plot",
+ "valType": "angle"
+ },
+ "angleref": {
+ "description": "Sets the reference for marker angle. With *previous*, angle 0 points along the line from the previous point to this one. With *up*, angle 0 points toward the top of the screen.",
+ "dflt": "up",
+ "editType": "plot",
+ "valType": "enumerated",
+ "values": [
+ "previous",
+ "up"
+ ]
+ },
+ "anglesrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `angle`.",
+ "editType": "none",
+ "valType": "string"
+ },
"autocolorscale": {
"description": "Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. Has an effect only if in `marker.color` is set to a numerical array. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed.",
"dflt": true,
@@ -48283,6 +48401,19 @@
"editType": "none",
"valType": "string"
},
+ "standoff": {
+ "arrayOk": true,
+ "description": "Moves the marker away from the data point in the direction of `angle` (in px). This can be useful for example if you have another marker at this location and you want to point an arrowhead marker at it.",
+ "dflt": 0,
+ "editType": "plot",
+ "min": 0,
+ "valType": "number"
+ },
+ "standoffsrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `standoff`.",
+ "editType": "none",
+ "valType": "string"
+ },
"symbol": {
"arrayOk": true,
"description": "Sets the marker symbol type. Adding 100 is equivalent to appending *-open* to a symbol name. Adding 200 is equivalent to appending *-dot* to a symbol name. Adding 300 is equivalent to appending *-open-dot* or *dot-open* to a symbol name.",
@@ -48763,7 +48894,19 @@
"arrow-bar-right",
152,
"152",
- "arrow-bar-right-open"
+ "arrow-bar-right-open",
+ 53,
+ "53",
+ "arrow",
+ 153,
+ "153",
+ "arrow-open",
+ 54,
+ "54",
+ "arrow-wide",
+ 154,
+ "154",
+ "arrow-wide-open"
]
},
"symbolsrc": {
@@ -49375,6 +49518,29 @@
"valType": "string"
},
"marker": {
+ "angle": {
+ "arrayOk": true,
+ "description": "Sets the marker angle in respect to `angleref`.",
+ "dflt": 0,
+ "editType": "calc",
+ "valType": "angle"
+ },
+ "angleref": {
+ "description": "Sets the reference for marker angle. With *previous*, angle 0 points along the line from the previous point to this one. With *up*, angle 0 points toward the top of the screen. With *north*, angle 0 points north based on the current map projection.",
+ "dflt": "up",
+ "editType": "calc",
+ "valType": "enumerated",
+ "values": [
+ "previous",
+ "up",
+ "north"
+ ]
+ },
+ "anglesrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `angle`.",
+ "editType": "none",
+ "valType": "string"
+ },
"autocolorscale": {
"description": "Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. Has an effect only if in `marker.color` is set to a numerical array. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed.",
"dflt": true,
@@ -50111,6 +50277,19 @@
"editType": "none",
"valType": "string"
},
+ "standoff": {
+ "arrayOk": true,
+ "description": "Moves the marker away from the data point in the direction of `angle` (in px). This can be useful for example if you have another marker at this location and you want to point an arrowhead marker at it.",
+ "dflt": 0,
+ "editType": "calc",
+ "min": 0,
+ "valType": "number"
+ },
+ "standoffsrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `standoff`.",
+ "editType": "none",
+ "valType": "string"
+ },
"symbol": {
"arrayOk": true,
"description": "Sets the marker symbol type. Adding 100 is equivalent to appending *-open* to a symbol name. Adding 200 is equivalent to appending *-dot* to a symbol name. Adding 300 is equivalent to appending *-open-dot* or *dot-open* to a symbol name.",
@@ -50591,7 +50770,19 @@
"arrow-bar-right",
152,
"152",
- "arrow-bar-right-open"
+ "arrow-bar-right-open",
+ 53,
+ "53",
+ "arrow",
+ 153,
+ "153",
+ "arrow-open",
+ 54,
+ "54",
+ "arrow-wide",
+ 154,
+ "154",
+ "arrow-wide-open"
]
},
"symbolsrc": {
@@ -51356,6 +51547,18 @@
}
},
"marker": {
+ "angle": {
+ "arrayOk": true,
+ "description": "Sets the marker angle in respect to `angleref`.",
+ "dflt": 0,
+ "editType": "calc",
+ "valType": "angle"
+ },
+ "anglesrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `angle`.",
+ "editType": "none",
+ "valType": "string"
+ },
"autocolorscale": {
"description": "Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. Has an effect only if in `marker.color` is set to a numerical array. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed.",
"dflt": true,
@@ -52539,7 +52742,19 @@
"arrow-bar-right",
152,
"152",
- "arrow-bar-right-open"
+ "arrow-bar-right-open",
+ 53,
+ "53",
+ "arrow",
+ 153,
+ "153",
+ "arrow-open",
+ 54,
+ "54",
+ "arrow-wide",
+ 154,
+ "154",
+ "arrow-wide-open"
]
},
"symbolsrc": {
@@ -54377,6 +54592,19 @@
"valType": "number"
},
"line": {
+ "backoff": {
+ "arrayOk": true,
+ "description": "Sets the line back off from the end point of the nth line segment (in px). This option is useful e.g. to avoid overlap with arrowhead markers. With *auto* the lines would trim before markers if `marker.angleref` is set to *previous*.",
+ "dflt": "auto",
+ "editType": "plot",
+ "min": 0,
+ "valType": "number"
+ },
+ "backoffsrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `backoff`.",
+ "editType": "none",
+ "valType": "string"
+ },
"color": {
"description": "Sets the line color.",
"editType": "style",
@@ -54425,6 +54653,28 @@
}
},
"marker": {
+ "angle": {
+ "arrayOk": true,
+ "description": "Sets the marker angle in respect to `angleref`.",
+ "dflt": 0,
+ "editType": "plot",
+ "valType": "angle"
+ },
+ "angleref": {
+ "description": "Sets the reference for marker angle. With *previous*, angle 0 points along the line from the previous point to this one. With *up*, angle 0 points toward the top of the screen.",
+ "dflt": "up",
+ "editType": "plot",
+ "valType": "enumerated",
+ "values": [
+ "previous",
+ "up"
+ ]
+ },
+ "anglesrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `angle`.",
+ "editType": "none",
+ "valType": "string"
+ },
"autocolorscale": {
"description": "Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. Has an effect only if in `marker.color` is set to a numerical array. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed.",
"dflt": true,
@@ -55168,6 +55418,19 @@
"editType": "none",
"valType": "string"
},
+ "standoff": {
+ "arrayOk": true,
+ "description": "Moves the marker away from the data point in the direction of `angle` (in px). This can be useful for example if you have another marker at this location and you want to point an arrowhead marker at it.",
+ "dflt": 0,
+ "editType": "plot",
+ "min": 0,
+ "valType": "number"
+ },
+ "standoffsrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `standoff`.",
+ "editType": "none",
+ "valType": "string"
+ },
"symbol": {
"arrayOk": true,
"description": "Sets the marker symbol type. Adding 100 is equivalent to appending *-open* to a symbol name. Adding 200 is equivalent to appending *-dot* to a symbol name. Adding 300 is equivalent to appending *-open-dot* or *dot-open* to a symbol name.",
@@ -55648,7 +55911,19 @@
"arrow-bar-right",
152,
"152",
- "arrow-bar-right-open"
+ "arrow-bar-right-open",
+ 53,
+ "53",
+ "arrow",
+ 153,
+ "153",
+ "arrow-open",
+ 54,
+ "54",
+ "arrow-wide",
+ 154,
+ "154",
+ "arrow-wide-open"
]
},
"symbolsrc": {
@@ -56263,6 +56538,18 @@
}
},
"marker": {
+ "angle": {
+ "arrayOk": true,
+ "description": "Sets the marker angle in respect to `angleref`.",
+ "dflt": 0,
+ "editType": "calc",
+ "valType": "angle"
+ },
+ "anglesrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `angle`.",
+ "editType": "none",
+ "valType": "string"
+ },
"autocolorscale": {
"description": "Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. Has an effect only if in `marker.color` is set to a numerical array. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed.",
"dflt": true,
@@ -57446,7 +57733,19 @@
"arrow-bar-right",
152,
"152",
- "arrow-bar-right-open"
+ "arrow-bar-right-open",
+ 53,
+ "53",
+ "arrow",
+ 153,
+ "153",
+ "arrow-open",
+ 54,
+ "54",
+ "arrow-wide",
+ 154,
+ "154",
+ "arrow-wide-open"
]
},
"symbolsrc": {
@@ -58030,6 +58329,19 @@
"valType": "number"
},
"line": {
+ "backoff": {
+ "arrayOk": true,
+ "description": "Sets the line back off from the end point of the nth line segment (in px). This option is useful e.g. to avoid overlap with arrowhead markers. With *auto* the lines would trim before markers if `marker.angleref` is set to *previous*.",
+ "dflt": "auto",
+ "editType": "plot",
+ "min": 0,
+ "valType": "number"
+ },
+ "backoffsrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `backoff`.",
+ "editType": "none",
+ "valType": "string"
+ },
"color": {
"description": "Sets the line color.",
"editType": "style",
@@ -58078,6 +58390,28 @@
}
},
"marker": {
+ "angle": {
+ "arrayOk": true,
+ "description": "Sets the marker angle in respect to `angleref`.",
+ "dflt": 0,
+ "editType": "plot",
+ "valType": "angle"
+ },
+ "angleref": {
+ "description": "Sets the reference for marker angle. With *previous*, angle 0 points along the line from the previous point to this one. With *up*, angle 0 points toward the top of the screen.",
+ "dflt": "up",
+ "editType": "plot",
+ "valType": "enumerated",
+ "values": [
+ "previous",
+ "up"
+ ]
+ },
+ "anglesrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `angle`.",
+ "editType": "none",
+ "valType": "string"
+ },
"autocolorscale": {
"description": "Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. Has an effect only if in `marker.color` is set to a numerical array. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed.",
"dflt": true,
@@ -58821,6 +59155,19 @@
"editType": "none",
"valType": "string"
},
+ "standoff": {
+ "arrayOk": true,
+ "description": "Moves the marker away from the data point in the direction of `angle` (in px). This can be useful for example if you have another marker at this location and you want to point an arrowhead marker at it.",
+ "dflt": 0,
+ "editType": "plot",
+ "min": 0,
+ "valType": "number"
+ },
+ "standoffsrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `standoff`.",
+ "editType": "none",
+ "valType": "string"
+ },
"symbol": {
"arrayOk": true,
"description": "Sets the marker symbol type. Adding 100 is equivalent to appending *-open* to a symbol name. Adding 200 is equivalent to appending *-dot* to a symbol name. Adding 300 is equivalent to appending *-open-dot* or *dot-open* to a symbol name.",
@@ -59301,7 +59648,19 @@
"arrow-bar-right",
152,
"152",
- "arrow-bar-right-open"
+ "arrow-bar-right-open",
+ 53,
+ "53",
+ "arrow",
+ 153,
+ "153",
+ "arrow-open",
+ 54,
+ "54",
+ "arrow-wide",
+ 154,
+ "154",
+ "arrow-wide-open"
]
},
"symbolsrc": {
@@ -59871,6 +60230,19 @@
"valType": "number"
},
"line": {
+ "backoff": {
+ "arrayOk": true,
+ "description": "Sets the line back off from the end point of the nth line segment (in px). This option is useful e.g. to avoid overlap with arrowhead markers. With *auto* the lines would trim before markers if `marker.angleref` is set to *previous*.",
+ "dflt": "auto",
+ "editType": "plot",
+ "min": 0,
+ "valType": "number"
+ },
+ "backoffsrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `backoff`.",
+ "editType": "none",
+ "valType": "string"
+ },
"color": {
"description": "Sets the line color.",
"editType": "style",
@@ -59919,6 +60291,28 @@
}
},
"marker": {
+ "angle": {
+ "arrayOk": true,
+ "description": "Sets the marker angle in respect to `angleref`.",
+ "dflt": 0,
+ "editType": "plot",
+ "valType": "angle"
+ },
+ "angleref": {
+ "description": "Sets the reference for marker angle. With *previous*, angle 0 points along the line from the previous point to this one. With *up*, angle 0 points toward the top of the screen.",
+ "dflt": "up",
+ "editType": "plot",
+ "valType": "enumerated",
+ "values": [
+ "previous",
+ "up"
+ ]
+ },
+ "anglesrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `angle`.",
+ "editType": "none",
+ "valType": "string"
+ },
"autocolorscale": {
"description": "Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. Has an effect only if in `marker.color` is set to a numerical array. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed.",
"dflt": true,
@@ -60662,6 +61056,19 @@
"editType": "none",
"valType": "string"
},
+ "standoff": {
+ "arrayOk": true,
+ "description": "Moves the marker away from the data point in the direction of `angle` (in px). This can be useful for example if you have another marker at this location and you want to point an arrowhead marker at it.",
+ "dflt": 0,
+ "editType": "plot",
+ "min": 0,
+ "valType": "number"
+ },
+ "standoffsrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `standoff`.",
+ "editType": "none",
+ "valType": "string"
+ },
"symbol": {
"arrayOk": true,
"description": "Sets the marker symbol type. Adding 100 is equivalent to appending *-open* to a symbol name. Adding 200 is equivalent to appending *-dot* to a symbol name. Adding 300 is equivalent to appending *-open-dot* or *dot-open* to a symbol name.",
@@ -61142,7 +61549,19 @@
"arrow-bar-right",
152,
"152",
- "arrow-bar-right-open"
+ "arrow-bar-right-open",
+ 53,
+ "53",
+ "arrow",
+ 153,
+ "153",
+ "arrow-open",
+ 54,
+ "54",
+ "arrow-wide",
+ 154,
+ "154",
+ "arrow-wide-open"
]
},
"symbolsrc": {
@@ -61714,6 +62133,18 @@
"valType": "number"
},
"marker": {
+ "angle": {
+ "arrayOk": true,
+ "description": "Sets the marker angle in respect to `angleref`.",
+ "dflt": 0,
+ "editType": "plot",
+ "valType": "angle"
+ },
+ "anglesrc": {
+ "description": "Sets the source reference on Chart Studio Cloud for `angle`.",
+ "editType": "none",
+ "valType": "string"
+ },
"autocolorscale": {
"description": "Determines whether the colorscale is a default palette (`autocolorscale: true`) or the palette determined by `marker.colorscale`. Has an effect only if in `marker.color` is set to a numerical array. In case `colorscale` is unspecified or `autocolorscale` is true, the default palette will be chosen according to whether numbers in the `color` array are all positive, all negative or mixed.",
"dflt": true,
@@ -62897,7 +63328,19 @@
"arrow-bar-right",
152,
"152",
- "arrow-bar-right-open"
+ "arrow-bar-right-open",
+ 53,
+ "53",
+ "arrow",
+ 153,
+ "153",
+ "arrow-open",
+ 54,
+ "54",
+ "arrow-wide",
+ 154,
+ "154",
+ "arrow-wide-open"
]
},
"symbolsrc": {
@@ -69114,6 +69557,13 @@
}
},
"marker": {
+ "angle": {
+ "arrayOk": false,
+ "description": "Sets the marker angle in respect to `angleref`.",
+ "dflt": 0,
+ "editType": "calc",
+ "valType": "angle"
+ },
"color": {
"arrayOk": false,
"description": "Sets the marker color. It accepts either a specific color or an array of numbers that are mapped to the colorscale relative to the max and min values of the array or relative to `marker.cmin` and `marker.cmax` if set.",
@@ -69656,7 +70106,19 @@
"arrow-bar-right",
152,
"152",
- "arrow-bar-right-open"
+ "arrow-bar-right-open",
+ 53,
+ "53",
+ "arrow",
+ 153,
+ "153",
+ "arrow-open",
+ 54,
+ "54",
+ "arrow-wide",
+ 154,
+ "154",
+ "arrow-wide-open"
]
}
},