我的页面之一需要加载SVG文件,然后进行编辑。现在,这是一个巨大的指令,可以处理SVG整体以及与形状相关的每个交互。我想将其拆分,以便可以将形状的交互放入单独的指令中。
这是我现在所做的:
<svg-canvas
fills="fills"
src="{{svgImageUrl}}
selected-shape="selectedShape"
on-drop-fill="addFill(pathId, fill)"
/>
该指令既管理父对象(SVG),又管理每个单个子形状的交互。例如,我向每个形状添加了一个单击处理程序,并在范围上更新了选定的形状。我深入观察填充的变化,查找正确的形状并应用它。
我宁愿做这样的事情:
<svg-canvas src="{{svgImageUrl}}>
<svg-each-shape as="shape" svg-click="selectShape(shape)" svg-fill="fills[shape.id]" on-drop-fill="addFill(shape, fill)"/>
</svg-canvas>
从概念上讲,能够为svg-click,svg-fill等创建单独的指令似乎更清洁。如果斜视,这很像ng-repeat。 Ng-repeat允许您将内容的交互与父对象分开。最大的区别在于,该指令永远都不应放在DOM中。我只想要一种将指令分别添加到每个路径的方法。
是否可以使用包含关系将集合中的对象(形状)链接到子范围,以便我可以使用它?没有将其放入DOM?怎么样?
最佳答案
您需要做的就是在父级中设置transclude: true
,并为每个子级调用一次transclude函数,并在范围上设置适当的属性,以便子级指令可以使用。
这是一个简化的示例:svgCanvas.js
.directive('svgCanvas', function() {
return {
restrict: 'AE',
transclude: true,
compile: function(tElement, tAttrs, transclude) {
return function(scope, el, attrs) {
return link(scope, el, attrs, transclude)
}
}
}
function link(scope, el, attrs, transclude) {
// ... other code
// after loaded
function afterLoaded() {
el.find("rect, path").each(function() {
var childScope = scope.$new()
// child directives can read ._path to work their magic
childScope._path = $(this)
transclude(childScope, function(clone) {
// You don't have to do anything in here if you don't want
// transclude runs all child directives
})
})
}
}
})
这是内部指令之一的示例:svgClick.js
.directive('svgClick', function() {
return {
restrict: 'A',
link: function(scope, el, attrs) {
var $path = scope._path
$path.click(function() {
scope.$apply(function() {
scope.$eval(attrs.svgClick)
})
})
}
}
})
这是您将如何使用它
<svg-canvas src="{{svgImageUrl}}">
<svg-each-path
svg-click="selectPath(path.id)"
/>
</svg-canvas>