如何防止文本选择阻碍 onMouseMove 事件?

How to prevent text selection from obstructing onMouseMove event?

我正在实施 "resize handle" 来更改左侧导航面板的宽度。它是一个 div,它接收 onMouseDown() 事件,计算必要的宽度并在后续调用 onMouseMove() 时将它们应用于正确的元素。但是我遇到了一些问题。

1) article 元素位于导航面板和手柄的右侧,如果我在那里释放鼠标,则不会激活 onMouseUp()。这是因为 onMouseDown() 在其他元素中被激活了吗?

2) 如果我快速向右移动鼠标,我无法阻止 article 中的文本被选中,即使调用 preventDefault()stopPropagation() 之类的方法也是如此.

3) 即使 article 中没有文本,调整大小也只有在我非常缓慢地移动鼠标时才有效。如果鼠标在 article 元素上快速移动,调整大小将停止,除非我松开鼠标按钮 - 在这种情况下,调整大小会顺利进行(表明它是停止调整大小的文本选择,即使没有文本根本)。但是如果我释放鼠标按钮,调整大小应该停止(见第 1 点)。

我见过一些使用 CSS user-select: none 的解决方案,但这会阻止在 article 中选择任何文本,这显然是一种矫枉过正。

那么,当我将鼠标移到文档中的任何元素上时,如何在不选择任何文本的情况下平滑地调整大小? (当然是按右边的按钮div后。)

那是我的 HTML:

<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<title>CSS Template</title>
</head>
<body>
<header>Header</header>
<main>
    <nav id='nav'>
        <div class='navcont' onmousemove='handMm(event)' onmouseup='handMu(event)'>
            <p>nav 1</p>
            <p>nav 2</p>
        </div>
        <div class='handle' onmousedown='handMd(event)' onmousemove='handMm(event)' onmouseup='handMu(event)'>
        </div>
    </nav>
    <article id='article' onmousemove='handMm(event)' onmouseup='handMu(event)'>
    </article>
</main>
<footer>Footer</footer>
</body>
</html>

那是我的 CSS:

html, body {
    height:100%;
    margin:0;
}
body {
    display:flex;
    flex-direction:column;
}
header {
    text-align:center;
}
main {
    flex:1;
    display:flex;
    min-height:0;
}
article {
    background:#CCC;
    width:auto;
    overflow:auto;
    padding:10px;
    flex-grow:1;
}
nav {
    width:300px;
    height:auto;
    overflow: hidden;
    display:flex;
}
.navcont {
    background:#8C8;
    width:auto;
    flex-grow:1;
}
.handle {
    background:#333;
    right:0px;
    width:30px;
    cursor:col-resize;
}
footer {
    text-align:center;
}

那是我的 Javascript:

var mx,px,moving=false;
function handMd(e) {
    mx = e.pageX;
    px = document.getElementById('nav').clientWidth;
    moving = true;
}
function handMm(e) {
    if (moving) {
        e.preventDefault();
        e.stopPropagation();
        e.cancelBubble = true;
        e.returnValue = false;
        var diff = e.pageX - mx;
        document.getElementById('nav').style.width = (px + diff)+'px';
        document.getElementById('article').style.width = (window.innerWidth-px-diff)+'px';
    }
}
function handMu(e) {
    moving = false;
}

这是一个工作示例:https://jsfiddle.net/45h7vq7u/

再举个例子,包括Ryan Tsui的回答:https://jsfiddle.net/v1cmk2f6/1/(text-selection没有了,但是div还是不会顺畅移动,只有快速向右移动时才会这样)。

I don't know how to stop the selection but I can tell you for some help that the event triggered when something is selected is onselect.

使用您喜欢的方法捕获 start movingfinish moving 的事件(onMouseDownonMouseUp 都可以)。添加一个CSS class来指定动作开始时的移动状态。动作完成后删除 CSS class。

对于您的情况,您可以尝试以下操作:

添加一个新的CSS class:

.moving {
    user-select: none;
    -moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
}

扩展您的 handMd()handMu() 功能:

function handMd(e) {
    mx = e.pageX;
    px = document.getElementById('nav').clientWidth;
    moving = true;
    document.getElementById('article').classList.toggle('moving', true);  // Add this line. 'article' is the id of the element where you don't want the selection to occur.
}
function handMu(e) {
    moving = false;
    document.getElementById('article').classList.toggle('moving', false);  // Add this line. 'article' is the id of the element where you don't want the selection to occur.
}

分析了这是如何解决的somewhere else,我得出了以下变化。

HTML - 只需要一个事件处理程序:

...
<main>
    <nav id='nav'>
        <div class='navcont'>
            <p>nav 1</p>
            <p>nav 2</p>
        </div>
        <div class='handle' onmousedown='handMd(event)'>
        </div>
    </nav>
    <article id='article'>
    </article>
</main>
...

Javascript - 附加和分离 onmousemove 事件处理程序比每次鼠标移动时调用 onmousemove 要好得多(只测试鼠标按钮是否已按下)。此外,事件现在附加到文档,而不是屏幕上的每个 div:

var mx,px,minW = 200;
function handMd(e) {
    mx = e.pageX;
    px = document.getElementById('nav').clientWidth;
    document.addEventListener('mousemove',handMm);
    document.addEventListener('mouseup',handMu);
    document.getElementById('article').classList.toggle('moving',true);
    document.getElementById('nav').classList.toggle('moving',true);
}
function handMm(e) {
    var diff = e.pageX - mx;
    if (px+diff >= minW && window.innerWidth-px-diff >= minW) {
        document.getElementById('nav').style.width = (px+diff)+'px';
        document.getElementById('article').style.width = (window.innerWidth-px-diff)+'px';
    }
}
function handMu(e) {
    document.removeEventListener('mousemove',handMm);
    document.removeEventListener('mouseup',handMu);
    document.getElementById('article').classList.toggle('moving',false);
    document.getElementById('nav').classList.toggle('moving',false);
}

CSS - 感谢 Ryan Tsui 的回答,我在调整大小时消除了不需要的文本选择:

.moving {
    user-select:none;
    -moz-user-select:none;
    -webkit-user-select:none;
    -ms-user-select:none;
}