HTML5拖放 - 没有透明度?

Joh*_*gen 42 javascript html5 css3

当我在页面上拖放元素时,元素变为"幻影".基本上它有一些透明度的价值.

有没有办法让它成功opacity: 1;

c2h*_*5oh 32

看起来它无法完成.被拖动的元素被放入具有它自己的容器中,低于1,不透明度.这意味着虽然可以降低拖动元素的不透明度,但是无法使其高于封装元素的不透明度.

可能覆盖此类元素的默认浏览器设置,但由于在拖动过程中没有任何内容添加到DOM,因此最多也会非常棘手.

  • 这只是我还是这也让别人伤心?我的意思是用html5拖放的想法真棒吗?但我现在已经尝试了几个小时,但它确实令我失望.这个不透明度问题是回到jquery ui的原因之一. (21认同)
  • @driechel听到"回到jquery"让我很难过. (16认同)
  • `drag(event)` 启动处理程序上的 `event.target.style.xxx` 将样式应用于选择用于拖动的元素,但似乎在创建用于拖动的幽灵副本之后,因此不透明度的建议不起作用(至少Chrome 上)并解释了上面的评论 (4认同)
  • 可以使用 event.target.style.opacity=1 来完成;内拖动($event){ .. } (3认同)
  • 这么奇怪。`console.log(window.getCompulatedStyle(event.target).opacity)` 和 `console.log(window.getCompulatedStyle(event.srcElement).opacity)` 都返回 `1`,但它仍然是半透明的。操作一定是正确的。它必须是一些不可见的容器,它继承了降低的不透明度。 (3认同)

Gaj*_*jus 7

正如其他人所建议的那样,您将需要某种机制:

  1. 隐藏正在拖动的元素.
  2. 复制正在拖动的元素.
  3. 将克隆放在被拖动元素的位置.
  4. 收听drag事件以定位克隆元素.

在实践中,看起来像这样:

function Drag (subject) {
    var dative = this,
        handle,
        dragClickOffsetX,
        dragClickOffsetY,
        lastDragX,
        lastDragY;

    subject.draggable = true;

    dative.styleHandle(subject);

    subject.addEventListener('dragstart', function (e) {    
        handle = dative.makeHandle(subject);

        dragClickOffsetX = e.layerX;
        dragClickOffsetY = e.layerY;

        this.style.opacity = 0;
    });

    subject.addEventListener('drag', function (e) {
        var useX = e.x,
            useY = e.y;

        // Odd glitch
        if (useX === 0 && useY === 0) {
            useX = lastDragX;
            useY = lastDragY;
        }

        if (useX === lastDragX && useY === lastDragY) {
            return;
        }

        dative.translate(useX - dragClickOffsetX, useY - dragClickOffsetY, handle, subject);

        lastDragX = useX;
        lastDragY = useY;
    });

    subject.addEventListener('dragend', function (e) {
        this.style.opacity = 1;

        handle.parentNode.removeChild(handle);
    });
};

/**
 * Prevent the text contents of the handle element from being selected.
 */
Drag.prototype.styleHandle = function (node) {
    node.style['userSelect'] = 'none';
};

/**
 * @param {HTMLElement} subject
 * @return {HTMLElement}
 */
Drag.prototype.makeHandle = function (subject) {
    return this.makeClone(subject);
};

/**
 * Clone node.
 * 
 * @param {HTMLElement} node
 * @return {HTMLElement}
 */
Drag.prototype.makeClone = function (node) {
    var clone;

    clone = node.cloneNode(true);

    this.styleClone(clone, node.offsetWidth, node.offsetHeight);

    node.parentNode.insertBefore(clone, node);

    return clone;
};

/**
 * Make clone width and height static.
 * Take clone out of the element flow.
 *
 * @param {HTMLElement} node
 * @param {Number} width
 * @param {Nubmer} height
 */
Drag.prototype.styleClone = function (node, width, height) {
    node.style.position = 'fixed';
    node.style.zIndex = 9999;
    node.style.width = width + 'px';
    node.style.height = height + 'px';
    node.style.left = '-9999px';

    node.style.margin = 0;
    node.style.padding = 0;
};

/**
 * Used to position the handle element.
 * 
 * @param {Number} x
 * @param {Number} y
 * @param {HTMLElement} handle
 * @parma {HTMLElement} subject
 */
Drag.prototype.translate = function (x, y, handle, subject) {
    handle.style.left = x + 'px';
    handle.style.top = y + 'px';
};
Run Code Online (Sandbox Code Playgroud)

从附加元素开始:

new Drag(document.querySelector('.element'));
Run Code Online (Sandbox Code Playgroud)

而且你可以完全控制可拖动元素的外观.在上面的例子中,我克隆了原始元素以将其用作句柄.您可以扩展该Drag功能以自定义句柄(例如,使用图像来表示可拖动元素).

在你太兴奋之前,有几件事需要考虑:

更新:

我已经编写了一个库,用于启用触摸功能的WHATWG拖放机制,https://github.com/gajus/pan.


Alp*_*til 5

截至 2021 年,您无需克隆该元素。浏览器创建一个半透明的克隆,在拖动事件上跟随鼠标指针。同时,原始拖动的项目保持不变,没有任何变化。

如果您希望显示被拖动的原始元素以跟随鼠标指针,那么这里有一个技巧。

设置:

<!- HTML Code Sample ->
<div draggable="true" 
    ondragstart="onDragStart(event)" ondrag="onDrag(event)"
                    ondragend="onDragEnd(event)">

<!- JS Code Sample ->
var dx = 0, dy = 0, draggedItem = undefined;
function onDragStart(e) {}
function onDrag(e) {}
function onDragEnd(e) {}
Run Code Online (Sandbox Code Playgroud)

步骤 1: 将拖动项目的 (x, y) 坐标与鼠标指针坐标之间的差值保存为 delta。

function onDragStart(e) {
    draggedItem = e.target;
    dx = e.clientX - draggedItem.getBoundingClientRect().x;
    dy = e.clientY - draggedItem.getBoundingClientRect().y;
    draggedItem.style.position = 'absolute';
}
Run Code Online (Sandbox Code Playgroud)

步骤 2: 用鼠标指针的 (x, y) 坐标更新拖动项目的位置。记住减去增量。

function onDrag(e) {
    draggedItem.style.left = e.ClientX - dx;
    draggedItem.style.top = e.ClientY - dy;
}
Run Code Online (Sandbox Code Playgroud)

步骤 3: 取决于是否保留拖动项目的新位置或运行一些自定义逻辑。

function onDragEnd(e) {

    if('retain new position ???'){
        draggedItem.style.left = e.ClientX - dx;
        draggedItem.style.top = e.ClientY - dy;
    } else {
        draggedItem.style.position = 'static';

        // Add your custom logic to handle drag completion
    }

    // Clear temporary data
    draggedItem = undefined;
    dx = dy = 0;
}
Run Code Online (Sandbox Code Playgroud)

这将使原始拖动的项目跟随半透明拖动的克隆,从而克服了不透明度的影响。onDrag 事件每 350 毫秒触发一次,并创建一个不错的可视化效果。