如何使用angularJS突出显示可拖动元素下的拖放区域?

时间:2015-08-03 12:14:14

标签: javascript css angularjs drag-and-drop

当拖动的元素位于其上方时,我遇到了突出显示拖放区域(使用dropZone指令定义)的问题。

我尝试过使用CSS:

.highlight {
    background-color: rgba(0, 255, 0, 0.2);
}
.highlight:hover {
    background-color: rgba(0, 255, 0, 0.5);
}

但这不起作用,因为我拖动了一个元素,因此hover位于可拖动元素上。

以下是代码:

var app = angular.module("myApp", []);

app.directive("dragCopy", function($http, $compile, $document) {
  return {
    restrict: 'A',
    link: function($scope, $element) {
      $element.on("mousedown", function($event) {
        $event.preventDefault();

        var newNode = $compile('<div class="dragFile" draggable-file>drag</div>')($scope);

        newNode.children("#title").text($element.parent().text());

        angular.element($document[0].body).append(newNode);
        newNode.css({
          top: $event.pageY - (newNode.prop("offsetHeight") * 0.9) + "px",
          left: $event.pageX - (newNode.prop("offsetWidth") / 2) + "px",
        });

        newNode.triggerHandler("mousedown");
      });
    }
  }
});

app.factory("dragDropService", function() {
  var object = {
    dropZoneList: [],
    highlightList: [],
    register: function(element) {
      object.dropZoneList.push(element);
    },
    highlightDropZones: function() {
      for (var i in object.dropZoneList) {
        var element = object.dropZoneList[i].append('<div class="highlight"></div>');
        var childrens = element.children();

        object.highlightList.push(childrens[childrens.length - 1]);
      }
    },
    resetDropZones: function() {
      for (var i in object.highlightList) {
        object.highlightList[i].remove();
      }
    }
  };

  return object;
});

app.directive("dropZone", function(dragDropService) {
  return {
    restrict: 'A',
    link: function($scope, $element) {
      dragDropService.register($element);
    }
  };
});

app.directive("draggableFile", function($document, dragDropService) {
  return {
    restrict: 'A',
    link: function($scope, $element) {
      var startX = 0,
        startY = 0;
      var x, y;

      $element.on("mousedown", function($event) {
        dragDropService.highlightDropZones();

        startX = $element.prop("offsetWidth") / 2;
        startY = $element.prop("offsetHeight") * 0.9;

        $document.on("mousemove", mousemove);
        $document.on("mouseup", mouseup);
      });

      function mousemove($event) {
        y = $event.pageY - startY;
        x = $event.pageX - startX;
        $element.css({
          top: y + "px",
          left: x + "px"
        });
      }

      function mouseup() {
        $document.off("mousemove", mousemove);
        $document.off("mouseup", mouseup);
        $element.remove();

        console.log(document.elementFromPoint(x, y));

        dragDropService.resetDropZones();
      }
    }
  }
});
.itemDrag {
  cursor: pointer;
  border: 3px solid #81CFE0;
  border-radius: 50%;
  font-size: 40px;
  color: #81CFE0;
  padding: 5px;
  background-color: rgba(255, 255, 255, 0.5);
}
#receiver {
  position: absolute;
  left: 50%;
  right: 0;
  top: 0;
  bottom: 0;
}
.dragFile {
  position: absolute;
  border: 1px solid #81CFE0;
  border-radius: 5px;
  background-color: rgba(129, 207, 224, 0.5);
  cursor: pointer;
}
.highlight {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  color: #00FF00;
  border: 3px dashed #00FF00;
  border-radius: 5px;
  text-align: center;
  font-weight: bold;
  text-shadow: 0px 0px 2px black;
  background-color: rgba(0, 255, 0, 0.2);
}
.highlight:before {
  content: "Add content to terminal";
}

