HTML5拖放 - 没有透明度?

时间:2012-03-15 00:47:23

标签: javascript html5 css3

当我在页面上拖放元素时,元素变为“幻影”。基本上它有一些透明度值。

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

14 个答案:

答案 0 :(得分:29)

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

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

答案 1 :(得分:7)

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

  1. 隐藏正在拖动的元素。
  2. 复制正在拖动的元素。
  3. 放置克隆代替正在拖动的元素。
  4. 收听drag事件以定位克隆元素。
  5. 在实践中,看起来像这样:

    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';
    };
    

    从附加元素开始:

    new Drag(document.querySelector('.element'));
    

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

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

    <强>更新

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

答案 2 :(得分:3)

请参阅此工作fiddle

我有一个解决方案,可以在ghost的位置制作不透明的图像,并且在chrome中工作正常。但是它不能在FF中工作。我需要一些机构来帮助我在Firefox和其他浏览器中使用它。 脚步 1.我们将制作自己的鬼影并将其设置为拖动图像。

document.addEventListener("dragstart", function(e) {
var img = document.createElement("img");
img.src = "img/hackergotchi-simpler.png";
e.dataTransfer.setDragImage(img, 5000, 5000);//5000 will be out of the window
}, false);

2.我们将克隆图像并将其附加到DOM ondrag

var crt,dragX,dragY;
function drag(ev) {
    crt = ev.target.cloneNode(true);
    crt.style.position = "absolute"; 
    document.body.appendChild(crt);
    ev.dataTransfer.setData("text", ev.target.id);
}

3.然后我们将使用光标移动克隆

    document.addEventListener("dragover", function(ev){
ev = ev || window.event;
dragX = ev.pageX; dragY = ev.pageY;
crt.style.left=dragX+"px";crt.style.top=  dragY+"px";
console.log("X: "+dragX+" Y: "+dragY);
}, false);

4.最后,我们将使克隆可见性消失

   document.addEventListener("dragend", function( event ) {crt.style.display='none';});

答案 3 :(得分:2)

如果您不是从网页外部(从操作系统)拖放元素,那么您可以通过实施自己的拖放操作轻松解决此问题。有很多纯javascript拖放的例子,它们可以在HTML5环境中完美运行,并且可以完全自定义。

回答:(用旧方式)

答案 4 :(得分:1)

对于那些对html5拖放操作感到失望的人(像我一样),这是一个基本的,原始的,跨浏览器,无缺陷且可完全自定义的解决方案:

html:

<div class="dropzone"></div>
<div class="dropzone"></div>
<div class="draggable"></div>

js:

var currentElement, currentDropzone, offsetX, offsetY;
function findZoneUnderPoint(x, y) {
  var dropzones = preview.querySelectorAll(".dropzone");
  for (var i = 0; i < dropzones.length; i++) {
    var box = dropzones[i].getBoundingClientRect();
    if (x > box.left && x < box.right && y > box.top && y < box.bottom) {
      return dropzones[i];
    }
  }
}
function onMouseDown(event) {
  currentElement = event.target.closest(".draggable");
  if (currentElement) {
    var box = currentElement.getBoundingClientRect();
    offsetX = event.clientX - box.x;
    offsetY = event.clientY - box.y;
    currentElement.classList.add("drag");           
    currentElement.style.width = box.width.toFixed()+"px";
    currentElement.style.height = box.height.toFixed()+"px";    
    currentElement.style.left = (event.clientX - offsetX) + "px";
    currentElement.style.top = (event.clientY - offsetY) + "px";
    currentElement.style.position = "fixed";
    currentElement.style.zIndex = "999";
    this.addEventListener("mousemove", onMouseMove);
    this.addEventListener("mouseup", onMouseUp);
  }
}
function onMouseMove(event) {
  currentElement.style.left = (event.clientX - offsetX) + "px";
  currentElement.style.top = (event.clientY - offsetY) + "px";
  var dropzone = findZoneUnderPoint(event.clientX, event.clientY);
  if (dropzone !== currentDropzone) {
    if (dropzone) {
      // -> drag enter zone
    }
    if (currentDropzone) {
      // -> drag leave zone
    }
    currentDropzone = dropzone;
  }
}
function onMouseUp(event) {
  var dropzone = findZoneUnderPoint(event.clientX, event.clientY);
  if (dropzone) {
    // -> drag complete
  } else {
    // -> drag canceled
  }
  currentElement = null;
  document.removeEventListener("mouseup", onMouseUp);
  document.removeEventListener("mousemove", onMouseMove);
}
document.addEventListener("mousedown", onMouseDown);

