我在线制作棋盘游戏的网络界面.我想用Snap.load加载Snap.svg地图,即异步.
加载后,我想将一个监视添加到作用域的属性,并根据属性(这是一个对象)向地图添加一些颜色.我的代码基本上是这样的:
.controller('GameCtrl', [
'$scope'
'$routeParams'
'GameService'
(
$scope
$routeParams
GameService
) ->
$scope.game = GameService.get($routeParams.gameId)
$scope.map = Snap("#map")
Snap.load("img/classical.svg", (data) ->
console.log "Loaded map!"
data.select("#provinces").attr
style: ""
provinces = data.selectAll("#provinces path")
for province in provinces
province.attr
style: ""
fill: "#FFFFFF"
"fill-opacity": "0"
$scope.map.append(data)
deregisterWatch = $scope.$watch('game', ->
console.debug "Game loaded!", $scope.game.data.Id
for provinceName,unit of $scope.game.data.Phase.Units
provinceName = provinceName.replace '/', '-'
province = $scope.map.select("##{provinceName}")
province.attr
style: ""
fill: powers[unit.Nation].colour
"fill-opacity": "0.8"
deregisterWatch()
)
)
])
现在,问题是我想将地图移动到它自己的“类”或文件,但它必须以某种方式知道$scope,以便能够在加载后设置手表.
我的第一个天真的方法是提取地图并传递范围:
define([
'snap'
], (
Snap
) ->
'use strict'
Map = ($scope, selector, svgPath) ->
that = {}
that.provinces = {}
...
that.snap = Snap(selector)
Snap.load(svgPath, (data) ->
console.log "Loaded map in Map!"
data.select("#provinces").attr
style: ""
provinces = data.selectAll("#provinces path")
for province in provinces
that.provinces[province.attr("id")] = province
province.attr
style: ""
fill: "#FFFFFF"
"fill-opacity": "0"
that.snap.append(data)
deregisterWatch = $scope.$watch('game', ->
console.debug "Game loaded!", $scope.game.data.Id
for provinceName,unit of $scope.game.data.Phase.Units
provinceName = provinceName.replace '/', '-'
that.colourProvince(provinceName, that.powerColors[unit.Nation].colour)
deregisterWatch()
)
)
that.colourProvince = (abbr, colour) ->
...
return that
return Map
)
但我认为必须采取更有棱角的方式来做到这一点.我应该做一个指示吗?还有其他建议吗?
解决方法:
你应该考虑写一个指令.
指令旨在封装可重用组件,尤其是图形组件.
define [
'app' # or use any other way to get to your Angular module.
'snap'
], (app, Snap) ->
app.directive 'awesomeMap', ->
# directive template: will be injected into controller ($element variable)
template: "<svg></svg>"
# will remplace hosting element
replace: true
# applicable as element and attribute
restrict: 'EA'
# here the "parameters" of your directive: can be parsed from HTML, or bound to parent scope (my example).
scope:
svgPath: '=?path'
# controller
controller: AwesomeMap
class AwesomeMap
# Controller dependencies: scope and HTML element
@$inject: ['$scope', '$element']
# Controller constructor: bind methods and attributes to current scope
#
# @param scope [Object] directive scope
# @param element [Object] root element's HTML (angular.element)
constructor: (@scope, element) -
@snap = Snap(element[0])
Snap.load(@scope.svgPath, (data) ->
console.log "Loaded map in Map!">
# do your stuff here !
您的指令需要在Angular的模块初始化之后加载(不要忘记在某处需要它),您只需在HTML中使用它.
<div data-ng-controller="AParentScope">
My awesome map <awsome-map data-path="scopeAttribute"></awsome-map>
(使用Angular的CoffeeScript类是一个挑战,我很高兴找到别人尝试:))