Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Cartesian dropline support #1461

Merged
merged 30 commits into from
Apr 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d9fab15
Cartesian dropline support
rpaskowitz Mar 10, 2017
5d39b53
Removed chart config for showDroplines
rpaskowitz Mar 11, 2017
be47533
Add spikecolor, spikethickness, spikedash and spikemode
rpaskowitz Apr 7, 2017
17d815c
Add cartesian spikeline modebar support
rpaskowitz Apr 7, 2017
162068e
Merge branch 'master' into dropline
rpaskowitz Apr 7, 2017
762b54a
Move dashStyle to Drawing
rpaskowitz Apr 7, 2017
d680bd4
Name back to showspikes
rpaskowitz Apr 7, 2017
2433d4c
Lint, test and implementation fixes
rpaskowitz Apr 7, 2017
75da2fe
add spikeline icon
etpinard Apr 7, 2017
7953488
Fix cartesian check and fine-tune marker placement
rpaskowitz Apr 7, 2017
55b17b2
Merge branch 'master' into dropline
etpinard Apr 10, 2017
b9f6ab1
Refactor dropline to spikeline
rpaskowitz Apr 10, 2017
7fe4363
Merge branch 'dropline' of github.com:rpaskowitz/plotly.js into dropline
rpaskowitz Apr 10, 2017
34a1562
Switch from getBoundingClientRect to offsetLeft and offsetTop.
rpaskowitz Apr 10, 2017
8c7ac76
Move spike setup from axis to layout.
rpaskowitz Apr 10, 2017
6e243de
Fix marker positioning and across rendering for top-side x-axes.
rpaskowitz Apr 11, 2017
c036bf7
Merge branch 'master' into dropline
alexcjohnson Apr 13, 2017
08371c2
short-circuit redraw for spike attribute relayouts
alexcjohnson Apr 14, 2017
69dc781
fix manual-hover logic for event emitting
alexcjohnson Apr 14, 2017
37b77fe
don't make spike markers crisp
alexcjohnson Apr 14, 2017
710d2d6
alter logic for where spikes start and end
alexcjohnson Apr 14, 2017
e509fa7
lint
alexcjohnson Apr 14, 2017
75121d2
:hocho: spikemode: 'none'
alexcjohnson Apr 17, 2017
bd11567
make drawing/attributes.dash - and clean up some dashes that don't fi…
alexcjohnson Apr 17, 2017
3a9aa58
short-circuit spike properties when spikes are off
alexcjohnson Apr 17, 2017
052417b
test hover event response to manual and "real" events
alexcjohnson Apr 17, 2017
a3a0a4f
:hocho: fit
alexcjohnson Apr 17, 2017
f7b467e
fix scattermapbox defaults for omitted options
alexcjohnson Apr 18, 2017
7aa4359
lint
alexcjohnson Apr 18, 2017
5925049
:hocho: :hocho:
alexcjohnson Apr 18, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions build/ploticon.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,11 @@ module.exports = {
'path': 'm0 850l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m285 0l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m-857-286l0-143 143 0 0 143-143 0z m857 0l0-143 143 0 0 143-143 0z m-857-285l0-143 143 0 0 143-143 0z m857 0l0-143 143 0 0 143-143 0z m-857-286l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z m285 0l0-143 143 0 0 143-143 0z m286 0l0-143 143 0 0 143-143 0z',
'ascent': 850,
'descent': -150
},
'spikeline': {
'width': 1000,
'path': 'M512 409c0-57-46-104-103-104-57 0-104 47-104 104 0 57 47 103 104 103 57 0 103-46 103-103z m-327-39l92 0 0 92-92 0z m-185 0l92 0 0 92-92 0z m370-186l92 0 0 93-92 0z m0-184l92 0 0 92-92 0z',
'ascent': 850,
'descent': -150
}
};
2 changes: 2 additions & 0 deletions src/components/dragelement/unhover.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ unhover.raw = function unhoverRaw(gd, evt) {
}

fullLayout._hoverlayer.selectAll('g').remove();
fullLayout._hoverlayer.selectAll('line').remove();
fullLayout._hoverlayer.selectAll('circle').remove();
gd._hoverdata = undefined;

