HTML5 Drag and Drop - Нет прозрачности? - PullRequest
38 голосов
/ 15 марта 2012

Когда я перетаскиваю элемент на моей странице, элемент становится «призрачным». В основном это получает некоторое значение прозрачности.

Есть ли способ сделать это opacity: 1;?

Ответы [ 11 ]

29 голосов
/ 06 июня 2012

Похоже, что это не может быть сделано.Перетаскиваемый элемент помещается в контейнер, который имеет свою непрозрачность ниже 1.Это означает, что хотя вы можете уменьшить непрозрачность перетаскиваемого элемента, вы не можете получить его выше, чем непрозрачность инкапсулирующего элемента.такой элемент, но так как ничего не добавляется в DOM во время перетаскивания, в лучшем случае это будет очень сложно.

7 голосов
/ 23 октября 2014

Как уже предлагали другие, вам понадобится какой-то механизм, который будет:

  1. Скрыть элемент, который перетаскивается.
  2. Сделать клон элемента, который находитсяDrag.
  3. Поместите клон на место перетаскиваемого элемента.
  4. Прослушайте событие drag, чтобы позиционировать элемент клона.

Inна практике это выглядит так:

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.

3 голосов
/ 02 июля 2015

Пожалуйста, посмотрите это работает скрипка

У меня есть решение для создания непрозрачного изображения вместо призрака, и оно отлично работает в 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';});
2 голосов
/ 11 июня 2012

Если вы не перетаскиваете элементы из-за пределов веб-страницы (из операционной системы), вы можете легко решить эту проблему, применив собственное перетаскивание. Существует множество примеров простого перетаскивания JavaScript, которое будет прекрасно работать в среде HTML5 и будет полностью настраиваемым вами.

ответ: (используйте старый способ)

1 голос
/ 04 февраля 2019

Для тех (как и я), разочарованных реализацией drag & drop html5, вот базовое, ванильное, кросс-браузерное, без ошибок и полностью настраиваемое решение:

HTML:

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

ЯШ:

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.

0 голосов
/ 04 июля 2019

Рабочий пример 2012 года можно посмотреть на Chrome (вы должны использовать Chrome) в «chrome: // apps /». Если вы хотите точно знать, как они это сделали, откройте dev tools (strg + shift + i, поскольку левый щелчок используется для пользовательского контекстного меню) и начните обратный инжиниринг (строка 7241 в index.html хорошая отправная точка).

Вот краткое резюме:

Они клонировали перетаскиваемый элемент на dragstart, добавили его в какой-то контейнер верхнего уровня и поместили его на курсор на drag. Чтобы не блокировать события для реальных элементов, они стилизовали клон с помощью pointer-events: none;

0 голосов
/ 12 июня 2012

Предложение, сделайте следующее, теперь для этого я использую jQuery, попробуйте, прежде чем сказать, что что-то не работает, мы здесь не для того, чтобы давать ответы, а здесь, чтобы указать вам правильное направление.

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

тогда вам нужно придумать, чтобы сказать, что он прекратил перетаскивание и опустился в позицию, а затем удалитьClass ('overdrag');

Это не сложно сделать, поэтому я думаю, что вы должны это сделать. Я хочу поблагодарить @DonaldHuckle, так как это действительно его решение, а не мое.

0 голосов
/ 11 июня 2012

Я думаю, что прозрачность исходит не от веб-содержимого, а от браузера и ОС. Если вы хотите изменить прозрачность, вы должны настроить или взломать браузер и ОС

0 голосов
/ 11 июня 2012

хотя это, вероятно, не реальное решение основной проблемы, у меня есть идея, что может сработать, по крайней мере, я протестировал это в одном из моих проектов GWT некоторое время назад, и это сработало, поэтому я думаю, что это может работать на нативномJS, хотя у меня нет примера кода:

  1. Вместо использования функции перетаскивания создайте новый элемент, равный элементу, который должен быть перетащен в исходное положение элемента, чтобы бытьтащили.Оригинальный элемент, который нужно перетащить, теперь должен быть невидимым.Реализуйте логику, которая восстанавливает оригинальный элемент и удаляет клона, как только мышь больше не нажимается.

  2. Заставьте элемент клона придерживаться позиции мыши.Событие, которое удаляет клон, также должно проверять, отпущена ли мышь, в то время как элемент для перетаскивания расположен над областью, в которую можно перетащить исходный элемент.

  3. Если true, удалитеклонировать и переместить исходный элемент в целевой контейнер.

Определенно, в CSS и JS также предстоит выполнить много корректировочных работ, но это может быть хитростью, чтобы сокрушитьСтандарт JS.

0 голосов
/ 08 июня 2012

как уже упоминалось, это обрабатывается браузером -> вы не можете изменить это поведение, но если вам действительно нужен этот эффект, попробуйте искать движение мыши, когда мышь нажата (коротко: перетаскивание), проверьте, какой элемент выбран, исоздать копию на лету, которая следует за курсором мыши.выглядит как идеальная работа для jQuery;)

, но если вам не нужно это отчаянно, я бы не стал менять значения по умолчанию в браузерах, так как люди к этому привыкли и могут быть смущены, если что-то ведет себядругим (неизвестным) образом

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...