Skip to content

Commit 974740b

Browse files
committed
improve zoom dragbox behavior
- add ways to cancel zoom (that depend on 1-sided/2-sided mode, and if mouse move crossed the origin) - add mouse down corner to more it more obvious to zoom can be canceled.
1 parent c2da23e commit 974740b

File tree

2 files changed

+48
-39
lines changed

2 files changed

+48
-39
lines changed

src/plots/polar/constants.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ module.exports = {
3333
cornerLen: 25,
3434
cornerHalfWidth: 2,
3535

36-
MINDRAG: 8,
37-
MINZOOM: 20
36+
// smallest radial distance [px] allowed for a zoombox
37+
MINZOOM: 20,
38+
// distance [px] off (r=0) or (r=radius) where we transition
39+
// from single-sided to two-sided radial zoom
40+
OFFEDGE: 20
3841
};

src/plots/polar/polar.js

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ proto.updateMainDrag = function(fullLayout, polarLayout) {
547547
var layers = _this.layers;
548548
var zoomlayer = fullLayout._zoomlayer;
549549
var MINZOOM = constants.MINZOOM;
550+
var OFFEDGE = constants.OFFEDGE;
550551
var radius = _this.radius;
551552
var cx = _this.cx;
552553
var cy = _this.cy;
@@ -576,9 +577,6 @@ proto.updateMainDrag = function(fullLayout, polarLayout) {
576577
var x0, y0;
577578
// radial distance from circle center at drag start (0), move (1)
578579
var r0, r1;
579-
// first (r1 - r0) dist greater than MINZOOM,
580-
// determines whether 'small' zoomboxes get filled from center or outer edge
581-
var drdir;
582580
// zoombox persistent quantities
583581
var path0, dimmed, lum;
584582
// zoombox, corners elements
@@ -598,10 +596,29 @@ proto.updateMainDrag = function(fullLayout, polarLayout) {
598596
return [r * Math.cos(a), r * Math.sin(-a)];
599597
}
600598

599+
function pathCorner(r, a) {
600+
var clen = constants.cornerLen;
601+
var chw = constants.cornerHalfWidth;
602+
603+
if(r === 0) return pathSectorClosed(2 * chw, sector);
604+
605+
var da = clen / r / 2;
606+
var am = a - da;
607+
var ap = a + da;
608+
var rb = Math.max(0, Math.min(r, radius));
609+
var rm = rb - chw;
610+
var rp = rb + chw;
611+
612+
return 'M' + ra2xy(rm, am) +
613+
'A' + [rm, rm] + ' 0,0,0 ' + ra2xy(rm, ap) +
614+
'L' + ra2xy(rp, ap) +
615+
'A' + [rp, rp] + ' 0,0,1 ' + ra2xy(rp, am) +
616+
'Z';
617+
}
618+
601619
function zoomPrep() {
602620
r0 = null;
603621
r1 = null;
604-
drdir = null;
605622
path0 = pathSectorClosed(radius, sector);
606623
dimmed = false;
607624

@@ -618,45 +635,34 @@ proto.updateMainDrag = function(fullLayout, polarLayout) {
618635
var x1 = x0 + dx;
619636
var y1 = y0 + dy;
620637
var rr0 = xy2r(x0, y0);
621-
var rr1 = xy2r(x1, y1);
622-
623-
var drr = rr1 - rr0;
624-
if(!drdir) drdir = drr;
625-
626-
if(Math.abs(drr) < MINZOOM) {
627-
if(drdir > 0) rr0 = 0;
628-
else if(drdir < 0) rr0 = radius;
629-
else return;
630-
}
631-
632-
var crossedOrigin = (
633-
sign(x0 - cxx) * sign(x1 - cxx) === -1 &&
634-
sign(cyy - y0) * sign(cyy - y1) === -1
635-
);
636-
if(crossedOrigin) rr0 = 0;
638+
var rr1 = Math.min(xy2r(x1, y1), radius);
639+
var a0 = xy2a(x0, y0);
640+
var a1 = xy2a(x1, y1);
637641

638-
r0 = Math.min(rr0, rr1);
639-
r1 = Math.min(Math.max(rr0, rr1), radius);
642+
// starting or ending drag near center (outer edge),
643+
// clamps radial distance at origin (at r=radius)
644+
if(rr0 < OFFEDGE) rr0 = 0;
645+
else if((radius - rr0) < OFFEDGE) rr0 = radius;
646+
else if(rr1 < OFFEDGE) rr1 = 0;
647+
else if((radius - rr1) < OFFEDGE) rr1 = radius;
640648

641649
var path1;
642650
var cpath;
643651

644-
if(r1 - r0 > MINZOOM || crossedOrigin) {
645-
path1 = path0 + pathSectorClosed(r1, sector) + pathSectorClosed(r0, sector);
652+
if(Math.abs(rr1 - rr0) > MINZOOM) {
653+
// make sure r0 < r1,
654+
// to get correct fill pattern in path1 below
655+
if(rr0 < rr1) {
656+
r0 = rr0;
657+
r1 = rr1;
658+
} else {
659+
r0 = rr1;
660+
r1 = rr0;
661+
a1 = [a0, a0 = a1][0]; // swap a0 and a1
662+
}
646663

647-
var a = xy2a(x1, y1);
648-
var da = clen / rr1 / 2;
649-
var am = a - da;
650-
var ap = a + da;
651-
var rb = Math.min(rr1, radius);
652-
var rm = rb - chw;
653-
var rp = rb + chw;
654-
655-
cpath = 'M' + ra2xy(rm, am) +
656-
'A' + [rm, rm] + ' 0,0,0 ' + ra2xy(rm, ap) +
657-
'L' + ra2xy(rp, ap) +
658-
'A' + [rp, rp] + ' 0,0,1 ' + ra2xy(rp, am) +
659-
'Z';
664+
path1 = path0 + pathSectorClosed(r1, sector) + pathSectorClosed(r0, sector);
665+
cpath = pathCorner(r0, a0) + pathCorner(r1, a1);
660666
} else {
661667
r0 = null;
662668
r1 = null;

0 commit comments

Comments
 (0)