Posted at

RailsでAjaxを使って簡単なお絵かきをしたい


初めに

Ajaxについて理解をしたいということでRailsで簡単なお絵かきアプリを作ってみる

機能的には20x20のマスがあってそこをクリックすると色が変わって簡単なお絵かきができる感じ


とりあえずアプリ作成とコントローラー作成

rails new oekaki

rails g controller paints


indexとcreateを作成

今回はindexでお絵かきをする感じ

ボタンが押されたらcreateアクションが非同期で行われ、その時どの場所のボタンが押されたかわかるようidも送る

ボタンが押されたらcreate.js.erbが実行されるのでそこにクリックしたボタンのcssを変更するコードを書く。

controllerはこんな感じ


paints_controller.rb

class PaintsController < ApplicationController

def index
end

def create
@id = params[:id]
end

end


そしてcreate.js.erbがこんな感じ


create.js.erb

$("#<%= @id %>").css('backgroundColor', 'black');


実際にお絵かきを行うindex.html.erbのコードは


index.html.erb


<div class="block">
<% 400.times do |i| %>
<%= link_to "", "/paints/create/#{i}", remote: true, class: "paint-block", id: "#{i}" %>
<% end %>
</div>

まず

はwidth: 800px; height: 800px;を指定して800pxx800pxのパネルにしている。

この上にボタンを敷き詰める。

そのために40px x 40pxのボタンを400個敷き詰める形にしている。

blockとpaint-blockのcssはこんな感じ


application.css

 .block {

width: 800px;
height: 800px;
}

.paint-block {
float: left;
background-color: red;
width: 40px;
height: 40px;
}


これで真っ赤のパネルができる。

それでクリックをするをボタンが黒くなりお絵かきができる。

paint.png


機能追加

色を変更できるようにする。

とりあえず色変更のボタンを作りボタンを押したらcolorアクションが実行され@@colorというクラス変数に色が設定されるようにする

colorアクションはこんな感じ


paints_controller.rb

def color 

@@color = params[:color]
if @@color.nil?
@@color = "black"
end
end

色のボタンを押すとparams[:color]が送られて@@colorに代入される感じ

create.js.erbに


create.js.erb

$("#<%= @id %>").css('backgroundColor', '<%= @@color %>');


こう書いたら@@colorがわからないと怒られたので

createアクションに


paints_controller.rb

def create 

@color = @@color
@id = params[:id]
end

このようにしてcreate.js.erbを


create.js.erb

$("#<%= @id %>").css('backgroundColor', '<%= @color %>');


こうした

色を選択するボタンだがとりあえずindexに@all_colorという値を


paints_controller.rb

    def index

@all_color = ["blue","indigo","violet","red","orange","yellow","green"]
respond_to do |format|
format.html
format.js
end
end

こんな感じで設定して

viewに


index.html.erb

<div class="color">

<% @all_color.each do |color| %>
<%= link_to "", "/paints/color/#{color}", remote: true, class: "select-color #{color}",method: :post %>
<% end %>
</div>


このように設定。

これで七色のボタンが作れる

ボタンのcssはこんな感じ


application.css

 .select-color {

width: 60px;
height: 40px;
float: left;
text-align: center;
line-height: 40px;
}

.blue {
background-color: blue;
}

.violet {
background-color: violet;
}

.indigo {
background-color: indigo;
}

.red {
background-color: red;
}

.orange {
background-color: orange;
}

.yellow {
background-color: yellow;
}

.green {
background-color: green;
}


これで完成。

paint_new.png

完成コードはこんな感じです

コントローラー


paints_controller.rb

class PaintsController < ApplicationController

def index
@all_color = ["blue","indigo","violet","red","orange","yellow","green"]
@@color = "black"
respond_to do |format|
format.html
format.js
end
end

def create
@color = @@color
@id = params[:id]
end

def color
@@color = params[:color]
if @@color.nil?
@@color = "black"
end
end

end


viewは


index.html.erb


<div class="color">
<% @all_color.each do |color| %>
<%= link_to "", "/paints/color/#{color}", remote: true, class: "select-color #{color}",method: :post %>
<% end %>

</div>

<div class="clear"></div>

<div class="block">
<% 400.times do |i| %>
<div class="paint-html">
<%= link_to "", "/paints/create/#{i}", remote: true, class: "paint-block", id: "#{i}", method: :post %>
</div>
<% end %>
</div>



create.js.erb

$("#<%= @id %>").css('backgroundColor', '<%= @color %>');



routes.rb

Rails.application.routes.draw do

# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
get '/paints/index'
post '/paints/create/:id', to: 'paints#create'
post '/paints/color/:color', to: 'paints#color'
end

こんな感じです。


課題

色の変更を行うとき最初は


index.html.erb

<%= link_to "", "/paints/color", remote: true, class: "select-color #{color}", method: :post, color: "blue" %>


みたいにパラメータを color: "blue"と書いて渡そうとしたがうまくいかなかった。

remote: trueにしているとうまく反応しないのかな?

あとクラス変数を使わずに色変更をしたい場合どんな実装の仕方があるのだろう…

クラス変数を使ったのはいろいろ試したがうまくいかずとりあえずクラス変数を使えばその値をほかのアクションでも使えそうだったからでほかの方法も考えてみたい。


おわり

とりあえずお絵かきアプリを作ってみた。

何かもっとこうしたらよいというのがあればご指摘いただけるとありがたいです。