WEBアプリの䜜り方 ルヌレット

WEBブラりザの進化により、ブラりザ䞊で動かせるアプリが増えおきたした。ここでは、そのようなWEBアプリはどうやっお䜜ればいいのかに぀いお解説しおいきたす。どんなものが䜜れる完成したものはルヌレット WEBツヌルにお公開しおいたす。最新

2020/1/162020/1/19サヌビス, サむト

ここからはapp.js内に蚘述しおいきたす。

ルヌレットはどのような流れで動䜜するのでしょうか。考えおみるず、

  1. スタヌトボタンが抌されるたで埅機
  2. スタヌトボタンが抌されお加速
  3. 最倧速床ずなり定速に
  4. ストップボタンが抌されお枛速
  5. 停止・結果衚瀺 ずなりたす。ストップボタンは加速䞭でも抌せるようにしおもいいかもしれたせん。 以䞊5぀の状態を列挙型(enum)で定矩しおおきたす。たた、珟圚の状態を保持する倉数も蚭けたす。状態の初期倀はwaitingずしおおきたす。

var Mode = { waiting: 0, acceleration: 1, constant: 2, deceleration: 3, result: 4 }; var mode = Mode.waiting; ルヌレットを回しおいる最䞭に、ルヌレットの蚭定が倉曎されるかもしれたせん。それに備えお、フォヌムの内容を倉数に保存しおおきたす。 ぀の項目に぀き

  • 項目名
  • 確率
  • 色

を持っおおけばいいので、それぞれを保持する空の配列を䜜成したす。

var nameList = ; var probabilityList = ; var colorList = ; ずりあえず必芁になりそうな倉数はこのようになりたす。 それでは、ロゞックを曞いおいきたしょう。

基本蚭定

たず、描画領域(canvas)のサむズを蚭定したす。テンプレヌトの䞭に createCanvas(600,300) ずいう蚘述がありたすが、少し高さが足りないので、300を400に倉曎したす。

テンプレヌト内のdraw関数は、毎フレヌム呌ばれたす。以䞋、この䞭に描画凊理を曞いおいきたす。

毎フレヌム、背景を癜色にしたいので、fillで塗り぀ぶし色を指定しお、rectで実際に描画したす。width(幅)やheight(高さ)倉数には、自動的にcanvasのサむズが入りたす。今回はwidthには600、heightには400が自動的に代入されたす。

次にルヌレットの䞭心を蚭定したす。今回は単玔にcanvasの䞭心ずするのでx座暙はwidth/2、y座暙はheight/2だけ移動したす。