if(evt.target && oldhoverdata) {
Expand Down
26 changes: 26 additions & 0 deletions src/components/drawing/attributes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Copyright 2012-2017, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/


'use strict';

exports.dash = {
valType: 'string',
// string type usually doesn't take values... this one should really be
// a special type or at least a special coercion function, from the GUI
// you only get these values but elsewhere the user can supply a list of
// dash lengths in px, and it will be honored
values: ['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot'],
dflt: 'solid',
role: 'style',
description: [
'Sets the dash style of lines. Set to a dash type string',
'(*solid*, *dot*, *dash*, *longdash*, *dashdot*, or *longdashdot*)',
'or a dash length list in px (eg *5px,10px,2px,2px*).'
].join(' ')
};
16 changes: 12 additions & 4 deletions src/components/drawing/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ drawing.lineGroupStyle = function(s, lw, lc, ld) {

drawing.dashLine = function(s, dash, lineWidth) {
lineWidth = +lineWidth || 0;

dash = drawing.dashStyle(dash, lineWidth);

s.style({
'stroke-dasharray': dash,
'stroke-width': lineWidth + 'px'
});
};

drawing.dashStyle = function(dash, lineWidth) {
lineWidth = +lineWidth || 1;
var dlw = Math.max(lineWidth, 3);

if(dash === 'solid') dash = '';
Expand All @@ -127,10 +138,7 @@ drawing.dashLine = function(s, dash, lineWidth) {
}
// otherwise user wrote the dasharray themselves - leave it be

s.style({
'stroke-dasharray': dash,
'stroke-width': lineWidth + 'px'
});
return dash;
};

drawing.fillGroupStyle = function(s) {
Expand Down
66 changes: 61 additions & 5 deletions src/components/modebar/buttons.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,17 +177,20 @@ function handleCartesian(gd, ev) {
astr = button.getAttribute('data-attr'),
val = button.getAttribute('data-val') || true,
fullLayout = gd._fullLayout,
aobj = {};
aobj = {},
axList = Axes.list(gd, null, true),
ax,
allEnabled = 'on',
i;

if(astr === 'zoom') {
var mag = (val === 'in') ? 0.5 : 2,
r0 = (1 + mag) / 2,
r1 = (1 - mag) / 2,
axList = Axes.list(gd, null, true);
r1 = (1 - mag) / 2;

var ax, axName;
var axName;

for(var i = 0; i < axList.length; i++) {
for(i = 0; i < axList.length; i++) {
ax = axList[i];

if(!ax.fixedrange) {
Expand All @@ -202,6 +205,12 @@ function handleCartesian(gd, ev) {
aobj[axName + '.range[0]'] = rangeInitial[0];
aobj[axName + '.range[1]'] = rangeInitial[1];
}
if(ax._showSpikeInitial !== undefined) {
aobj[axName + '.showspikes'] = ax._showSpikeInitial;
if(allEnabled === 'on' && !ax._showSpikeInitial) {
allEnabled = 'off';
}
}
}
else {
var rangeNow = [
Expand All @@ -219,12 +228,24 @@ function handleCartesian(gd, ev) {
}
}
}
fullLayout._cartesianSpikesEnabled = allEnabled;
}
else {
// if ALL traces have orientation 'h', 'hovermode': 'x' otherwise: 'y'
if(astr === 'hovermode' && (val === 'x' || val === 'y')) {
val = fullLayout._isHoriz ? 'y' : 'x';
button.setAttribute('data-val', val);
if(val !== 'closest') {
fullLayout._cartesianSpikesEnabled = 'off';
}
} else if(astr === 'hovermode' && val === 'closest') {
for(i = 0; i < axList.length; i++) {
ax = axList[i];
if(allEnabled === 'on' && !ax.showspikes) {
allEnabled = 'off';
}
}
fullLayout._cartesianSpikesEnabled = allEnabled;
}

aobj[astr] = val;
Expand Down Expand Up @@ -518,3 +539,38 @@ modeBarButtons.resetViews = {
// geo subplots.
}
};

modeBarButtons.toggleSpikelines = {
name: 'toggleSpikelines',
title: 'Toggle Spike Lines',
icon: Icons.spikeline,
attr: '_cartesianSpikesEnabled',
val: 'on',
click: function(gd) {
var fullLayout = gd._fullLayout;

fullLayout._cartesianSpikesEnabled = fullLayout.hovermode === 'closest' ?
(fullLayout._cartesianSpikesEnabled === 'on' ? 'off' : 'on') : 'on';

var aobj = setSpikelineVisibility(gd);

aobj.hovermode = 'closest';
Plotly.relayout(gd, aobj);
}
};

function setSpikelineVisibility(gd) {
var fullLayout = gd._fullLayout,
axList = Axes.list(gd, null, true),
ax,
axName,
aobj = {};

for(var i = 0; i < axList.length; i++) {
ax = axList[i];
axName = ax._name;
aobj[axName + '.showspikes'] = fullLayout._cartesianSpikesEnabled === 'on' ? true : false;
}

return aobj;
}
2 changes: 1 addition & 1 deletion src/components/modebar/manage.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function getButtonGroups(gd, buttonsToRemove, buttonsToAdd) {
addGroup(['hoverClosestGl2d']);
}
else if(hasCartesian) {
addGroup(['hoverClosestCartesian', 'hoverCompareCartesian']);
addGroup(['toggleSpikelines', 'hoverClosestCartesian', 'hoverCompareCartesian']);
Copy link
Contributor

Choose a reason for hiding this comment

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

peek 2017-04-07 17-09

Personally, I think I'd prefer placing this new icon first from the right. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My reasoning was to put it beside hovermode: closest because of how spikeline functionality is tied to that mode. (Needed for any spikelines, and using the toggle will force you into that mode)

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point. I'm ok leaving it there.

}
else if(hasPie) {
addGroup(['hoverClosestPie']);
Expand Down
10 changes: 7 additions & 3 deletions src/components/modebar/modebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ proto.createButton = function(config) {
button.setAttribute('data-toggle', config.toggle || false);
if(config.toggle) d3.select(button).classed('active', true);

button.appendChild(this.createIcon(config.icon || Icons.question));
button.appendChild(this.createIcon(config.icon || Icons.question, config.name));
button.setAttribute('data-gravity', config.gravity || 'n');

return button;
Expand All @@ -162,7 +162,7 @@ proto.createButton = function(config) {
* @Param {string} thisIcon.path
* @Return {HTMLelement}
*/
proto.createIcon = function(thisIcon) {
proto.createIcon = function(thisIcon, name) {
var iconHeight = thisIcon.ascent - thisIcon.descent,
svgNS = 'http://www.w3.org/2000/svg',
icon = document.createElementNS(svgNS, 'svg'),
Expand All @@ -172,8 +172,12 @@ proto.createIcon = function(thisIcon) {
icon.setAttribute('width', (thisIcon.width / iconHeight) + 'em');
icon.setAttribute('viewBox', [0, 0, thisIcon.width, iconHeight].join(' '));

var transform = name === 'toggleSpikelines' ?
Copy link
Contributor

Choose a reason for hiding this comment

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

A little hacky here. Ideally, the icon should have been exported 50% bigger. I opted for this hacky fix because implementing some icon transform setting as proposed #1335 would be really nice.

Copy link
Contributor

@etpinard etpinard Apr 7, 2017

Choose a reason for hiding this comment

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

Hmm. did I break something, the new button doesn't seem to work:

peek 2017-04-07 17-28

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that was me. Grab my latest commit.

'matrix(1.5 0 0 -1.5 0 ' + thisIcon.ascent + ')' :
'matrix(1 0 0 -1 0 ' + thisIcon.ascent + ')';

path.setAttribute('d', thisIcon.path);
path.setAttribute('transform', 'matrix(1 0 0 -1 0 ' + thisIcon.ascent + ')');
path.setAttribute('transform', transform);
icon.appendChild(path);

return icon;
Expand Down
7 changes: 3 additions & 4 deletions src/components/shapes/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@
'use strict';

var annAttrs = require('../annotations/attributes');
var scatterAttrs = require('../../traces/scatter/attributes');
var scatterLineAttrs = require('../../traces/scatter/attributes').line;
var dash = require('../drawing/attributes').dash;
var extendFlat = require('../../lib/extend').extendFlat;

var scatterLineAttrs = scatterAttrs.line;

module.exports = {
_isLinkedToArray: 'shape',

Expand Down Expand Up @@ -151,7 +150,7 @@ module.exports = {
line: {
color: scatterLineAttrs.color,
width: scatterLineAttrs.width,
dash: scatterLineAttrs.dash,
dash: dash,
role: 'info'
},
fillcolor: {
Expand Down
3 changes: 2 additions & 1 deletion src/fonts/ploticon/ploticon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 10 additions & 5 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ Plotly.plot = function(gd, data, layout, config) {
makePlotFramework(gd);
}

// save initial show spikes once per graph
if(graphWasEmpty) Plotly.Axes.saveShowSpikeInitial(gd);

// prepare the data and find the autorange

// generate calcdata, if we need to
Expand Down Expand Up @@ -2121,14 +2124,16 @@ function _relayout(gd, aobj) {
flags.doticks = flags.dolayoutstyle = true;
}
/*
* hovermode and dragmode don't need any redrawing, since they just
* affect reaction to user input, everything else, assume full replot.
* hovermode, dragmode, and spikes don't need any redrawing, since they just
* affect reaction to user input. Everything else, assume full replot.
* height, width, autosize get dealt with below. Except for the case of
* of subplots - scenes - which require scene.updateFx to be called.
*/
else if(['hovermode', 'dragmode'].indexOf(ai) !== -1) flags.domodebar = true;
else if(['hovermode', 'dragmode', 'height',
'width', 'autosize'].indexOf(ai) === -1) {
else if(['hovermode', 'dragmode'].indexOf(ai) !== -1 ||
ai.indexOf('spike') !== -1) {
flags.domodebar = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

🐎

}
else if(['height', 'width', 'autosize'].indexOf(ai) === -1) {
flags.doplot = true;
}

Expand Down
Loading