当前位置:网站首页>Custom scroll bar
Custom scroll bar
2022-07-24 12:44:00 【Liang wha duck,】
List of articles
Code effect :
See the Pen vYxvXPb by Liang what duck “ ( @liang-duck) on CodePen.Drag the scroll bar
oSpan.onmousedown = function (e) {
e = e || window.event;
// Record when clicking the scroll block , Mouse coordinates and scroll blocks oSpan Of left and top
// Because the scroll block only needs to move up and down , So there is no need to record x coordinate and Rolling block oSpan Of left
const contentTop = oContent.offsetTop;
const spanTop = oSpan.offsetTop;
const downY = e.clientY;
// To prevent a bubble
e.stopPropagation();
document.onmousemove = function (e) {
e = e || window.event;
// Record the coordinates when the mouse moves
const moveY = e.clientY;
// Record the distance the mouse moved
const deferY = moveY - downY;
// Make the scroll block move the same distance
let _y = spanTop + deferY;
// The proportion of distance the content moves relative to the scroll block
let _cy = contentTop - deferY * gap_box;
// Set the range of scroll block movement
if (_y >= gap_scroll) {
oSpan.style.top = gap_scroll + 'px';
oContent.style.top = -gap_content + 'px';
}
else if (_y <= 0) {
oSpan.style.top = 0;
oContent.style.top = 0;
}
else {
oSpan.style.top = _y + 'px';
oContent.style.top = _cy + 'px';
}
};
};
// When the mouse is up , Clear mouse movement events
document.onmouseup = function () {
document.onmousemove = null;
}
Diagram :
The distance of the scroll block : The scroll block does not exceed the top and bottom of the scroll bar ,
That is, the scroll block 0 ≤ top ≤ oScroll.offsetHeight - oSpan.offsetHeight
The scrolling distance of the content box : When the scroll block is dragged to the bottom , The content box is just finished , Therefore, the rolling distance of the content box is proportional to the rolling distance of the rolling block . The height of the content box is dynamic , It is generally customary to use dynamic boxes rather than static boxes .
So the ratio is :
(oContent.offsetHeight - oBox.offsetHeight ) / (oScroll.offsetHeight - oSpan.offsetHeight )
Scroll wheel
mousewheel(oBox, function (e) {
e = e || window.event;
const scrollTop = oSpan.offsetTop;
let val;
const speed = 5; // Set the speed at which the scroll bar moves with the scroll wheel
// When the roller rolls forward , The scroll block moves up
if (e.wheelDetail > 0) {
val = scrollTop - speed;
}else { // When the roller rolls backward , Scroll down
val = scrollTop + speed;
}
compare(val);
}, true);
}
// Set the scroll block to follow the scroll wheel Rolling distance range
function compare(val) {
val = max(0, val); // 0 and val The one with the largest
val = min(gap_scroll, val); // gap_scroll and val The smallest one , gap_scroll Is the difference between the scroll bar and the scroll block
const bili = val / gap_scroll; // Record the scroll block Rolling distance Close ratio up The rolling range of the rolling block
const contentTop = bili * gap_content; // Set the moving distance of the content box to account for Movable range The proportion
oSpan.style.top = val + 'px';
oContent.style.top = -contentTop + 'px';
}
Icon :
Click on the scroll bar , Move the scroll block to the clicked position
Generally, the middle position of the scroll block is moved to the position where the mouse clicks the scroll bar
When clicking on the scroll block , The scroll block does not move . Only click on the scroll bar to move
oScroll.onclick = function (e) {
e = e || window.event;
const that = e.target;
if(that !== this) return ; // Event agent , Judge whether it is scroll Click on
// stay scroll Click on
/*let clickTop = e.clientY - oSpan.offsetHeight / 2;
clickTop = max(0, clickTop); // When span Of top Less than 0 when ,clickTop=0
clickTop = min(gap_scroll, clickTop); // When span Of top Greater than gap_scroll when ,clickTop=gap_scroll
oSpan.style.top = clickTop + 'px';
oContent.style.top = -(oSpan.offsetTop / gap_scroll * gap_content) + 'px';*/
// The above code does not consider a problem :
// What the mouse gets is in the visible area y Location , here box Of left top All are 0, So the running result here is right ,
// Suppose there's a divA Wrapped box This div, And box With A Is the positioning standard , hypothesis left top All for 100, Then the running result is wrong
// This is the code : let clickTop = e.clientY - oSpan.offsetHeight / 2;
// To click on scroll On the same location , So at this time e.clientY It adds 100,
// that clickTop It is no longer the expected value , And more than expected 100
// let val = e.clientY - this.getBoundingClientRect() - oSpan.offsetHeight / 2; // Are not compatible IE
let val = e.pageY - getDoc(this).top - oSpan.offsetHeight / 2;
compare(val);
}
A relative positioning problem
For the above problematic code :
let clickTop = e.clientY - oSpan.offsetHeight / 2;
clickTop = max(0, clickTop); // When span Of top Less than 0 when ,clickTop=0
clickTop = min(gap_scroll, clickTop); // When span Of top Greater than gap_scroll when ,clickTop=gap_scroll
oSpan.style.top = clickTop + 'px';
The idea of the above code :
Click on the scroll bar with the mouse ,
The position in the middle of the scroll block and the position of the mouse click

