Skip to content

Commit 113b361

Browse files
authored
Merge pull request #2426 from plotly/legend-scroll-fix
Legend scroll fix
2 parents f8e7ee4 + f2d8cfd commit 113b361

File tree

4 files changed

+225
-75
lines changed

4 files changed

+225
-75
lines changed

Diff for: src/components/dragelement/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ dragElement.init = function init(options) {
135135
startY = offset[1];
136136
initialTarget = e.target;
137137
initialEvent = e;
138-
rightClick = (e.buttons && e.buttons === 2) || e.ctrlKey;
138+
rightClick = e.buttons === 2 || e.ctrlKey;
139139

140140
newMouseDownTime = (new Date()).getTime();
141141
if(newMouseDownTime - gd._mouseDownTime < DBLCLICKDELAY) {

Diff for: src/components/legend/constants.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
'use strict';
1010

1111
module.exports = {
12-
scrollBarWidth: 4,
13-
scrollBarHeight: 20,
12+
scrollBarWidth: 6,
13+
scrollBarMinHeight: 20,
1414
scrollBarColor: '#808BA4',
1515
scrollBarMargin: 4
1616
};

Diff for: src/components/legend/draw.js

+54-49
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@ module.exports = function draw(gd) {
7878
'shape-rendering': 'crispEdges'
7979
});
8080

81-
bg.call(Color.stroke, opts.bordercolor);
82-
bg.call(Color.fill, opts.bgcolor);
83-
bg.style('stroke-width', opts.borderwidth + 'px');
81+
bg.call(Color.stroke, opts.bordercolor)
82+
.call(Color.fill, opts.bgcolor)
83+
.style('stroke-width', opts.borderwidth + 'px');
8484

8585
var scrollBox = legend.selectAll('g.scrollbox')
8686
.data([0]);
@@ -94,10 +94,10 @@ module.exports = function draw(gd) {
9494
scrollBar.enter().append('rect')
9595
.attr({
9696
'class': 'scrollbar',
97-
'rx': 20,
98-
'ry': 2,
99-
'width': 0,
100-
'height': 0
97+
rx: 20,
98+
ry: 3,
99+
width: 0,
100+
height: 0
101101
})
102102
.call(Color.fill, '#808BA4');
103103

@@ -207,12 +207,9 @@ module.exports = function draw(gd) {
207207
// legend, background and border, scroll box and scroll bar
208208
Drawing.setTranslate(legend, lx, ly);
209209

210-
var scrollBarYMax = legendHeight -
211-
constants.scrollBarHeight -
212-
2 * constants.scrollBarMargin,
213-
scrollBoxYMax = opts._height - legendHeight,
214-
scrollBarY,
215-
scrollBoxY;
210+
// to be safe, remove previous listeners
211+
scrollBar.on('.drag', null);
212+
legend.on('wheel', null);
216213

217214
if(opts._height <= legendHeight || gd._context.staticPlot) {
218215
// if scrollbar should not be shown.
@@ -232,11 +229,21 @@ module.exports = function draw(gd) {
232229
y: opts.borderwidth
233230
});
234231

235-
scrollBox.call(Drawing.setClipUrl, clipId);
232+
Drawing.setClipUrl(scrollBox, clipId);
233+
234+
Drawing.setRect(scrollBar, 0, 0, 0, 0);
235+
delete opts._scrollY;
236236
}
237237
else {
238-
scrollBarY = constants.scrollBarMargin,
239-
scrollBoxY = scrollBox.attr('data-scroll') || 0;
238+
var scrollBarHeight = Math.max(constants.scrollBarMinHeight,
239+
legendHeight * legendHeight / opts._height);
240+
var scrollBarYMax = legendHeight -
241+
scrollBarHeight -
242+
2 * constants.scrollBarMargin;
243+
var scrollBoxYMax = opts._height - legendHeight;
244+
var scrollRatio = scrollBarYMax / scrollBoxYMax;
245+
246+
var scrollBoxY = Math.min(opts._scrollY || 0, scrollBoxYMax);
240247

241248
// increase the background and clip-path width
242249
// by the scrollbar width and margin
@@ -257,60 +264,58 @@ module.exports = function draw(gd) {
257264
constants.scrollBarMargin,
258265
height: legendHeight - 2 * opts.borderwidth,
259266
x: opts.borderwidth,
260-
y: opts.borderwidth - scrollBoxY
267+
y: opts.borderwidth + scrollBoxY
261268
});
262269

263-
scrollBox.call(Drawing.setClipUrl, clipId);
270+
Drawing.setClipUrl(scrollBox, clipId);
264271

265-
if(firstRender) scrollHandler(scrollBarY, scrollBoxY);
272+
scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio);
266273

267-
legend.on('wheel', null); // to be safe, remove previous listeners
268274
legend.on('wheel', function() {
269275
scrollBoxY = Lib.constrain(
270-
scrollBox.attr('data-scroll') -
276+
opts._scrollY +
271277
d3.event.deltaY / scrollBarYMax * scrollBoxYMax,
272-
-scrollBoxYMax, 0);
273-
scrollBarY = constants.scrollBarMargin -
274-
scrollBoxY / scrollBoxYMax * scrollBarYMax;
275-
scrollHandler(scrollBarY, scrollBoxY);
276-
if(scrollBoxY !== 0 && scrollBoxY !== -scrollBoxYMax) {
278+
0, scrollBoxYMax);
279+
scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio);
280+
if(scrollBoxY !== 0 && scrollBoxY !== scrollBoxYMax) {
277281
d3.event.preventDefault();
278282
}
279283
});
280284