.highlight:hover {
  background-color: rgba(0, 255, 0, 0.5);
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp">
  <div class="itemDrag fa fa-hand-pointer-o" drag-copy></div>
  <div id="receiver" drop-zone></div>
</div>

是否只能使用CSS?

3 个答案:

答案 0 :(得分:2)

您可以使用document.elementFromPoint来标识光标所在的元素。现在你只需要验证它是否有'突出显示'类。

btw - 如果你使用translate来移动元素图像,document.elementFromPoint会有更好的结果,因为被拖动的元素不会干扰。

function mousemove($event) {
    y = $event.pageY - startY;
    x = $event.pageX - startX;

    var dropElement = document.elementFromPoint(x, y);

    console.log(dropElement.classList.contains('highlight'));

    $element.css({
        top : y + "px",
        left : x + "px"
    });
}

答案 1 :(得分:2)

我找到了解决问题的方法。感谢您的回答,我找到了另一条路。

我正在mousemove指令上收听dropZone事件。这样,如果鼠标在放置区域内移动,它将触发并添加样式。

以下是工作代码:

&#13;
&#13;
var app = angular.module("myApp", []);

app.directive("dragCopy", function($http, $compile, $document) {
  return {
    restrict: 'A',
    link: function($scope, $element) {
      $element.on("mousedown", function($event) {
        $event.preventDefault();

        var newNode = $compile('<div class="dragFile" draggable-file>drag</div>')($scope);

        newNode.children("#title").text($element.parent().text());

        angular.element($document[0].body).append(newNode);
        newNode.css({
          top: $event.pageY - (newNode.prop("offsetHeight") * 0.5) + "px",
          left: $event.pageX - (newNode.prop("offsetWidth") / 2) + "px",
        });

        newNode.triggerHandler("mousedown");
      });
    }
  }
});

app.factory("dragDropService", function() {
  var object = {
    dropZoneList: [],
    callbackList: [],
    highlightList: [],
    register: function(element, callback) {
      object.dropZoneList.push(element);
      object.callbackList.push(callback);
    },
    highlightDropZones: function() {
      for (var i in object.dropZoneList) {
        object.dropZoneList[i].append('<div class="highlight"></div>');

        var childrens = object.dropZoneList[i].children();

        object.highlightList.push(childrens[childrens.length - 1]);
        object.callbackList[i]();
      }
    },
    resetDropZones: function() {
      for (var i in object.highlightList) {
        object.callbackList[i]();
        object.highlightList[i].remove();
      }
      object.highlightList = [];
    }
  };

  return object;
});

app.directive("dropZone", function($document, dragDropService) {
  return {
    restrict: 'A',
    link: function($scope, $element) {
      var highlighted = false;

      function toggleHover() {
        if (highlighted) {
          $document.off("mousemove", mousemove);
          highlighted = false;
        } else {
          $document.on("mousemove", mousemove);
          highlighted = true;
        }
      }

      function mousemove($event) {
        x = $event.pageX;
        y = $event.pageY;

        elementBounding = $element[0].getBoundingClientRect();

        console.log("in");

        if (x > elementBounding.left && x < elementBounding.right && y > elementBounding.top && y < elementBounding.bottom) {
          angular.element($element.children()[$element.children().length - 1]).addClass("droppable");
        } else {
          angular.element($element.children()[$element.children().length - 1]).removeClass("droppable");
        }
      }

      dragDropService.register($element, toggleHover);
    }
  };
});

app.directive("draggableFile", function($document, dragDropService) {
  return {
    restrict: 'A',
    link: function($scope, $element) {
      var startX = 0,
        startY = 0;
      var x, y;

      $element.on("mousedown", function($event) {
        dragDropService.highlightDropZones();

        startX = $element.prop("offsetWidth") / 2;
        startY = $element.prop("offsetHeight") * 0.5;

        $document.on("mousemove", mousemove);
        $document.on("mouseup", mouseup);
      });

      function mousemove($event) {
        x = $event.pageX - startX;
        y = $event.pageY - startY;

        $element.css({
          left: x + "px",
          top: y + "px"
        });
      }

      function mouseup() {
        $document.off("mousemove", mousemove);
        $document.off("mouseup", mouseup);
        $element.remove();

        console.log(document.elementFromPoint(x, y));

        dragDropService.resetDropZones();
      }
    }
  };
});
&#13;
.itemDrag {
  cursor: pointer;
  border: 3px solid #81CFE0;
  border-radius: 50%;
  font-size: 40px;
  color: #81CFE0;
  padding: 5px;
  background-color: rgba(255, 255, 255, 0.5);
}
#receiver1 {
  position: absolute;
  left: 50%;
  right: 0;
  top: 0;
  bottom: 50%;
}
#receiver2 {
  position: absolute;
  left: 50%;
  right: 0;
  top: 50%;
  bottom: 0;
}
.dragFile {
  position: absolute;
  border: 1px solid #81CFE0;
  border-radius: 5px;
  background-color: rgba(129, 207, 224, 0.5);
  cursor: pointer;
}
.highlight {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  color: #00FF00;
  border: 3px dashed #00FF00;
  border-radius: 5px;
  text-align: center;
  font-weight: bold;
  text-shadow: 0px 0px 2px black;
  background-color: rgba(0, 255, 0, 0.2);
}
.highlight:before {
  content: "Add content to terminal";
}
.highlight.droppable {
  background-color: rgba(0, 255, 0, 0.5);
}
&#13;
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp">
  <div class="itemDrag fa fa-hand-pointer-o" drag-copy></div>
  <div id="receiver1" drop-zone></div>
  <div id="receiver2" drop-zone></div>
</div>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

  

是否只能使用CSS?

