[英]In nested directive, why is my child directive getting the attributes of the parent directive?
我正在使用AngularJS + D3來創建交互式繪圖工具。 我是兩個新手。 我有一個framecontainer指令,其中包含框架。 每個幀都是一個包含矩形和拖動句柄的svg組。 Framecontainer處理所有交互,包括添加新幀。 每個幀可以包含更多幀。 在Framecontainer指令的link函數中,我編譯一個新幀並附加它以添加新幀。 現在,當我第一次使用$ compile添加一個幀時,它會按預期添加幀。 但是,當我拖動新添加的幀時,它似乎從父DOM元素獲取其寬度和高度等屬性。 drag-function取父DOM元素的值。 為什么會這樣?
這是拖動功能:
var dragmove=function(d) {
if (scope.moveable==="true") {
console.log("COMES HERE TOO!");
d.x = Math.max(0, Math.min(w - width, d3.event.x));
d.y = Math.max(0, Math.min(h - height, d3.event.y));
d3.select(dragrect[0].parentNode).attr("transform","translate("+ d.x+","+ d.y+")");
translatex= d.x;
translatey= d.y;
}
}
通過讀取屬性,可以在鏈接函數的開頭設置moveable。 在此拖動功能之外,值應該是它們應該的。 但是,在此函數內部,值似乎是父DOM元素。 因此,盡管我將其設置為true並且函數外部的值為true,但scope.moveable仍為false。 此外,frame指令需要Framecontainer指令並使用其控制器。
這是我的frame指令:
app.directive('frames',function($compile){
return{
restrict:'E',
priority:20,
scope:{
},
replace:true,
require:'^^framecontainer',
template:"<g><rect id='{{surfaceID}}' class='drawarea' ng-Dblclick='popDialog()' fill-opacity='1' ng-attr-x='{{x}}' ng-attr-y='{{y}}' ng-attr-height='{{rectheight}}' ng-attr-width='{{rectwidth}}' stroke-width='3' cursor='move' stroke='{{strokecolor}}' ng-attr-fill={{rectfill}} ></rect>"
+ "<rect ng-attr-height='{{handlerheightr}}' class='dragr' opacity='0' ng-attr-x='{{handlerxr}}' ng-attr-y='{{handleryr}}' ng-attr-width='{{handlerwidthr}}' cursor='ew-resize' fill='#773326' ></rect>"
+ "<rect ng-attr-height='{{handlerheightl}}' class='dragl' opacity='0' ng-attr-x='{{handlerxl}}' ng-attr-y='{{handleryl}}' ng-attr-width='{{handlerwidthl}}' cursor='ew-resize' fill='#773326'></rect>"
+ "<rect ng-attr-height='{{handlerheightt}}' class='dragt' opacity='0' ng-attr-x='{{handlerxt}}' ng-attr-y='{{handleryt}}' ng-attr-width='{{handlerwidtht}}' cursor='ns-resize' fill='#773326'></rect>"
+ "<rect ng-attr-height='{{handlerheightb}}' class='dragb' opacity='0' ng-attr-x='{{handlerxb}}' ng-attr-y='{{handleryb}}' ng-attr-width='{{handlerwidthb}}' cursor='ns-resize' fill='#773326'></rect>"
+"</g>",
compile:function(s,e) {
return {
post: function postLink(scope, element, attr, controller) {
var dragbarw = 10;
scope.surfaceID=attr.id;
scope.rectheight = attr.height;
scope.rectwidth = attr.width;
scope.strokecolor = attr.stroke;
scope.rectfill = attr.fill;
scope.x = attr.x;
scope.y = attr.y;
scope.handlerheightr = attr.height;
scope.handlerwidthr=dragbarw;
scope.handlerheightl = scope.rectheight;
scope.handlerwidthl=dragbarw;
scope.handlerheightt=dragbarw;
scope.handlerheightb=dragbarw;
scope.handlerwidtht=scope.rectwidth;
scope.handlerwidthb=scope.rectwidth;
scope.moveable=attr.mv;
var w = 800;
var h = 500;
var width = scope.rectwidth;
var height=scope.rectheight;
var translatex,translatey;
var dragrect = d3.select(element[0]).selectAll('.drawarea').attr("width","300");
var entireContents=d3.select(element[0]).select('*');
d3.select(element[0]).data([{x:0, y: 0}]);
var dragbarleft=d3.select(element[0]).select(".dragl");
var dragbartop=d3.select(element[0]).select(".dragt");
var dragbarright=d3.select(element[0]).select(".dragr");
var dragbarbottom=d3.select(element[0]).select(".dragb");
// Selector and deselector
var select = function () {
controller.addToSelection('#'+d3.select(this).attr("id"));
//controller.addToSelection(this);
d3.select(this).attr('stroke-dasharray', '5 5')
.on('click', deselect);
};
var deselect = function () {
controller.popFromSelection('#'+d3.select(this).attr("id"));
d3.select(this).attr('stroke-dasharray', '')
.on('click', select);
};
d3.select(element[0]).select('.drawarea').on('click', select);
function rdragresize(d) {
var dragx = Math.max(d.x + (dragbarw / 2), Math.min(w, d.x + width + d3.event.dx));
width = dragx - d.x;
dragbarright.attr("x", function (d) {
return dragx;
});
dragrect.attr("width", width);
dragbarright.attr("x", dragx);
dragbartop
.attr("width", width - dragbarw)
dragbarbottom
.attr("width", width - dragbarw)
}
function ldragresize(d) {
var oldx = d.x;
//Max x on the right is x + width - dragbarw
//Max x on the left is 0 - (dragbarw/2)
d.x = Math.max(0, Math.min(d.x + width - (dragbarw / 2), d3.event.x));
width = width + (oldx - d.x);
dragbarleft
.attr("x", function(d) { return d.x - (dragbarw / 2)-translatex; });
dragrect
.attr("x", function(d) { return d.x-translatex; })
.attr("width", width);
dragbartop
.attr("x", function(d) { return d.x + (dragbarw/2)-translatex; })
.attr("width", width - dragbarw)
dragbarbottom
.attr("x", function(d) { return d.x + (dragbarw/2)-translatex; })
.attr("width", width - dragbarw)
}
function tdragresize(d){
var oldy = d.y;
d.y = Math.max(0, Math.min(d.y + height - (dragbarw / 2), d3.event.y));
height = height + (oldy - d.y);
dragbartop
.attr("y", function(d) { return d.y - (dragbarw / 2)-translatey; });
dragrect
.attr("y", function(d) { return d.y-translatey; })
.attr("height", height);
dragbarleft
.attr("y", function(d) { return d.y + (dragbarw/2)-translatey; })
.attr("height", height - dragbarw);
dragbarright
.attr("y", function(d) { return d.y + (dragbarw/2)-translatey; })
.attr("height", height - dragbarw);
}
var bdragresize=function(d){
var dragy = Math.max(d.y + (dragbarw/2), Math.min(h, d.y + height + d3.event.dy));
//recalculate width
height = dragy - d.y;
//move the right drag handle
dragbarbottom
.attr("y", function(d) { return dragy - (dragbarw/2) });
//resize the drag rectangle
//as we are only resizing from the right, the x coordinate does not need to change
dragrect
.attr("height", height);
dragbarleft
.attr("height", height - dragbarw);
dragbarright
.attr("height", height - dragbarw);
}
var dragmove=function(d) {
if (scope.moveable==="true") {
console.log("COMES HERE TOO!");
d.x = Math.max(0, Math.min(w - width, d3.event.x));
d.y = Math.max(0, Math.min(h - height, d3.event.y));
d3.select(dragrect[0].parentNode).attr("transform","translate("+ d.x+","+ d.y+")");
translatex= d.x;
translatey= d.y;
}
}
scope.popDialog=function()
{
var newText=angular.element('<editabletext x="'+(scope.x+scope.rectwidth/2-scope.rectwidth/10)+'" y="'+scope.y+scope.rectheight/5+'" height="'+scope.rectheight/5+'" width="'+scope.rectwidth/5+'" text="Hello!!"></editabletext>');
element.append(newText);
$compile(newText)(scope);
}
function stopPropagation()
{
d3.event.sourceEvent.stopPropagation();
}
var dragr = d3.behavior.drag().origin(Object).on("drag", rdragresize).on("dragstart",stopPropagation);
var dragl=d3.behavior.drag().origin(Object).on("drag",ldragresize).on("dragstart",stopPropagation);
var dragt=d3.behavior.drag().origin(Object).on("drag",tdragresize).on("dragstart",stopPropagation);
var dragb=d3.behavior.drag().origin(Object).on("drag",bdragresize).on("dragstart",stopPropagation);
var drag=d3.behavior.drag().origin(Object).on("drag",dragmove);
console.log("ATTR-MV outside the drag function: "+attr.mv);
d3.select(dragrect[0].parentNode).call(drag);
dragbarleft.call(dragl);
dragbarright.call(dragr);
dragbartop.call(dragt);
dragbarbottom.call(dragb);
}
}
},
controller:function($scope,$element)
{
this.getHeight=function()
{
return $scope.height;
}
this.getWidth=function()
{
return $scope.rectwidth;
}
this.getPosition=function()
{
return {x:scope.x,y:scop.y};
}
//$scope.$watch('fillFromParent',function(){ if ($scope.fillFromParent)$scope.rectfill=$scope.fillFromParent;});
}
};});
這是框架容器指令:
app.directive('framecontainer',function($compile){
return{
restrict:'A',
scope:{
split:'=',
mergeq:'=',
fillparam:'@',
perform:'='
},
priority:1,
replace:true,
transclude:false,
template:'<svg><frames id ="maing" stroke="#bada55" x="0" y="0" resize height="500" width="765" fill="#006600" mv="false" dialog="poptextdialog()"> </frames></svg>',
link:function(scope,element,attr)
{
scope.$watch('perform',function(){
var newFrame;
var curWidth;
var curHeight;
var curX,curY;
var newFrame;
var frameID=0;
function getRectCor(x,y,width,height)
{
return {x:(parseFloat(x)-parseFloat(width)/2),y:(parseFloat(y)-parseFloat(height)/2)};
}
if (scope.perform) {
switch (scope.perform.action) {
case 0:
angular.forEach(scope.selectionStack,function(value,i){
curWidth=100;
curHeight=100;
curX=10;
curY=10;
newFrame=angular.element('<frames data-mv="true" data-stroke="#bada55" data-x="'+curX+'" data-y="'+curY+'" data-height="'+curHeight+'" data-width="'+curWidth+'" data-fill="#FFFFFF" id="elem'+frameID+'" ></frames>');
frameID=frameID+1;
console.log("value is "+value);
$(value).append(newFrame);
$compile(newFrame)(scope.$new(true));
});
break;
}
}
});
var firstFrame='<g frame id ="maing" stroke="#bada55" x="0" y="0" resize height="500" width="765" fill="#006600" mv="true" dialog="poptextdialog()"> </g>';
element.append(firstFrame);
$compile(firstFrame)(scope);
},
controller:function($scope,$element)
{
$scope.selectionStack=[];
var indexSelectionStack;
this.addToSelection=function(s){
$scope.selectionStack.push(s);
console.log($scope.selectionStack);
};
this.popFromSelection=function(s){
var index=$scope.selectionStack.indexOf(s)
if (index>-1){
$scope.selectionStack.splice(index,1);
}
};
$scope.$watch('fillparam',function(){
angular.forEach($scope.selectionStack,function(value,index){
d3.select(value).select("rect").attr("fill",$scope.fillparam);
});
});
}
};});
抱歉,這個龐大的帖子和超網狀代碼。 我是AngularJS和d3的新手。
問題解決了。 雖然這可能不是一般問題,但我認為這將有助於將來發布答案。 這個錯誤非常簡單。 拖動事件冒泡到最頂層的父框架。 因此,更改拖動功能以調用以下解決了問題:
var drag=d3.behavior.drag().origin(Object).on("drag",dragmove).on("dragstart",stopPropagation);
stopPropagation函數可防止拖動事件冒泡DOM。 謝謝大家指點我正確的方向!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.