Skip to content

Commit 6658428

Browse files
authored
Merge pull request #2038 from VisActor/feat/support-minSliderSize-ins-scrollbar
Feat/support min slider size ins scrollbar
2 parents 92895fc + e97144c commit 6658428

4 files changed

Lines changed: 74 additions & 35 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"changes": [
3+
{
4+
"comment": "feat: support minSliderSize in scrollBar\n\n",
5+
"type": "none",
6+
"packageName": "@visactor/vrender-components"
7+
}
8+
],
9+
"packageName": "@visactor/vrender-components",
10+
"email": "lixuef1313@163.com"
11+
}

packages/vrender-components/__tests__/browser/examples/scrollbar.ts

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ export function run() {
1313
height: 12,
1414
padding: [2, 0],
1515
realTime: false,
16+
minSliderSize: 20,
1617
railStyle: {
1718
fill: 'rgba(0, 0, 0, .1)'
1819
},
19-
range: [0, 0.05],
20+
range: [0, 0.0001],
2021
delayTime: 0
2122
// scrollRange: [0.4, 0.8]
2223
});
@@ -30,6 +31,7 @@ export function run() {
3031
height: 500,
3132
padding: [0, 2],
3233
delayTime: 0,
34+
// minSliderSize: 20,
3335
railStyle: {
3436
fill: 'rgba(0, 0, 0, .1)'
3537
//
@@ -49,7 +51,7 @@ export function run() {
4951
});
5052

5153
for (let j = 0; j < 10; j++) {
52-
for (let i = 0; i < 10; i++) {
54+
for (let i = 0; i < 1000; i++) {
5355
let fill = 'green';
5456
if (i > 6) {
5557
fill = 'orange';
@@ -73,32 +75,32 @@ export function run() {
7375
}
7476
}
7577

76-
const stage = render([group], 'main');
78+
const stage = render([group, hScrollBar, vScrollBar], 'main');
7779
window.stage = stage;
78-
hScrollBar.addEventListener('mouseenter', e => {
79-
console.log('abc');
80-
hScrollBar.setAttributes({ visible: true });
81-
hScrollBar.showAll();
82-
});
83-
hScrollBar.addEventListener('mouseleave', e => {
84-
console.log('def');
85-
hScrollBar.setAttributes({ visibleAll: false });
86-
hScrollBar.hideAll();
87-
});
80+
// hScrollBar.addEventListener('mouseenter', e => {
81+
// console.log('abc');
82+
// hScrollBar.setAttributes({ visible: true });
83+
// hScrollBar.showAll();
84+
// });
85+
// hScrollBar.addEventListener('mouseleave', e => {
86+
// console.log('def');
87+
// hScrollBar.setAttributes({ visibleAll: false });
88+
// hScrollBar.hideAll();
89+
// });
8890

89-
hScrollBar.addEventListener('scrollDown', e => {
90-
console.log('hScrollBar', e.detail);
91-
});
91+
// hScrollBar.addEventListener('scrollDown', e => {
92+
// console.log('hScrollBar', e.detail);
93+
// });
9294

93-
vScrollBar.addEventListener('scrollDown', e => {
94-
console.log('vScrollBar', e.detail);
95-
});
95+
// vScrollBar.addEventListener('scrollDown', e => {
96+
// console.log('vScrollBar', e.detail);
97+
// });
9698

97-
hScrollBar.addEventListener('scroll', e => {
98-
console.log('hScrollBar', e.detail.value);
99-
});
99+
// hScrollBar.addEventListener('scroll', e => {
100+
// console.log('hScrollBar', e.detail.value);
101+
// });
100102

101-
vScrollBar.addEventListener('scroll', e => {
102-
console.log('vScrollBar', e.detail.value);
103-
});
103+
// vScrollBar.addEventListener('scroll', e => {
104+
// console.log('vScrollBar', e.detail.value);
105+
// });
104106
}

packages/vrender-components/src/scrollbar/scrollbar.ts

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export class ScrollBar extends AbstractComponent<Required<ScrollBarAttributes>>
3636
direction: 'horizontal',
3737
round: true,
3838
sliderSize: 20,
39+
minSliderSize: 0,
3940
sliderStyle: {
4041
fill: 'rgba(0, 0, 0, .5)'
4142
},
@@ -267,15 +268,23 @@ export class ScrollBar extends AbstractComponent<Required<ScrollBarAttributes>>
267268
return 0;
268269
}
269270

270-
// 计算滑块在轨道的位置
271+
/**
272+
* 计算滑块在轨道的位置(像素),应用最小展示尺寸但不改变 range 语义
273+
*/
271274
private _getSliderPos(range: [number, number]) {
272-
const { direction } = this.attribute as ScrollBarAttributes;
275+
const { direction, minSliderSize = 0 } = this.attribute as ScrollBarAttributes;
273276
const { width, height, x1, y1 } = this.getSliderRenderBounds();
274-
275-
if (direction === 'horizontal') {
276-
return [width * range[0] + x1, width * range[1] + x1];
277-
}
278-
return [height * range[0] + y1, height * range[1] + y1];
277+
const track = direction === 'horizontal' ? width : height;
278+
const origin = direction === 'horizontal' ? x1 : y1;
279+
const start = clamp(range[0], 0, 1);
280+
const end = clamp(range[1], 0, 1);
281+
const ratio = clamp(end - start, 0, 1);
282+
const L = Math.max(ratio * track, minSliderSize);
283+
const T = Math.max(track - L, 0);
284+
const denom = Math.max(1 - ratio, 1e-12);
285+
const pStart = origin + (start / denom) * T;
286+
const pEnd = pStart + L;
287+
return [pStart, pEnd];
279288
}
280289

281290
private _getScrollRange() {
@@ -349,24 +358,37 @@ export class ScrollBar extends AbstractComponent<Required<ScrollBarAttributes>>
349358
});
350359
};
351360