事实是,由浏览器决定元素是否悬停。因此,如果他说不,那么我不确定如果:hover:active首先被触发,CSS是否足够。

无论如何,这是使用Angular的内置行为的另一个JS解决方案:

ngMouseenter + ngMouseleave

将此添加到您的CSS:

.hovered {
  background-color: rgba(0, 255, 0, 0.5);
  cursor: pointer;
  z-index: 999;
}

然后在 dropZone 指令中使用 mouseenter mouseleave 行为,如下所示:

app.directive("dropZone", function(dragDropService) {
  return {
    restrict: 'A',
    link: function($scope, $element) {
      dragDropService.register($element);

      $element.bind("mouseenter", function(e){
         // if mouse's button is not clicked then we are not dragging
         if(e.buttons == 1 || e.buttons == 3){
            $element.addClass('hovered');
         }
      });

      $element.bind("mouseleave", function(){
          $element.removeClass('hovered');
      });

    }
  };
});

此代码段显示了它的工作原理:

&#13;
&#13;
var app = angular.module("myApp", []);

app.directive("dragCopy", function($http, $compile, $document) {
  return {
    restrict: 'A',
    link: function($scope, $element) {
      $element.on("mousedown", function($event) {
        $event.preventDefault();

        var newNode = $compile('<div class="dragFile" draggable-file>drag</div>')($scope);

        newNode.children("#title").text($element.parent().text());

        angular.element($document[0].body).append(newNode);
        newNode.css({
          top: $event.pageY - (newNode.prop("offsetHeight") * 0.9) + "px",
          left: $event.pageX - (newNode.prop("offsetWidth") / 2) + "px",
        });

        newNode.triggerHandler("mousedown");
      });
    }
  }
});

app.factory("dragDropService", function() {
  var object = {
    dropZoneList: [],
    highlightList: [],
    register: function(element) {
      object.dropZoneList.push(element);
    },
    highlightDropZones: function() {
      for (var i in object.dropZoneList) {
        var element = object.dropZoneList[i].append('<div class="highlight"></div>');
        var childrens = element.children();

        object.highlightList.push(childrens[childrens.length - 1]);
      }
    },
    resetDropZones: function() {
      for (var i in object.highlightList) {
        object.highlightList[i].remove();
      }
    }
  };

  return object;
});

app.directive("dropZone", function(dragDropService) {
  return {
    restrict: 'A',
    link: function($scope, $element) {
      dragDropService.register($element);

      $element.bind("mouseenter", function(e){
         if(e.buttons == 1 || e.buttons == 3){
            $element.addClass('hovered');
         }
      });

      $element.bind("mouseleave", function(){
          $element.removeClass('hovered');
      });
    }
  };
});

app.directive("draggableFile", function($document, dragDropService) {
  return {
    restrict: 'A',
    link: function($scope, $element) {
      var startX = 0,
        startY = 0;
      var x, y;

      $element.on("mousedown", function($event) {
        dragDropService.highlightDropZones();

        startX = $element.prop("offsetWidth") / 2;
        startY = $element.prop("offsetHeight") * 0.9;

        $document.on("mousemove", mousemove);
        $document.on("mouseup", mouseup);
      });

      function mousemove($event) {
        y = $event.pageY - startY;
        x = $event.pageX - startX;
        $element.css({
          top: y + "px",
          left: x + "px"
        });
      }

      function mouseup() {
        $document.off("mousemove", mousemove);
        $document.off("mouseup", mouseup);
        $element.remove();

        console.log(document.elementFromPoint(x, y));

        dragDropService.resetDropZones();
      }
    }
  }
});
&#13;
.itemDrag {
  cursor: pointer;
  border: 3px solid #81CFE0;
  border-radius: 50%;
  font-size: 40px;
  color: #81CFE0;
  padding: 5px;
  background-color: rgba(255, 255, 255, 0.5);
}
#receiver {
  position: absolute;
  left: 50%;
  right: 0;
  top: 0;
  bottom: 0;
}
.dragFile {
  position: absolute;
  border: 1px solid #81CFE0;
  border-radius: 5px;
  background-color: rgba(129, 207, 224, 0.5);
  cursor: pointer;
}
.highlight {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  color: #00FF00;
  border: 3px dashed #00FF00;
  border-radius: 5px;
  text-align: center;
  font-weight: bold;
  text-shadow: 0px 0px 2px black;
  background-color: rgba(0, 255, 0, 0.2);
}
.highlight:before {
  content: "Add content to terminal";
}

.hovered {
  background-color: rgba(0, 255, 0, 0.5);
  cursor: pointer;
  z-index: 999;
}
&#13;
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp">
  <div class="itemDrag fa fa-hand-pointer-o" drag-copy></div>
  <div id="receiver" drop-zone></div>
</div>
&#13;
&#13;
&#13;