【问题标题】:How to stop Angular handling a click event from within d3如何停止Angular从d3中处理点击事件
【发布时间】:2016-02-26 01:57:42
【问题描述】:

我有一个 Angular 应用程序,在该应用程序中单击 SVG 元素会改变其状态(在附加的 sn-p 中切换填充颜色)

我还连接了 d3 来拖动同一个对象。

d3 文档指出,它们在非空拖动后停止点击事件,但无论我是否尝试停止传播 ng-click 仍在拾取点击事件。

是否可以仅在没有 d3 拖动的情况下触发 ng-click?

在附加的 sn-p 中,我的期望是,如果您单击蓝色矩形,它将切换为黄色(然后再次返回),但如果您拖动它,则颜色不会改变。我发现在拖动结束时颜色会发生变化。

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

myApp.controller('ctrl', function ($scope){
  //clicking rectangle toggles yellow background
  $scope.isYellow = false; 
  
  var drag = d3.behavior.drag()
        .on("drag", function(d,i) {
          var el = d3.select(this);
          var h = el.attr("height");
          var w = el.attr("width");
          var x = d3.event.x - (w/2);
          var y = d3.event.y - (h/2);
          el.attr("transform", "translate(" + [ x,y ] + ")")

          //try to stop the event from propagating
          d3.event.sourceEvent.stopPropagation();
          d3.event.preventDefault();
        });
  
  d3.select('rect').call(drag);
});
svg {background:red}
rect {fill:blue}
.yellow {fill: yellow}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

  <div ng-app="app">
    <svg width=250 height=250 ng-controller="ctrl">
      <rect 
            ng-class="{yellow : isYellow}"
            ng-click="isYellow = !isYellow"
            x="10" y="10" width="30" height="30">

      </rect>
    </svg>
  </div>

【问题讨论】:

  • 您是否尝试过在 ng-click 函数中设置条件,例如 if ($scope.hasBeenDragged === false) { doThing(); },然后在 d3 .on("drag",...) 块中设置 $scope.hasBeenDragged = true;
  • @BennettAdams 如果真正的代码像这样靠近,那么我们可以,但我们实际上正在使用 browserify,我试图让 d3 代码与 Angular 完全隔离。另外,如果可以避免的话,我讨厌添加状态/代码(随着时间的推移需要摸索和维护):)

标签: angularjs d3.js


【解决方案1】:

通常情况下,只是在一个尖峰中提出问题就足以让我的潜意识继续工作。

d3 docs 甚至有我还没意识到的答案

在拖动手势期间,会阻止某些浏览器默认行为(例如文本选择)。为了允许拖动链接,阻止紧跟在非空拖动手势之后的单击事件的默认行为。在可拖动元素上注册自己的点击监听器时,可以如下检查点击事件是否被抑制:

selection.on("点击", function() { 如果(d3.event.defaultPrevented)返回; // 点击抑制 console.log("点击了!"); });

在从 ng-click 传递 Angular 的 $event 时,我可以检查 isDefaultPrevented,在 d3 拖动后允许修改解决方案,如此处的 sn-p 所示

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

myApp.controller('ctrl', function ($scope){
  //clicking rectangle toggles yellow background
  $scope.isYellow = false; 
  
  $scope.toggleColour = function($event) {
    if ($event.isDefaultPrevented()) {
     return;
    }
    $scope.isYellow = !$scope.isYellow;  
  };

  var drag = d3.behavior.drag()
        .on("drag", function(d,i) {
          var el = d3.select(this);
          var h = el.attr("height");
          var w = el.attr("width");
          var x = d3.event.x - (w/2);
          var y = d3.event.y - (h/2);
          el.attr("transform", "translate(" + [ x,y ] + ")")

          //try to stop the event from propagating
          d3.event.sourceEvent.stopPropagation();
          d3.event.preventDefault();
        });
  
  d3.select('rect').call(drag);
});
svg {background:red}
rect {fill:blue}
.yellow {fill: yellow}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

  <div ng-app="app">
    <svg width=250 height=250 ng-controller="ctrl">
      <rect 
            ng-class="{yellow : isYellow}"
            ng-click="toggleColour($event)"
            x="10" y="10" width="30" height="30">

      </rect>
    </svg>
  </div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-02
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多