361+
/**
362+
* 将拖拽像素位移映射为逻辑 range 增量,保证最小尺寸下仍覆盖 [0,1]
363+
*/
352364
private _computeScrollValue = (e: any) => {
353365
const { direction } = this.attribute as ScrollBarAttributes;
354366
const { x, y } = this.stage.eventPointTransform(e);
355367

356-
let currentScrollValue;
368+
let currentScrollValue = 0;
357369
let currentPos;
358370
let delta = 0;
359371

360372
const { width, height } = this.getSliderRenderBounds();
373+
const track = direction === 'vertical' ? height : width;
374+
const travel = Math.max(track - this._sliderSize, 0);
375+
const { range } = this.attribute as ScrollBarAttributes;
376+
const ratio = clamp(range[1] - range[0], 0, 1);
377+
361378
if (direction === 'vertical') {
362379
currentPos = y;
363380
delta = currentPos - this._prePos;
364-
currentScrollValue = delta / height;
365381
} else {
366382
currentPos = x;
367383
delta = currentPos - this._prePos;
368-
currentScrollValue = delta / width;
369384
}
385+
386+
if (travel > 0 && ratio < 1) {
387+
currentScrollValue = (delta / travel) * (1 - ratio);
388+
} else {
389+
currentScrollValue = 0;
390+
}
391+
370392
return [currentPos, currentScrollValue];
371393
};
372394

packages/vrender-components/src/scrollbar/type.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ export interface ScrollBarAttributes extends IGroupGraphicAttribute {
2727
* 滚动条内边距,影响滑轨的实际可用空间 [top, right, bottom, left]
2828
*/
2929
padding?: Padding;
30+
/**
31+
* 滑块最小展示尺寸,单位像素。仅影响视觉大小,不改变 range 表示的内容比例。
32+
*/
33+
minSliderSize?: number;
3034
/** 滑块当前的可视范围,数值为 0 - 1 */
3135
range: [number, number];
3236
/**

0 commit comments

Comments
 (0)