注意:需要Element.closest() polyfill来获得支持。

答案 5 :(得分:0)

如前所述,这是由浏览器处理的 - &gt;你不能改变这种行为,但如果你真的需要这种效果,试着在鼠标停止时寻找鼠标移动(简短:拖动),检查选择了哪个元素,并在鼠标光标后面立即创建一个副本。看起来像jQuery的理想工作;)

但如果你不需要它,我不会尝试更改浏览器的默认值,因为人们习惯了它,如果某些事情以另一种(未知)的方式表现,可能会感到困惑

答案 6 :(得分:0)

尽管这可能不是核心问题的真正解决方案,但我知道什么可能有用,至少我前一段时间在我的一个GWT项目中测试了它并且它有效,所以我想它可能在本机工作JS以及我没有代码示例:

  1. 不使用拖动功能,而是创建一个新元素,该元素等于在要拖动的元素的原始位置应该是dragget的元素。要拖动的原始元素现在应该是不可见的。实现恢复orignal元素的逻辑,并在不再按下鼠标时立即删除克隆。

  2. 使克隆元素保持在鼠标位置。删除克隆的事件还要检查鼠标是否被释放,而要拖动的元素位于可以拖动原始元素的区域上。

  3. 如果为true,请删除克隆并将原始元素移动到目标容器。

  4. 在CSS和JS中肯定还有很多调整工作要做,但这可能是一个淹没JS标准的技巧。

答案 7 :(得分:0)

我认为透明度不是来自网页内容,而是来自浏览器和操作系统。 如果要更改不透明度,则必须调整或破解浏览器和操作系统

答案 8 :(得分:0)

可以在“ chrome:// apps /”下的chrome(必须使用chrome)上查看2012年以后的工作示例。如果您想确切地知道他们是如何做到的,请打开dev toolsstrg + shift + i,因为左键用于自定义上下文菜单)并开始进行逆向工程(index.html中的7241行是一个很好的选择)。初始点)。

这是一个简短的总结:

他们在dragstart上克隆了拖动的元素,将其添加到某个顶级容器中,并将其定位到drag上的光标上。为了避免将事件阻止到实际元素,他们使用pointer-events: none;

为克隆设置了样式

答案 9 :(得分:0)

请不要问我为什么会这样,但是如果您将不透明度设置为0.99999而不是1,那么它对我有效。 我真的很好奇为什么如果有人知道,请发表您的想法。

答案 10 :(得分:0)

在拖动开始时使用 event.dataTransfer.setDragImage(new Image(), 0, 0); 隐藏原始图像。 onDrag 获取重影图像,使用 event.pageX, event.pageY

更新位置

答案 11 :(得分:0)

自 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) {}

第 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';
}

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

function onDrag(e) {
    draggedItem.style.left = e.ClientX - dx;
    draggedItem.style.top = e.ClientY - dy;
}

第 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;
}

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

答案 12 :(得分:-4)

如果您使用的是JavaScript,则在处理dragStart事件的函数中包括将样式不透明度设置为1示例:

function dragStartHandler(e) {
   this.style.opacity = '1.0';
}

答案 13 :(得分:-4)

建议,执行以下操作,现在为此我使用jQuery,尝试一下,然后说一些不会工作的东西,我们不是在这里给出答案,但这里指的是正确的方向。

function dragStartHandler(e) { 
   $("span.{CLASS}")addClass('overdrag'); 
} 

然后你需要拿出来告诉它已经停止了拖动并掉到了位置,然后到了RemoveClass(&#39; overdrag&#39;);

这并不难,所以我认为你应该能够做到。我要感谢@DonaldHuckle,因为这不是我的解决方案。