Javascript iOS上的拖放自定义滚动条janky问题

Javascript iOS上的拖放自定义滚动条janky问题,javascript,css,drag-and-drop,scrollbar,Javascript,Css,Drag And Drop,Scrollbar,这是我关于堆栈溢出的第一个问题。我已经开始学习网络开发,并决定从头开始构建公司网站,然后部署到Netlify。我曾几次雄心勃勃地让自己陷入困境,但到目前为止,我已经能够解决问题,除了以下几点: 我在视口的右侧有一个音量控制器(就像在混合板上一样),用作自定义滚动条。它在拖动和滚动页面时都可以工作,从而相应地更改音量控制器的位置和滚动位置。然而,为了让它在移动应用中发挥作用,我得到了这种古怪的行为,这似乎是iOS特有的,在安卓系统上并没有问题。当我点击并拖动它时,它似乎会在touchmove事件触

这是我关于堆栈溢出的第一个问题。我已经开始学习网络开发,并决定从头开始构建公司网站,然后部署到Netlify。我曾几次雄心勃勃地让自己陷入困境,但到目前为止,我已经能够解决问题,除了以下几点:

我在视口的右侧有一个音量控制器(就像在混合板上一样),用作自定义滚动条。它在拖动和滚动页面时都可以工作,从而相应地更改音量控制器的位置和滚动位置。然而,为了让它在移动应用中发挥作用,我得到了这种古怪的行为,这似乎是iOS特有的,在安卓系统上并没有问题。当我点击并拖动它时,它似乎会在touchmove事件触发时跳回到起始位置,导致一些非常难看的跳跃。我尝试过使用preventDefault,添加一个布尔标志来停用mousedown和mousemove事件,以防引起冲突,并尝试添加requestAnimationFrame以提高效率(这似乎不起作用——当单击并拖动音量控制器时,我的帧速率仍然比正常滚动页面时低很多),没有任何效果。我尝试研究iOS如何处理触摸事件,以找出导致这种行为的原因以及如何防止这种行为,但找不到合适的资源

可以找到我一直致力于此的git分支的部署

回购协议可以找到

注意:在iPhone上,音量控制器滚动条仅在横向模式下显示,且仅当vw大于685px时才显示。此外,桌面显示器和iPad Pro等大型平板电脑的布局也有很大不同,并且更依赖于基于滚动的效果

这是适用于音量控制器的javascript;有一个用于鼠标事件的代码块和另一个用于触摸事件的代码块。触摸事件是我主要关心的问题。鼠标事件代码的唯一问题是我上面提到的低帧速率

var enabled = 'yes';
var faderPath = document.getElementById('scrolltrack');
var fader = document.getElementById('scrollthumb');
let touch = false;

//click and drag
fader.addEventListener('mousedown', pickup, false);
function pickup(event) {
    if (touch == false){
        enabled = 'no';
        let startPos = event.clientY;
        let faderStart = fader.offsetTop;
        let bottomEdge = faderPath.offsetHeight - fader.offsetHeight;

        let needRAF = null;
        function moveAt(event) {
            if (needRAF){
                needRAF = null;
                cancelAnimationFrame(setNew);
            }
            needRAF = requestAnimationFrame(setNew);
            function setNew(){
                let dragDist = event.clientY - startPos;
                let newTop = faderStart + dragDist;        
                //restrains fader in track
                if(newTop<0){
                    newTop=0;
                } else if(newTop>bottomEdge){
                    newTop = bottomEdge;
                }

                //sets new position
                fader.style.top = `${newTop}px`;
                //convert position to percentage
                var newTopPer = (newTop / bottomEdge);
                //make page scroll with fader position
                var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
                var scrollPos = newTopPer*height;
                document.documentElement.scrollTop = scrollPos;
            }
        }
        document.addEventListener('mousemove', moveAt, false);
        document.addEventListener('mouseup', dropIt, false);

        function dropIt() {
            document.removeEventListener('mousemove', moveAt, false);
            fader.onmouseup = null;
            enabled = 'yes';
        }
    }
}

