【问题标题】:Draggable text box scales more than expected可拖动文本框的缩放超出预期
【发布时间】:2021-02-22 02:19:23
【问题描述】:

我在角落制作了一个文本框和框以调整大小。我第一次拖动时,它工作得很好,但在第一次之后,拖动量似乎成倍增加。 (不要介意拖动节点的位置)。如果您拖动一次,它可以用鼠标很好地缩放。似乎每次之后,当您拖动时,它的缩放距离用户的鼠标越来越远,从而导致“无法控制”的缩放。我在移动函数结束时重置了 prevX 和 prevY 值。我不确定这是否是问题所在。我认为,问题在于在调整大小部分使用 getBoundingClientRect() 进行缩放。但是,移动文本框可以正常工作。这是我的代码:

 var textBox = document.querySelector(".text-box");
            var textArea = document.querySelector('.text-field');
            textArea.focused = false;

            textBox.addEventListener('mousedown', mousedown);

            let isResizing = false;
            let isTyping = false;

            textArea.addEventListener('dblclick', type)
            function type(){
                if (!isTyping){
                    isTyping = true;
                    textArea.style.cursor = 'text';
                }else {
                    isTyping = false;
                    textArea.style.cursor = 'default';
                }
            }

            document.body.onclick = function(e){
                if (e.target != textArea){
                isTyping = false;
                e.target.style.cursor = 'default';
                }
            }

            function mousedown(e){
                if (e.target == textArea){
                    e.target.style.cursor = 'default';
                }

                window.addEventListener('mousemove', mousemove);
                window.addEventListener('mouseup', mouseup);

                let prevX = e.clientX;
                let prevY = e.clientY;

                function mousemove(e){
                    if(!isResizing && !isTyping){
                    let newX = prevX - e.clientX;
                    let newY = prevY - e.clientY;

                    const rect = textBox.getBoundingClientRect();

                    textBox.style.left = rect.left - newX + "px";
                    textBox.style.top = rect.top - newY + "px";

                    prevX = e.clientX;
                    prevY = e.clientY;
                }
                }
                function mouseup(){
                    window.removeEventListener('mousemove', mousemove);
                    window.removeEventListener('mouseup', mouseup);
                }

                const handles = document.querySelectorAll('.handle');
                let currentHandle;

                for(let handle of handles){
                    handle.addEventListener('mousedown', mousedown);

                    function mousedown(e){
                        currentHandle = e.target;
                        isResizing = true;

                        let prevX = e.clientX;
                        let prevY = e.clientY;

                        window.addEventListener('mousemove', mousemove);
                        window.addEventListener('mouseup', mouseup);

                        function mousemove(e){
                            const rect = textBox.getBoundingClientRect();

                            if (currentHandle.classList.contains("se")) {
                                textBox.style.width = rect.width - (prevX - e.clientX) + "px";
                                textBox.style.height = rect.height - (prevY - e.clientY) + "px";
                            } else if (currentHandle.classList.contains("sw")) {
                                textBox.style.width = rect.width + (prevX - e.clientX) + "px";
                                textBox.style.height = rect.height - (prevY - e.clientY) + "px";
                                textBox.style.left = rect.left - (prevX - e.clientX) + "px";
                            } else if (currentHandle.classList.contains("ne")) {
                                textBox.style.width = rect.width - (prevX - e.clientX) + "px";
                                textBox.style.height = rect.height + (prevY - e.clientY) + "px";
                                textBox.style.top = rect.top - (prevY - e.clientY) + "px";
                            } else {
                                textBox.style.width = rect.width + (prevX - e.clientX) + "px";
                                textBox.style.height = rect.height + (prevY - e.clientY) + "px";
                                textBox.style.top = rect.top - (prevY - e.clientY) + "px";
                                textBox.style.left = rect.left - (prevX - e.clientX) + "px";
                            }
                            prevX = e.clientX;
                            prevY = e.clientY;
                        }

                        function mouseup(){
                            window.removeEventListener('mousemove', mousemove);
                            window.removeEventListener('mouseup', mouseup);
                            textArea.focused = false;
                            isResizing = false;

                        }
                    }
                }
            }
.text-box{
            height: 50px;
            width: 150px;
            position: absolute;
        }
        .handle{
            position: absolute;
            width: 5px;
            height: 5px;
            background-color: blue;
            z-index: 2;
        }
        .ne{
            top: -1px;
            right: -1px;
            cursor: ne-resize;
        }
        .nw{
            top: -1px;
            left: -1px;
            cursor: nw-resize;
        }
        .sw{
            bottom: -1px;
            left: -1px;
            cursor: sw-resize;
        }
        .se{
            bottom: -1px;
            right: -1px;
            cursor: se-resize;
        }
        .text-field {
            width: 100%;
            height: 100%;
            resize: none;
            cursor: default;
        }