281-
// to be safe, remove previous listeners
282-
scrollBar.on('.drag', null);
283-
scrollBox.on('.drag', null);
285+
var eventY0, scrollBoxY0;
284286

285-
var drag = d3.behavior.drag().on('drag', function() {
286-
scrollBarY = Lib.constrain(
287-
d3.event.y - constants.scrollBarHeight / 2,
288-
constants.scrollBarMargin,
289-
constants.scrollBarMargin + scrollBarYMax);
290-
scrollBoxY = - (scrollBarY - constants.scrollBarMargin) /
291-
scrollBarYMax * scrollBoxYMax;
292-
scrollHandler(scrollBarY, scrollBoxY);
287+
var drag = d3.behavior.drag()
288+
.on('dragstart', function() {
289+
eventY0 = d3.event.sourceEvent.clientY;
290+
scrollBoxY0 = scrollBoxY;
291+
})
292+
.on('drag', function() {
293+
var e = d3.event.sourceEvent;
294+
if(e.buttons === 2 || e.ctrlKey) return;
295+
296+
scrollBoxY = Lib.constrain(
297+
(e.clientY - eventY0) / scrollRatio + scrollBoxY0,
298+
0, scrollBoxYMax);
299+
scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio);
293300
});
294301

295302
scrollBar.call(drag);
296-
scrollBox.call(drag);
297303
}
298304

299305

300-
function scrollHandler(scrollBarY, scrollBoxY) {
301-
scrollBox
302-
.attr('data-scroll', scrollBoxY)
303-
.call(Drawing.setTranslate, 0, scrollBoxY);
306+
function scrollHandler(scrollBoxY, scrollBarHeight, scrollRatio) {
307+
opts._scrollY = gd._fullLayout.legend._scrollY = scrollBoxY;
308+
Drawing.setTranslate(scrollBox, 0, -scrollBoxY);
304309

305-
scrollBar.call(
306-
Drawing.setRect,
310+
Drawing.setRect(
311+
scrollBar,
307312
legendWidth,
308-
scrollBarY,
313+
constants.scrollBarMargin + scrollBoxY * scrollRatio,
309314
constants.scrollBarWidth,
310-
constants.scrollBarHeight
315+
scrollBarHeight
311316
);
312317
clipPath.select('rect').attr({
313-
y: opts.borderwidth - scrollBoxY
318+
y: opts.borderwidth + scrollBoxY
314319
});
315320
}
316321

@@ -434,7 +439,7 @@ function drawTexts(g, gd) {
434439
return Plotly.restyle(gd, update, traceIndex);
435440
});
436441
} else {
437-
text.call(textLayout);
442+
textLayout(text);
438443
}
439444
}
440445

@@ -664,7 +669,7 @@ function computeLegendDimensions(gd, groups, traces) {
664669
var legendItem = d[0],
665670
bg = d3.select(this).select('.legendtoggle');
666671

667-
bg.call(Drawing.setRect,
672+
Drawing.setRect(bg,
668673
0,
669674
-legendItem.height / 2,
670675
(gd._context.edits.legendText ? 0 : opts._width) + extraWidth,

0 commit comments

Comments
 (0)