データ属性、つまり Object.data をスケールの生成に使用される d3 コールバックに渡そうとしています。
renderScatter: () ->
$("#render").click =>
@target.selectAll("svg").selectAll("circle")
.data(@data)
.enter()
.append("circle")
.attr("cx", (d) =>
@xScale(d[0])
)
.attr("cy", (d) -> d[1])
.attr("r", (d) ->
Math.sqrt(200 - d[1])
)
@xScale(d[0])
以下の関数を指します
xScale:
d3.scale.linear()
.domain([ 1, d3.max(@data, (d) -> d[1]) ])
.range([ 0, 200 ])
Object.data
配列の配列、つまり [[1,2],[3,4]] を指しますが、正しく設定されたスケーリング情報で @renderScatter() を呼び出そうとすると、次のようなエラー メッセージが表示されます。 xScale() 内のスコープは @data を認識しません。
Uncaught TypeError: Cannot read property 'length' of undefined
完全な Coffeescript クラスを以下に示します。
class ScatterPlot
constructor: (width, height, target) ->
@confirmation = ->
console.log "scatter is working"
@data= []
@width = width || "100"
@height = height || "200"
@target = d3.select(target)
@callActions()
callActions: () ->
@generateTitle()
@generateData()
@drawScatterSvg()
@renderScatter()
@renderLabels()
generateTitle: () ->
$("#scatterButton").click =>
@target.append("h5")
.text($("#scatterName").val())
generateData: ()->
$("#generateData").click =>
if @data.length is 0
_(10).times =>
@data.push([Math.round(Math.random() * 325 + 5), Math.round(Math.random()*150 + 20)])
$("#data").text(@data)
drawScatterSvg: () ->
$("#drawSVG").click =>
console.log @target
@target.append("svg")
.attr("width", @width + "px")
.attr("height", @height + "px")
.classed("scatter", true)
renderScatter: () ->
$("#render").click =>
@target.selectAll("svg").selectAll("circle")
.data(@data)
.enter()
.append("circle")
.attr("cx", (d) =>
@xScale(d[0])
)
.attr("cy", (d) -> d[1])
.attr("r", (d) ->
Math.sqrt(200 - d[1])
)
renderLabels: ->
$("#labels").click =>
@target.selectAll("svg").selectAll("text")
.data(@data)
.enter()
.append("text")
.text( (d) ->
d[0] + "," + d[1] )
.attr("x", (d) -> d[0])
.attr("y", (d) -> d[1])
.attr("fill", "red")
xScale:
d3.scale.linear()
.domain([ 1, d3.max(@data, (d) -> d[1]) ])
.range([ 0, 200 ])
plot = new ScatterPlot("500", "200", "#scatter")