fader.addEventListener('touchstart', touchPickup, false);
function touchPickup(event) {
    event.preventDefault();
    enabled = 'no';
    touch = true;
    let startPos = event.targetTouches[0].clientY;
    let faderStart = fader.offsetTop;
    //declare bottomEdge here to prevent recalculating with each drag move
    let bottomEdge = faderPath.offsetHeight - fader.offsetHeight;

    let needRAF = null;
    function moveAt(touchEvent) {
        touchEvent.preventDefault();
        if (needRAF) {
            needRAF = null;
            cancelAnimationFrame(setNew);
        }
        needRAF = requestAnimationFrame(setNew);
        function setNew() {
            let dragDist = touchEvent.targetTouches[0].clientY - startPos; 
            let newTop = faderStart + dragDist;
                
            //restrains fader in track
            if(newTop<0){
                newTop=0;
            } else if(newTop>bottomEdge){
                newTop = bottomEdge;
            }
            fader.style.top = `${newTop}px`;
            //convert position to percentage
            var newTopPer = (newTop / bottomEdge);
            //make page scroll with fader position
            var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
            var scrollPos = newTopPer*height;
            document.documentElement.scrollTop = scrollPos;
        }
        
        
        
    }
    document.addEventListener('touchmove', moveAt, false);
    document.addEventListener('touchend', dropIt, false);
    document.addEventListener('touchcancel', function(e){e.preventDefault()}, false);

    function dropIt() {
        document.removeEventListener('touchmove', moveAt, false);
        fader.ontouchend = null;
        enabled = 'yes';
        touch = false;
    }
}

fader.ondragstart = function() {
    return false;
}

//make fader move with window scrolling
window.addEventListener('scroll', scrollLink, false);
function scrollLink(){
    if(enabled == 'yes') {
        var scrollPos = document.documentElement.scrollTop;
        var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
        var scrolled = ((scrollPos/height)*100)/1.13;
        fader.style.top = scrolled + "%";
    }
}

var enabled='yes';
var faderPath=document.getElementById('scrolltrack');
var fader=document.getElementById('scrollthumb');
让触摸=虚假;
//点击并拖动
音量调节器。添加音量调节器(“鼠标向下”,拾取,错误);
功能拾取(事件){
if(touch==false){
已启用='否';
让startPos=event.clientY;
让faderStart=fader.offsetTop;
让bottomEdge=faderPath.OffsetEight-fader.OffsetEight;
设needRAF=null;
函数moveAt(事件){
如果(需要RAF){
needRAF=null;
取消动画帧(setNew);
}
needRAF=requestAnimationFrame(setNew);
函数setNew(){
让dragDist=event.clientY-startPos;
让newTop=faderStart+dragDist;
//抑制音轨中的音量控制器
if(新的底部边缘){
newTop=底边;
}
//设置新位置
fader.style.top=`${newTop}px`;
//将头寸换算成百分比
var newTopPer=(newTop/底边);
//使用音量控制器位置使页面滚动
var height=document.documentElement.scrollHeight-document.documentElement.clientHeight;
var scrollPos=newTopPer*高度;
document.documentElement.scrollTop=scrollPos;
}
}
文档。addEventListener('mousemove',moveAt,false);
文件。addEventListener('mouseup',dropIt,false);
函数dropIt(){
document.removeEventListener('mousemove',moveAt,false);
fader.onmouseup=null;
已启用='是';
}
}
}
音量控制器。addEventListener('touchstart',TouchPick,false);
功能触摸拾取(事件){
event.preventDefault();
已启用='否';
触摸=真实;
让startPos=event.targetTouches[0].clientY;
让faderStart=fader.offsetTop;
//在此处声明bottomEdge以防止每次拖动时重新计算
让bottomEdge=faderPath.OffsetEight-fader.OffsetEight;
设needRAF=null;
函数moveAt(touchEvent){
touchEvent.preventDefault();
如果(需要RAF){
needRAF=null;
取消动画帧(setNew);
}
needRAF=requestAnimationFrame(setNew);
函数setNew(){
让dragDist=touchEvent.targetTouches[0].clientY-startPos;
让newTop=faderStart+dragDist;
//抑制音轨中的音量控制器
if(新的底部边缘){
newTop=底边;
}
fader.style.top=`${newTop}px`;
//将头寸换算成百分比
var newTopPer=(newTop/底边);
//使用音量控制器位置使页面滚动
var height=document.documentElement.scrollHeight-document.documentElement.clientHeight;
var scrollPos=newTopPer*高度;
document.documentElement.scrollTop=scrollPos;
}
}
文件。添加的文件列表器('touchmove',moveAt,false);
文件。addEventListener('touchend',dropIt,false);
addEventListener('touchcancel',函数(e){e.preventDefault()},false);
函数dropIt(){
document.removeEventListener('touchmove',moveAt,false);
fader.ontouchend=null;
已启用='是';
触摸=假;
}
}
fader.ondragstart=函数(){
返回false;
}
//使音量控制器随着窗口滚动而移动
window.addEventListener('scroll',scrollLink,false);
函数scrollLink(){
如果(已启用==“是”){
var scrollPos=document.documentElement.scrollTop;
var height=document.documentElement.scrollHeight-document.documentElement.clientHeight;
变量滚动=((滚动位置/高度)*100)/1.13;
衰减器