Javascript 在指令和控制器之间使用公共作用域
我想创建一个svg形状,它是一个圆,并从html文档中存在的应用程序范围中读取规范,例如半径或中心坐标:Javascript 在指令和控制器之间使用公共作用域,javascript,angularjs,Javascript,Angularjs,我想创建一个svg形状,它是一个圆,并从html文档中存在的应用程序范围中读取规范,例如半径或中心坐标: <div ng-app="myApp" > <div id="body" ng-controller="testCtrl"> cx: <input type="number" ng-model="cx"/><br/> cy: <input type="number" ng-model="cy"/><br/&g
<div ng-app="myApp" >
<div id="body" ng-controller="testCtrl">
cx: <input type="number" ng-model="cx"/><br/>
cy: <input type="number" ng-model="cy"/><br/>
R : <input type="number" ng-model="radius" />
<draggable-circle/>
</div>
</div>
该指令是:
testCtrl.directive('draggableCircle', function () {
function link(scope, el, attr) {
var w = 600, h = 400;
var drag = d3.behavior.drag().origin(Object).on("drag", dragmove);
var svg = d3.select(el[0]).append("svg")
.attr("class", "svgContainer")
.attr("width", w)
.attr("height", h);
var newg = svg.append("g").data([{ x: scope.cx , y: scope.cy}]);
var dragCircle = newg.append("circle")
.attr("r", scope.radius)
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function (d) {
return d.y;
})
.attr("fill", "red")
.style("fill-opacity", 0.8)
.style("stroke", "steelblue")
.style("cursor"," pointer")
.call(drag);
function dragmove(d) {
var mousePosition = d3.mouse(this);
dragCircle.attr("cx", d.x =scope.cx= mousePosition[0])
.attr("cy", d.y=scope.cy = mousePosition[1]);
scope.$apply()
}
}
return {
link: link
};
});
问题是,当控制器更改坐标值时,必须在指令中更改形状。但它并没有像我预期的那样起作用。此外,当用户拖动形状时,指令中更改的值会自动广播到控制器和模型,因为使用了scope.$apply()
,我认为这不是最佳解决方案。
我想进行双工连接,即当指令中的规范发生更改时,它会影响控制器,反之亦然。我还想为这个目标实施最好的解决方案
Plunker链接:
更新
我想将控件和形状绑定在一起,这意味着形状坐标会随着绑定到模型的控件值的更改而更改,反之亦然。Saman
你可以使用这个概念叫做。它工作正常,是一个轻量级的解决方案。您无需过度使用$watch
和$broadcast
或$emit
萨曼
你可以使用这个概念叫做。它工作正常,是一个轻量级的解决方案。您不需要过度使用
$watch
和$broadcast
或$emit
您的问题根本不是范围;问题是您将dragmove
函数注册为回调函数。
此回调未在AngulasJs环境中注册,因此需要使用$apply
。当此回调对范围变量进行更改时,除非调用$apply
,否则angular框架不会意识到它。在使用非角度库和角度代码时,这是一个常见问题
我认为你是对的;也许你现在需要的只是
function updatePosition(){
dragCircle.attr("cx", d.x =scope.cx)
.attr("cy", d.y=scope.cy);
}
$scope.$watch('cx', updatePosition);
$scope.$watch('cy', updatePosition);
如果这方面有任何问题,请告诉我,因为我从未使用过d3.js,所以我可能不知道那里发生了什么事。你的问题根本不是关于作用域;问题是您将
dragmove
函数注册为回调函数。
此回调未在AngulasJs环境中注册,因此需要使用$apply
。当此回调对范围变量进行更改时,除非调用$apply
,否则angular框架不会意识到它。在使用非角度库和角度代码时,这是一个常见问题
我认为你是对的;也许你现在需要的只是
function updatePosition(){
dragCircle.attr("cx", d.x =scope.cx)
.attr("cy", d.y=scope.cy);
}
$scope.$watch('cx', updatePosition);
$scope.$watch('cy', updatePosition);
如果这方面有任何问题,请告诉我,因为我从未使用过d3.js,所以我可能不知道那里发生了什么事情。您应该阅读。在此之后,您需要从指令中的控制器中获取$watch属性,并在应用它们之后生成$scope.apply,这将不会导致父范围,因为对象位于隔离范围中
我为你做了一件事:
cx:
赛义德:
R:
var angularApp=angular.module('myApp',[]);
var testCtrl=angularApp.controller('testCtrl',function($scope){
$scope.initial={};
$scope.initial.cx=100;
$scope.initial.cy=100;
$scope.initial.radius=50;
});
指令('DragableCircle',函数(){
功能链接(范围、el、属性){
var w=600,h=400;
var drag=d3.behavior.drag().origin(Object).on(“drag”,dragmove);
var svg=d3.select(el[0]).append(“svg”)
.attr(“类”、“svgContainer”)
.attr(“宽度”,w)
.attr(“高度”,h);
var newg=svg.append(“g”).data([{x:scope.initial.cx,y:scope.initial.cy}]);
var dragCircle=newg.append(“圆”)
.attr(“r”,范围初始半径)
.attr(“cx”,功能(d){
返回d.x;
})
.attr(“cy”,函数(d){
返回d.y;
})
.attr(“填充”、“红色”)
.style(“填充不透明度”,0.8)
.风格(“笔划”、“钢蓝”)
.style(“光标”、“指针”)
.呼叫(拖动);
范围$watch('initial.cx',applyNewProperties);
范围:$watch('initial.cy',applyNewProperties);
函数applyNewProperties(){
dragCircle.attr(“cx”,scope.initial.cx)
.attr(“cy”,scope.initial.cy);
}
功能拖动(d){
console.log(scope.initial);
var mousePosition=d3.mouse(this);
dragCircle.attr(“cx”,d.x=scope.cx=scope.initial.cx=mousePosition[0])
.attr(“cy”,d.y=scope.cy=scope.initial.cy=mousePosition[1]);
范围:$apply()
}
}
返回{
链接:链接,
范围:{
首字母:'='
}
};
});
你应该读一读。在此之后,您需要从指令中的控制器中获取$watch属性,并在应用它们之后生成$scope.apply,这将不会导致父范围,因为对象位于隔离范围中
我为你做了一件事:
cx:
赛义德:
R:
var angularApp=angular.module('myApp',[]);
var testCtrl=angularApp.controller('testCtrl',function($scope){
$scope.initial={};
$scope.initial.cx=100;
scope.$watch('coord', updateCoord,true);
function updateCoord() {
dragCircle.attr("cx", scope.coord.cx)
.attr("cy", scope.coord.cy).attr("r",scope.coord.radius);
}
function dragmove(d) {
var mousePosition = d3.mouse(this);
dragCircle.attr("cx", d.x = scope.coord.cx = mousePosition[0])
.attr("cy", d.y = scope.coord.cy =mousePosition[1]);
scope.$apply();
}
function update() {
dragCircle = newg.selectAll("circle")
.attr("r", scope.data.radius)
.attr("cx", scope.data.cx)
.attr("cy", scope.data.cy)
.call(drag);
}