<div class="text-box">
        <textarea class="text-field">Click to add text...</textarea>
        <div class="handle ne"></div>
        <div class="handle nw"></div>
        <div class="handle sw"></div>
        <div class="handle se"></div>
    </div>

【问题讨论】:

  • 您的问题是,每次触发文本框 mousedown 事件时,您都会向四个处理程序中的每一个添加一个新的 mousedown 事件。您的一些代码会在它们运行后尝试清除处理程序,但处理程序上的那些 (handle.addEventListener('mousedown', mousedown);) 总是被添加并且永远不会被删除。如果您想了解我的意思,请将console.log 放入内部mousedown 事件中。

标签: javascript html css node.js


【解决方案1】:

正如克里斯在评论中所说的那样,(但是在理解这个问题之前我尝试了很多东西......) 一种非常简单的解决方法是从 mousedown 函数中取出 for 循环。

var textBox = document.querySelector(".text-box");
var textArea = document.querySelector('.text-field');
textArea.focused = false;

textBox.addEventListener('mousedown', mousedown);

let isResizing = false;
let isTyping = false;

textArea.addEventListener('dblclick', type)
function type(){
    if (!isTyping){
        isTyping = true;
        textArea.style.cursor = 'text';
    }else {
        isTyping = false;
        textArea.style.cursor = 'default';
    }
}


document.body.onclick = function(e){
    if (e.target != textArea){
    isTyping = false;
    e.target.style.cursor = 'default';
    }
}

function mousedown(e){
    if (e.target == textArea){
        e.target.style.cursor = 'default';
    }

    window.addEventListener('mousemove', mousemove);
    window.addEventListener('mouseup', mouseup);

    let prevX = e.clientX;
    let prevY = e.clientY;

    function mousemove(e){
        if(!isResizing && !isTyping){
        let newX = prevX - e.clientX;
        let newY = prevY - e.clientY;

        const rect = textBox.getBoundingClientRect();

        textBox.style.left = rect.left - newX + "px";
        textBox.style.top = rect.top - newY + "px";

        prevX = e.clientX;
        prevY = e.clientY;
    }
    }
    function mouseup(){
        window.removeEventListener('mousemove', mousemove);
        window.removeEventListener('mouseup', mouseup);
    }
}

const handles = document.querySelectorAll('.handle');
let currentHandle;

for(let handle of handles){
    handle.addEventListener('mousedown', mousedown);

    function mousedown(e){
        currentHandle = e.target;
        isResizing = true;

        let prevX = e.clientX;
        let prevY = e.clientY;

        window.addEventListener('mousemove', mousemove);
        window.addEventListener('mouseup', mouseup);

        function mousemove(e){
            const rect = textBox.getBoundingClientRect();

            if (currentHandle.classList.contains("se")) {
                textBox.style.width = rect.width - (prevX - e.clientX) + "px";
                textBox.style.height = rect.height - (prevY - e.clientY) + "px";
            } else if (currentHandle.classList.contains("sw")) {
                textBox.style.width = rect.width + (prevX - e.clientX) + "px";
                textBox.style.height = rect.height - (prevY - e.clientY) + "px";
                textBox.style.left = rect.left - (prevX - e.clientX) + "px";
            } else if (currentHandle.classList.contains("ne")) {
                textBox.style.width = rect.width - (prevX - e.clientX) + "px";
                textBox.style.height = rect.height + (prevY - e.clientY) + "px";
                textBox.style.top = rect.top - (prevY - e.clientY) + "px";
            } else {
                textBox.style.width = rect.width + (prevX - e.clientX) + "px";
                textBox.style.height = rect.height + (prevY - e.clientY) + "px";
                textBox.style.top = rect.top - (prevY - e.clientY) + "px";
                textBox.style.left = rect.left - (prevX - e.clientX) + "px";
            }
            prevX = e.clientX;
            prevY = e.clientY;
        }

        function mouseup(){
            window.removeEventListener('mousemove', mousemove);
            window.removeEventListener('mouseup', mouseup);
            textArea.focused = false;
            isResizing = false;

        }
    }
}

还有一件事,我将这些行添加到您的代码中,以在单击处理程序时不移除调整大小光标:

document.body.onclick = function(e){
     if (e.target != textArea){
         if(e.target.classList.contains('handle')){
             isTyping = false
         }
         else{
             isTyping = false;
             e.target.style.cursor = 'default';
         }
     }
 }

【讨论】:

    猜你喜欢
    • 2010-12-17
    • 1970-01-01
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多