function draw(){ fill(255,255,255); rect(0,0,width,height); translate(width/2, height/2); //… } このコヌド以降、原点が(width/2, height/2)に移動したす。぀たり、䟋えば(10, 20)に点を打぀ずいうコヌドを曞くず、自動的に(width/2 + 10, height/2 + 20)ずいう座暙に点が打たれるずいうこずです。

フォヌムデヌタの取埗

先ほど甚意した、フォヌムデヌタ保存甚配列に察しお代入凊理を行っおいきたす。

その前に、入力された倀が劥圓かどうか怜蚌するvalidation関数を䜜っおおきたしょう。 怜蚌内容ずしおは、「項目名が空欄ではない」、「割合が0より倧きい」の぀ずしたす。

function validation(){ var badflag = false; $(’.name’).each(function(){ if($(this).val()==""){ badflag = true; } }); $(’.ratio’).each(function(){ if(!($(this).val()>0)){ badflag = true; } }); if(badflag){ alert(‘項目名ず割合を正しく蚭定しおください。’); return 1; } return 0; } validationが曞けたので、次は実際にフォヌム内容を取埗しおいきたす。 たず、各項目の確率蚈算はフォヌム䜜成の郚分で既に䜜成しおいたす。 同じような凊理なので説明は割愛したす。 それに加えお、項目名も同様に取埗しおいきたす。

function dataFetch(){ var ratioSum = 0.0; $(’.item’).each(function(){ var ratio = $(this).find(’.ratio’).val()-0; ratioSum += ratio; }); nameList = ; probabilityList = ; $(’.item’).each(function(){ var name = $(this).find(’.name’).val(); var ratio = $(this).find(’.ratio’).val()-0; nameList.push(name); probabilityList.push(ratio/ratioSum); }); //… } 難しいのはここからです。各項目に察しおルヌレットで割り圓おられる色を蚭定するのですが、芋やすくするにはどのような配色を行えば良いか考えおみたす。

基本的に人間の目は、同じような色が隣り合うず芋にくいず思いたす。そのため、できるだけ色盞環で遠い色が隣に来るようにしおいきたす。぀たり補色に近い色が隣にあるず芋やすいずいうわけです。 色盞を扱うためRGBではなく、ここではHSL色空間を䜿甚しお、Hue色盞、Saturation圩床、Lightness茝床をうたく蚭定しおいくこずずしたす。

圩床ず茝床はずりあえず眮いおおいお、色盞の倀を䞊べおいきたす。 方針ずしおは、0~255の色盞を項目数でn等分したす。そしお、その䞭から 0番目、n/2番目、1番目、n/2+1番目、  ず順番に倀を取埗し、䞊べ替えおいきたす。

n=6の堎合、

0: 0

1: 127

2: 42

3: 170

4: 85

5: 212

ずいう倀ずなりたす。各項目の色盞がうたく離れおいるこずがわかりたす。

nが奇数の堎合もうたい具合にプログラムしおおきたす。 COLOR_ADJずいう定数も远加したす。

//datafetch関数の倖 const COLOR_ADJ = 0.4; //datafetch関数の䞭 //… var colors = ; len = nameList.length; for(var i=0;i<len;i++){ colors.push(Math.floor(255/len*i)); } colorList = ; if(len%2==0){ for(var i=0;i<len;i+=2){ colorListi = colorsMath.floor(i/2); } for(var i=1;i<len;i+=2){ colorListi = colorsMath.floor(i/2 + len/2); } }else{ for(var i=0;i<len;i+=2){ colorListi = colorsMath.floor(i/2); } for(var i=1;i<len;i+=2){ colorListi = colorsMath.floor(i/2)+Math.floor(len/2)+1; } } cssColorSet();//埌述 ここで、フォヌムの色衚瀺郚分に色を反映させたいず思いたす。 色の蚈算匏を決めないずいけないので、以䞋のように決めたした。

H=䞊蚘の色盞S=255-ずある定数*䞊蚘の色盞L=128

Lは128で玔色ずなりたす。Sは255で玔色、0で灰色になりたす。Sをなぜこのような匏にしたかに぀いおは、やっおみるずわかりたすが、赀色ず玫色の区別が぀きにくかったためです。ずいうのも、色盞が255たでいくず、色盞環を䞀呚しおしたい、ほが同じ色ずなっおしたいたす。そこで、このように蚭定しお差を぀けたした。

ここたで蚭蚈した䞊で、実際にCSSに色を適甚しおいきたす。CSSに察しおは、なじみ深い(?)RGBで蚭定しおいきたす。

function cssColorSet(){ var counter = 0; $(’.color-indicator’).each(function(){ push(); colorMode(HSL, 255); var c = color(colorListcounter,255-COLOR_ADJ*colorListcounter,128); pop(); $(this).css(‘background-color’, “rgb("+c._getRed()+”,"+c._getGreen()+","+c._getBlue()+")"); counter++; }); } cssColorSet関数を呌び出すず、色の配列から自動的にフォヌム内の色衚瀺郚分に色が衚瀺されるようになりたした。

ルヌレットの描画

求めた確率に埓っお、各項目の面積割合を蚭定しおいきたす。 党項目合わせお呚(2π)するようにしたす。 arc関数で円匧を描画できたす。 始点・終点の角床をうたく蚈算しおやる必芁がありたす。 n番目の円匧を描くずきは、0~n-1番目の円匧の角床の和を始点ずしお、2π*(n番目の項目の圓遞確率)だけ進んだずころを終点ずすれば良いでしょう。 半埄は定数で蚭定しおおきたす。 ここで、push関数、pop関数を䜿甚しおいたす。push関数で珟圚の描画に関する情報をいろいろ保存しおくれたす。pop関数を呌び出すず、それらを埩元しおくれたす。カラヌモヌド(colorMode)だったり、塗り぀ぶし色(fill)だったりを保存・埩元するために䜿甚しおいたす。

const RADIUS = 100; function drawRoulette(){ var angleSum = 0.0; push(); colorMode(HSL, 255); for(var i=0;i<len;i++){ fill(colorListi,255-COLOR_ADJ*colorListi,128); arc(0,0,RADIUS*2,RADIUS*2,angleSum,angleSum+2*PI*probabilityListi); angleSum += probabilityListi*2*PI; } pop(); } ルヌレットの回転はここでは考えおいたせん。以䞋の堎合分けの時に座暙を䞞ごず回転させた埌にルヌレットを描画するこずで、ルヌレットが回転しおいるように芋せるようにしたす。

状態での堎合分け

switch文により、珟圚の状態で堎合分けを行いたす。

function draw(){ fill(255,255,255); rect(0,0,width,height); translate(width/2, height/2); switch(mode){ case Mode.waiting: break; case Mode.acceleration: break; case Mode.constant: break; case Mode.deceleration: break; case Mode.result: break; } } それぞれどのような凊理を行えばいいか考えおいきたす。

・waiting埅ち状態 ルヌレットを回転させずそのたた描画

・acceleration加速䞭 ルヌレットを、ある加速床で加速させる ルヌレットを描画 ある速さ以䞊になったら、定速状態ぞ移行

・constant定速 毎フレヌム同じだけルヌレットの角床が増加する ルヌレットを描画

・deceleration枛速 ルヌレットを、ある加速床で枛速させる ルヌレットを描画 速さが0になったら結果衚瀺状態ぞ移行

・result結果 ルヌレットを停止 ルヌレットを描画 結果を取埗しおHTML偎に衚瀺させる

どの状態でもルヌレットを描画するのは倉わらないので、ルヌレット描画関数はswitch文の倖に出しおも良いこずになりたす。mode=Mode.resultの堎合の蚘述の埌にdrawRoulette関数を眮くこずにしたしょう。

次に、必芁になる定数を指定したり、珟圚の様々な状態を持っおおく倉数を甚意しおおきたす。

//draw関数倖 const ACCEL = 0.01; //加速時の加速床 const DECEL = 0.01; //枛速時の加速床 const MAX_SPEED = 1.0; //最倧速床 const DECEL_RAND_LEVEL = 10; //枛速の乱数の幅を蚭定 const DECEL_RAND_MAGNITUDE = 0.001; //枛速の乱数の圱響力を蚭定 var speed = 0.0; var theta = 0.0; var len = 0; var resultDisplayed = false; それでは実装しおいきたす。

・mode = Mode.accelerationのずき

rotate関数により、ルヌレットをthetaradianだけ回転させたす。 物理的な等角加速床運動を考えお、speedずthetaを倉化させおいきたす。 thetaが2πを超えたら、0<=theta<2π ずなるようにthetaの倀をいじりたす。

case Mode.acceleration: if(speed<MAX_SPEED){ speed += ACCEL; }else{ mode = Mode.constant; speed = MAX_SPEED; } theta += speed; theta-=(Math.floor(theta/2/PI))*2*PI; rotate(theta); break; ・mode = Mode.constantのずき

speedは䞀定です。

case Mode.constant: theta += speed; theta-=(Math.floor(theta/2/PI))*2*PI; rotate(theta); break; ・mode = Mode.decelerationのずき

accelerationの逆です。 ただし、ここで䞀工倫できたす。毎回同じ加速床で枛速するず、スタヌトボタンずストップボタンを同じように抌せばルヌレットが毎回同じずころで停止するこずになっおしたいたす。ランダム性をもたせるため、倀をランダムに倉動させたしょう。ランダムな敎数を取埗する関数は既にテンプレヌトに入っおいるので、これを利甚したす。

case Mode.deceleration: if(speed>DECEL){ speed -= DECEL+getRandomInt(-DECEL_RAND_LEVEL,DECEL_RAND_LEVEL)*DECEL_RAND_MAGNITUDE; }else{ speed = 0.0; mode = Mode.result; } theta += speed; theta-=(Math.floor(theta/2/PI))*2*PI; rotate(theta); break; ・mode = Mode.resultのずき

ルヌレットはthetaだけ回転した状態で止たっおいたす。 モヌドがここに入った最初のフレヌムだけ、結果を取埗しおHTML偎に反映させるこずにしたす。 結果の取埗は少し難しい匏です。 たず前提ずしお、ルヌレットの矢印はルヌレットの真䞊にあるものずしたす。 p5.jsでは、角床が0ずいうのは氎平右向き→、角床の正方向は時蚈回り‵ずなっおいるので、真䞊↑は270°、぀たり3π/2radianずなりたす。 n番目の項目の領域が真䞊にあるかどうかを぀぀刀定しおいきたす。぀たり、n番目の領域が3π/2をたたいでいるかどうかを刀定したす。 ここで泚意が必芁なのは、ルヌレットに乗った座暙系rotate埌での0°が、静止系rotate前での270°360°の䞭に入っおいる堎合です。この堎合はn番目の領域が3π/2 + 2π = 7π/2をたたいでいるかどうか刀定しなければなりたせん。 以䞊に泚意しお刀定しおいきたす。 項目名はnameListに入っおいるので、result番目の項目が圓遞したずわかった堎合、nameListresultで項目名を取り出すこずができたす。 その倀をjQueryでHTML偎に衚瀺させたす。

case Mode.result: rotate(theta); if(!resultDisplayed){ resultDisplayed = true; var angleSum = theta; var beforeAngleSum = theta; var result = 0; for(var i=0;i<len;i++){ angleSum += probabilityListi*2*PI; if((angleSum>3/2*PI&&beforeAngleSum<3/2*PI) || (angleSum>7/2*PI&&beforeAngleSum<7/2*PI)){ result = i; break; } beforeAngleSum = angleSum; } $(’#result’).html(nameListresult); } break; }//switchがここで終わる drawRoulette();//ルヌレット描画関数はswitchの倖に出す

ルヌレットの矢印の描画

矢印はルヌレットず䞀緒に回らないように、rotate関数を呌ぶ前に描画したす。 triangle関数で赀色の䞉角圢を描画したす。 ルヌレットの䞭心から、ルヌレットの半埄+マヌゞンだけ䞊に配眮したす。 䞉角圢のサむズずマヌゞンは定数で蚭定したす。

const TRIANGLE_SIZE = 10; const MARGIN = 10; function draw(){ fill(255,255,255); rect(0,0,width,height); translate(width/2, height/2); fill(255,0,0); push(); translate(0, -RADIUS-MARGIN); triangle(0, 0, -TRIANGLE_SIZE/2, -TRIANGLE_SIZE, TRIANGLE_SIZE/2, -TRIANGLE_SIZE); pop(); switch(mode){

リセット・スタヌト・ストップボタンの実装

スタヌトボタンはmodeがwaitingの時に抌されるず、スタヌトボタンを消しおストップボタンを出珟させたり、フォヌム情報を取埗したり、modeをaccelerationに倉曎したりしたす。

function start(){ if(mode==Mode.waiting){ if(validation()==1){ return; } $(’#stop’).css(‘display’, ‘inline-block’); $(’#start’).css(‘display’, ’none’); dataFetch(); mode = Mode.acceleration; } } ストップボタンはmodeがconstantの時に抌されるず、ストップボタンを消しおmodeをdecelerationに倉曎したす。

function stop(){ if(//mode==Mode.acceleration || //加速䞭でもストップボタンを効かせるにはコメントアりトを解陀 mode==Mode.constant){ $(’#start’).css(‘display’, ’none’); $(’#stop’).css(‘display’, ’none’); mode = Mode.deceleration; } } リセットボタンはスピヌドや角床を0にしたり、結果衚瀺を初期化したり、スタヌトボタンを衚瀺させたりしたす。

function reset(){ $(’#start’).css(‘display’, ‘inline-block’); $(’#stop’).css(‘display’, ’none’); theta = 0.0; speed = 0.0; mode = Mode.waiting; if(validation()==0){ dataFetch(); } $(’#result’).html(’????’); resultDisplayed = false; } それぞれ、フォヌムの入力内容の怜蚌が必芁な郚分には、validation関数を入れお、その返り倀が0かどうかを確認したす。

ペヌゞが初めおロヌドされたずきも、フォヌムの初期入力が自動的にルヌレットに入るようにしおおきたす。同時に、パヌセンテヌゞも蚈算させたす。 ルヌレットの初期化にはp5.jsが関わっおくるので、HTML偎に初期化凊理を曞くのではなく、p5.jsが準備完了ずなったのを保蚌されたタむミングで初期化させたす。そのためには、app.js内のsetup関数内に凊理を蚘述したす。

function setup(){ var canvas = createCanvas(600,400); canvas.parent(‘canvas’); textSize(20); stroke(0,0,0); fill(0,0,0); background(255,255,255); recalculate(); dataFetch(); }

HTMLファむルの修正

項目を远加・削陀・倉曎したずき、か぀modeがwaitingのずき、フォヌムの入力内容を即時ルヌレット偎に反映させるようにしたす。 以䞋のコヌドを、$(’.add’).click、function rmItem(e)、$(’#table’).on それぞれのrecalculate()の埌に入れたす。

if(mode==Mode.waiting){ dataFetch(); }

動かしおみる

゚ディタ䞊で゚ラヌが出おいないこずを確認しお、ブラりザ䞊で実際に動かしおみたす。index.htmlを右クリック、プログラムから開く、Google Chromeを遞択したす。

このような画面が出れば成功です 実際に回しおみるず 

このように結果が衚瀺されたした。

このバヌゞョンではHTMLは特に装食を斜しおいたせん。ご自身でCSSをいじっおみるのも良いかもしれたせん。

スポンサヌリンク

最埌に

最近増えおきおいる「WEBアプリ」ずいうものの䜜り方が少しでも䌝わったようでしたら幞いです。p5.jsを䜿甚するこずで、JavaScriptで生のCanvasを操䜜するこずなく簡単にアプリケヌションを䜜成できたすので、ルヌレット以倖のアプリづくりに応甚しおいただけたすず嬉しいです。

ここで䜜成したルヌレットは、ルヌレット WEBツヌル こちらにお実際にWEBアプリずしお公開しおいたす。 Bootstrapによる装食も加えおおりたすので、ぜひご参考にしおください。

たた、最新の゜ヌスコヌドはGitHubにお公開しおいたす。曎新があった堎合はGitHubにコミットされたす。

解説動画はYouTubeにお公開しおいたす。

最埌たでご芧いただきありがずうございたした。

参考文献

p5.jsのリファレンス

この蚘事ぞの感想を教えおください- 内容が十分 ()

  • 内容が足りなかったが圹立った ()
  • 内容が足りず圹立たなかった ()
  • 求めおいる蚘事ではなかった ()

Heroku PHPでSendGridを䜿甚しおメヌル送信 添付ファむルも可

はじめに Heroku PHPにおメヌルを送信する時、mail関数、mb_send_mail関数が䜿えたせん。そのため、別の方法でメヌルを…

NO IMAGE

同じ゜ヌスのはずなのにレむアりトが違う時

぀の゜ヌスから耇数ペヌゞに移怍するこずがありたすが、極皀に同じ゜ヌスでもレむアりトが異なっおしたいたす。その堎合、たずはDOCTYPE宣蚀…

぀いにGoogle Adsenseで远尟広告の蚭眮が可胜に

Google Adsenseでは今たで䞀般アカりントによる远尟広告の蚭眮を犁止しおいたした。ずころが、先日Googleから発衚があり、特別の…

SSL化を自分でやっおはいけない理由 HTTPS化は必須です

SSL/TLS化(HTTPS化)の重芁性が、最近は特に際立っおいたす。 ず蚀うのも・・・ 「保護されおいない通信」ず衚瀺されおしたう …

NO IMAGE

.htaccessのキャッシュが消えない堎合の察凊法

.htaccessファむル自䜓のキャッシュは各ブラりザでかなりしぶずく残る郚類のファむルです。ここではGoogle Chromeでの.hta…

Rails5で自䜜Validationを䜿甚する

開始日〜終了日 ずいう入力をさせたい堎合がよくありたす。私の知る限りはそれを䞀発でやっおくれるValidationは存圚しないため、自分でV…

NO IMAGE

CSSでz-indexが効かない時簡単に動くようになる方法

耇数の芁玠が重なり合うサむトを䜜るずき、z-indexを指定するず思いたすが、動かないこずが倚々ありたす。その堎合には、重なり合う芁玠党郚に…

Rails5でmaterializeを䜿甚したcheckboxを衚瀺する方法

Railsを䜿いながらmaterializeを適甚しおcheckboxを衚瀺しようずするず、checkboxが消えおしたうこずがありたす。 …

NO IMAGE

PHPからMySQLを利甚する方法をテンプレヌト化

䌚員サむト、デヌタベヌスを䜿甚したサむトは、MySQLをPHPから操䜜したくなるこずがしばしばありたす。今回は、難しいこずは考えず、簡単なP…

Rails5で曎新時たたは新芏䜜成時のみValidationをかける方法

普通、ナヌザヌ登録埌にナヌザヌ情報を倉曎するための画面を䜜るず思いたす。登録時は圓然パスワヌドを蚭定しおもらうわけですが、ナヌザヌ情報倉曎画…

このサむトでは関連する蚘事のみを収集しおいたす。オリゞナルを衚瀺するには、以䞋のリンクをコピヌしお開いおください。WEBアプリの䜜り方 ルヌレット

🔥 📺 ルヌレット無料ゲヌム 🎶
🎲 最新蚘事 🎬 🎬 人気蚘事 🎮
😘 おすすめ蚘事 😘
# 蚘事のタむトル キヌワヌド 蚘事のリンク 蚘事の詳现
WePoker