HTML5 拖放 - 没有透明度?

Posted

技术标签:

【中文标题】HTML5 拖放 - 没有透明度?【英文标题】:HTML5 Drag and Drop - No transparency? 【发布时间】:2012-03-31 12:52:16 【问题描述】:

当我在页面上拖放一个元素时,该元素会变成“幻影”。基本上它会获得一些透明度值。

有没有办法让它opacity: 1;

【问题讨论】:

请给我们更多的合作机会。向我们展示您的 javascript 以处理拖放事件等。 重复问题? ***.com/questions/7206622/… 您真的需要代码吗?只是html5中的原生拖拽,能不能让它不透明?不,这不是那个问题的重复。 遗憾的是,这个问题没有答案。我也在为此苦苦挣扎。 唯一的办法就是重新编程拖动功能! 【参考方案1】:

好像做不到。拖动的元素被放入具有它自己的容器中,不透明度低于 1。这意味着虽然您可以降低被拖动元素的不透明度,但您不能使其高于封装元素的不透明度。

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

【讨论】:

是我自己还是这也让其他人伤心?我的意思是用 html5 拖放的想法很棒吧?但是我已经尝试了几个小时了,但它真的让我失望了。这个不透明度问题是原因之一.....回到jquery ui。 @driechel 听到“回到 jquery”让我很难过。 可以使用 event.target.style.opacity=1;内部拖动($event) .. 太奇怪了。 console.log(window.getComputedStyle(event.target).opacity)console.log(window.getComputedStyle(event.srcElement).opacity) 都返回 1,但它仍然是半透明的。操作必须是正确的。它必须是一些不可见的容器,它从中继承了降低的不透明度。 event.target.style.xxx on the drag(event) start 处理程序将样式应用于选择要拖动的元素,但似乎 后生成了用于拖动的幽灵副本,因此不透明度的建议不会'不起作用(至少在 Chrome 上)并解释了上面的 cmets【参考方案2】:

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

    隐藏被拖动的元素。 复制被拖动的元素。 将克隆放置在被拖动元素的位置。 侦听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';
;

从附加元素开始:

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

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

在您过于兴奋之前,有几件事情需要考虑:

WHATWG 拖放功能不适用于移动设备,HTML5 Drag & Drop for Mobile 无法捕获“句柄释放”事件,解决方法见链接:How to get mouseup event after native drag event?。

更新:

我已经为 WHATWG 拖放机制的触控实现编写了一个库,https://github.com/gajus/pan。

【讨论】:

【参考方案3】:

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

回答:(用老办法)

【讨论】:

【参考方案4】:

请看这个工作fiddle

我有一个解决方案可以制作一个不透明的图像来代替 ghost,它在 chrome 中运行良好。但它在 FF 中不起作用。我需要一些身体来帮助我让它在 Firefox 和其他浏览器中运行。 脚步 1.我们会制作自己的ghost图像,并将其设置为拖动图像。

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

【讨论】:

【参考方案5】:

对于那些(像我一样)对拖放 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 来支持ie。

【讨论】:

【参考方案6】:

截至 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 毫秒触发一次,并创建一个不错的可视化效果。

【讨论】:

【参考方案7】:

如前所述,这是由浏览器处理的 -> 您无法更改此行为,但如果您确实需要此效果,请尝试在鼠标按下时寻找鼠标移动(简称:拖动),检查选择了什么元素并动态创建一个跟随鼠标光标的副本。看起来是 jQuery 的理想工作;)

但如果您不是非常需要它,我不会尝试更改浏览器的默认值,因为人们已经习惯了它,并且如果某些东西以另一种(未知)方式运行时可能会感到困惑

【讨论】:

【参考方案8】:

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

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

    使克隆元素粘在鼠标的位置上。删除克隆的事件还必须检查当要拖动的元素位于可以拖动原始元素的区域上时是否释放鼠标。

    如果为 true,则移除克隆并将原始元素移动到目标容器中。

在 CSS 和 JS 中肯定也有很多调整工作要做,但这可能是压倒 JS 标准的一个技巧。

【讨论】:

这就是我建议做的,但我不确定他在阅读 c2h5oh 的回答后是否仍然对解决方案感兴趣;)【参考方案9】:

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

【讨论】:

【参考方案10】:

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

这是一个简短的总结:

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

【讨论】:

【参考方案11】:

在 Dragstart 上使用 event.dataTransfer.setDragImage(new Image(), 0, 0); 隐藏原始图像。 onDrag 获取鬼图,更新位置使用event.pageX,event.pageY

【讨论】:

【参考方案12】:

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

【讨论】:

刚才用 Firefox 试过了,不行。在 dragstart 事件之前和之后,我将被拖动项目的不透明度设置为 0.999。鬼影效果依然存在。【参考方案13】:

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

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

【讨论】:

没有区别...this 指的是目标元素,在我的例子中是一个跨度元素。这就是为什么我认为这行不通。【参考方案14】:

建议,请执行以下操作,现在我正在使用 jQuery,尝试一下,在说什么不起作用之前,我们不是在这里给出答案,而是在这里为您指明正确的方向。

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

然后你需要拿出 away 告诉它已经停止拖动并放置到位,然后到 RemoveClass('overdrag');

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

【讨论】:

这是一个问答,我们在这里给出答案 是,但没有答案解决了这个问题,所以我使用了答案中最好的部分,并想出了这段代码,@HotHeadMartin

以上是关于HTML5 拖放 - 没有透明度?的主要内容,如果未能解决你的问题,请参考以下文章

Javascript:拖放图像标签

C# 具有叠加/不透明图像的拖放效果

使控件在拖放期间对拖动事件透明

HTML5 画布覆盖透明渐变

如何在 html5 中制作透明画布?

是否可以让 HTML5 颜色输入值透明?