In this case, it is feasible ,
Because the scroll bar and mouse are relative body Positioning of the
Mouse clientX and clientY and
Scroll block offsetLeft and offsetTop
It's consistent

Suppose the height of the scroll bar is 200px , With body Is the positioning standard ,left=100 top=100
The height of the scroll block is 30px , Or relative to the scroll bar positioning
At this time, when the mouse clicks on the scroll bar ,
Suppose the mouse clicks in the middle of the scroll bar , At this time, the mouse clientY = 200
Follow the idea of the above code ,oSpan.offsetTop = 200 - (oSpan.offsetHeight/2)=185
because oSpan It is positioned relative to the scroll bar , So it will move to the lower position 
So the scrolling block top be equal to Mouse position - Positioning distance 
let val = e.pageY - getDoc(this).top - oSpan.offsetHeight / 2;
It is possible to nest multiple boxes :
That is to say, subtract The positioning distance of each box and :
// Stack the positioning distance between each stage , Know add body
function getDoc(ele) {
const obj = {
top: 0,
left: 0
}
while (ele !== document.body) {
obj.left += ele.offsetLeft;
obj.top += ele.offsetTop;
ele = ele.offsetParent;
}
return obj;
}
边栏推荐
- Force deduction exercise - 26 split array into continuous subsequences
- iSCSI新应用,以及NFS的存储服务分离
- What can breaking through the memory wall bring? See the actual battle of volcano engine intelligent recommendation service to save money and increase efficiency
- Everything about native crash
- The setting float cannot float above the previous Div
- Why does 2.tostring() report an error
- 1.9. 触摸按钮(touch pad)测试
- Vscode solves the problem of terminal Chinese garbled code
- 6-16 vulnerability exploitation -rlogin maximum permission login
- Case summary of SSH service suddenly unable to connect
猜你喜欢
Say no to blackmail virus, it's time to reshape data protection strategy
EfficientFormer:轻量化ViT Backbone

基于Kubernetes v1.24.0的集群搭建(二)

Implementing deep learning framework from zero -- further exploration of the implementation of multilayer bidirectional RNN

Use abp Zero builds a third-party login module (4): wechat applet development

Reserved instances & Savings Plans
![[rust] reference and borrowing, string slice type (& STR) - rust language foundation 12](/img/48/7a1777b735312f29d3a4016a14598c.png)
[rust] reference and borrowing, string slice type (& STR) - rust language foundation 12

手把手教你用 Power BI 实现 4 种可视化图表

Use typeface to set the text font of textview
Efficientformer: lightweight vit backbone
随机推荐
树莓派自建 NAS 云盘之——树莓派搭建网络存储盘
TypeNameExtractor could not be found
try...finally总结
生信识图 之 点图基础
Getting started with SQL join use examples to learn left connection, inner connection and self connection
Implementing deep learning framework from zero -- further exploration of the implementation of multilayer bidirectional RNN
SSH服务突然连接不了案例总结
Static attribute, super()
Basic SQL server operation problems - only when lists are used and identity_ Only when insert is on can the display value be set for the identification column in the table
Error: [synth 8-439] module 'xxx' not found not found error solution
It is difficult for Chinese consumers and industrial chains to leave apple, and iPhone has too much influence
自己实现is_default_constructible
基于Qt的软件框架设计
Shell script case ---2
猿人学第六题
About packaging objects
Nacos deployment
QT based software framework design
leetcode第 302 场周赛复盘
Okaleido tiger NFT即将登录Binance NFT平台