第6回: 正方形の代わりに画像を表示
2012/03/25
前回はCoffeeScriptでAjaxのコードを書く話をしました。
今回は趣向を変えて、読者の方からのメールにお答えしようと思います。以下、メールからの抜粋です。
CoffeeScriptについては勉強しようと思っていたところへ
CoffeeScript入門が掲載され、大変タイムリーでした。
今後の展開が楽しみです。ところで、本記事では、blockを描画していますが、これを
png等のイメーファイルに置き換えてみようと思い、
ネットで調べたり、自分で推測してプログラムを変更してみましたが、
どうもうまくいきません。
いい質問です:)
。ちょっとやってみましょうか。
その前に
いまdiv要素を追加しているところをimg要素に書き換えればよさそうですね。でもその前に、現行のソースコードを少し手直ししておきましょう。いまはこうなっています:
$ -> $("div#canvas").dblclick (e) -> [x, y] = positionOfNewBlock(e) $.post '/blocks', block: { x: x, y: y }, (block_id) -> block = $("<div class='block' style='left: #{x}px; top: #{y}px;' />"). data("blockId", block_id). draggable(containment: "parent").css(position: "absolute") $(e.target).append(block) $("div.block").draggable(containment: "parent").css(position: "absolute") $(document).on "dragstop", "div.block", (e) -> block = $(e.target) blockId = block.data("blockId") x = parseInt(block.css("left")) y = parseInt(block.css("top")) $.ajax "/blocks/#{blockId}", type: "PUT", data: { block: { x: x, y: y } } positionOfNewBlock = (e) -> canvas = $(e.target) x = e.pageX - canvas.position().left y = e.pageY - canvas.position().top [x, y]
5-7行目を次のように修正します:
block = $("<div />"). addClass("block"). css(left: "#{x}px", top: "#{y}px"). data("blockId", block_id). draggable(containment: "parent"). css(position: "absolute")
$("div class='block' />")
と書く代わりに $("<div />").addClass("block")
と書いています。
また、$("div style='left: #{x}px; top: #{y}px;' />")
と書く代わりに $("<div />").css(left: "#{x}px", top: "#{y}px")
と書いています。
このようにclass属性やstyle属性は、文字列として埋め込まずに後からメソッドで設定することもできます。
正方形の代わりに画像を表示する
では、メールへの回答です。
本連載を今後も読み続ける方は、以下の修正を行う前に、現行のソースコードのバックアップを取ってください。次回以降は、この時点でのソースコードを起点にして話が進みます。
app/views/top/index.html.erb
を修正。
<div id="canvas"> <% @blocks.each do |block| %> <%= image_tag("rails.png", data: { :"block-id" => block.id }, style: "left: #{block.x}px; top: #{block.y}px") %> <% end %> </div>
3行目の content_tag(:div, nil, class: "block"
を image_tag("rails.png"
に変更しています。
app/assets/stylesheets/top.css.scss
を修正。
div#canvas { position: relative; width: 400px; height: 400px; background-color: silver; -moz-user-select: none; -khtml-user-select: none; -webkit-user-select: none; -o-user-select: none; img { position: absolute; cursor: pointer; } }
img要素にスタイルを指定しています。-moz-user-select
などの指定は、キャンバスをダブルクリックしたときに画像が選択されないようにするためのものです。
app/assets/javascripts/top.js.coffee
を修正。
$ -> $("div#canvas").dblclick (e) -> [x, y] = positionOfNewBlock(e) $.post '/blocks', block: { x: x, y: y }, (block_id) -> block = $("<img />"). attr("src", "assets/rails.png"). css(left: "#{x}px", top: "#{y}px"). data("blockId", block_id). draggable(containment: "parent"). css(position: "absolute") $(e.target).append(block) $("div#canvas img").draggable(containment: "parent").css(position: "absolute") $(document).on "dragstop", "div#canvas img", (e) -> block = $(e.target) blockId = block.data("blockId") x = parseInt(block.css("left")) y = parseInt(block.css("top")) $.ajax "/blocks/#{blockId}", type: "PUT", data: { block: { x: x, y: y } } positionOfNewBlock = (e) -> canvas = $(e.target) x = e.pageX - canvas.position().left y = e.pageY - canvas.position().top [x, y]
変更箇所は4点です:
- 5行目の
$("<div />")
を$("<img />")
に変更。 - 6行目の
addClass("block")
をattr("src", "assets/rails.png")
に変更。 - 13行目の
$("div.block")
を$("div#canvas img")
に変更。 - 15行目の
"div.block"
を"div#canvas img"
に変更。
img要素のsrc
属性を指定するのにattr
メソッドを使用している点に着目してください。jQueryはclass
属性とstyle
属性とdata-*
を特別扱いしていて、それぞれにaddClass
とcss
とdata
という専用メソッドを用意しています。それ以外の属性については、attr
メソッドの第1引数に属性名を指定することで値を参照したり変更したりできます。
では、動作確認しましょう。ブラウザを再読込してから、ページ上の灰色の部分を何度かダブルクリックすると次のような表示になります。
画像をドラッグして位置を変更できる点と、変更後にブラウザを再読込して画像の位置が変わらない点についても確認してください。