[2019/11/16] JavaScript jQueryでcanvasを使い図形を描画する方法 (No.137)
[2019/08/28] JavaScript 数値の小数点以下の丸め処理(Math.floor, Math.round, Math.ceil) (No.117)
[2019/07/11] JavaScript jQueryでAjaxを使いブロック領域を表示・非表示にする方法(css()メソッド、"display"属性) (No.112)
[2019/07/10] JavaScript jQueryを使った checkbox の操作方法 (No.111)
[2019/07/09] JavaScript jQueryでAjaxを使いPHPからデータを取得する方法その2(郵便番号からの住所取得) (No.110)
-
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
-
今回は HTML5 で用意されている canvas を使って図形を描画する方法について説明します。
この canvas は以前の様に Flash や Java を使わずに JavaScript で図形を描画することができます。
canvas の使い方ですが、以下の様に順を追って説明します。■canvasを使う準備
以下の様に HTML ソースの中に canvas タグを定義します。 タグIDは取敢えず canvas とし width height で領域の大きさを設定します。
その後 javascript で canvas にアクセスする為に canvas オブジェクトを取得します。 さらに canvas オブジェクトからグラフィック用コンテキストオブジェクトを取得します。
コンテキストオブジェクトの中のメソッドを使って各種の描画を行います。<canvas id="canvas" width="200" height="200" ></canvas> ... <script type="text/javascript"> ... var canvas = $("#canvas"); //canvasオブジェクトを取得 var ctx = canvas[0].getContext("2d"); //コンテキストオブジェクトを取得 //"2d":2次元グラフィック ... </script>
■直線の描画
直線の描画を行う為のコンテキストオブジェクトのメソッドは以下のものがあります。
メソッド 書式 説明 beginPath beginPath() 線処理の開始指定 moveTo moveTo(x, y)
x:点の x (水平) 座標
y:点の y (鉛直) 座標点の移動 lineTo lineTo(x, y)
x:線の終点の x 座標
y:線の終点の y 座標現在の点と指定された座標で直線を描画
(この線は実際には描画されません)closePath closePath() beginPathで始めたパスを最後に閉じる
(閉じた図形が描画される)stroke stroke() 現在まで蓄積された描画情報で実際に描画する 直線の例として以下のソースを示します。 closePath の部分がコメントになっていますが、 このまま実行すると、ソースの下の実際のボタンの「Line」の処理となり、 コメントを解除すると三角形を描画する「Triangle」の処理となります。
<html> <head> <meta charset="utf-8"> <title>test ajax</title> <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script type="text/javascript"> //Line関数 function drawLine() { var canvas = $("#canvas"); var ctx = canvas[0].getContext("2d"); //パス開始 ctx.beginPath(); //パス始点の座標 ctx.moveTo( 10, 10); //線の終点の座標 ctx.lineTo(190,190); //引き続いて線の終点の座標 ctx.lineTo( 10,190); //パス終了 //ctx.closePath(); //パスの輪郭の描画 ctx.stroke(); return false; } </script> </head> <body> <h2>test canvas</h2> <canvas id="canvas" width="200" height="200" ></canvas> <br /> <button onclick="drawLine();">Line</button> </body> </html>
「Line」をクリックすると2本の線が「Triangle」をクリックすると三角形の線が描画されます。
■四角形の描画
四角形の描画を行う為のコンテキストオブジェクトのメソッド・プロパティは以下のものがあります。
メソッド・
プロパティ書式 説明 strokeStyle strokeStyle = color
color:cssで用いる色指示枠線の色指定 strokeRect strokeRect(x, y, width, height)
x:四角形の左上の x (水平) 座標
y:四角形の左上の y (鉛直) 座標
width:四角形の横幅
height:四角形の高さ四角形の描画
線の色は直前のstrokeStyleで指定されたものfillStyle fillStyle = color
color:cssで用いる色指示塗りつぶしの色指定 fillRect fillRect(x, y, width, height)
x:四角形の左上の x (水平) 座標
y:四角形の左上の y (鉛直) 座標
width:四角形の横幅
height:四角形の高さ四角形の描画し内部を塗りつぶす
塗りつぶす色は直前のfillStyleで指定されたものclearRect clearRect(x, y, width, height)
x:四角形の左上の x (水平) 座標
y:四角形の左上の y (鉛直) 座標
width:四角形の横幅
height:四角形の高さ四角形の領域をクリアする 四角形の例として以下のソースを示します。
strokeStyle で線の色を設定し strokeRect で四角い枠を描画します。
fillStyle で塗りつぶす色を設定し fillRect で四角い領域を塗りつぶします。
最後に clearRect で四角い領域をクリアします。<html> <head> <meta charset="utf-8"> <title>test ajax</title> <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script type="text/javascript"> //Rect関数 function drawRect() { var canvas = $("#canvas"); var ctx = canvas[0].getContext("2d"); //[strokeRect]用色指定 ctx.strokeStyle = "red"; //四角形・枠のみ描画 ctx.strokeRect( 10, 10, 180, 180); //[fillRect]用色指定 ctx.fillStyle = "green"; //四角形・全体を塗りつぶす ctx.fillRect( 50, 50, 100, 100); //四角形・全体をクリア ctx.clearRect( 75, 75, 50, 50); return false; } </script> </head> <body> <h2>test canvas</h2> <canvas id="canvas" width="200" height="200" ></canvas> <br /> <button onclick="drawRect();">Rectangle</button> </body> </html>
「Rectangle」をクリックすると3種類の四角形が描画されます。
■円の描画
円の描画を行う為のコンテキストオブジェクトのメソッド・プロパティは以下のものがあります。
メソッド・
プロパティ書式 説明 arc arc(x, y, radius, startAngle, endAngle [, anticlockwise])
x:円の中心の x (水平) 座標
y:円の中心の y (鉛直) 座標
radius:円の半径
startAngle:円の開始角度(ラジアン:πの値で指定)
endAngle:円の終了角度(ラジアン:πの値で指定)
anticlockwise:trueで時計回り、falseで反時計回りの描画円の描画 <html> <head> <meta charset="utf-8"> <title>test ajax</title> <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script type="text/javascript"> //Circle関数 function drawCircle() { var canvas = $("#canvas"); var ctx = canvas[0].getContext("2d"); //[strokeRect]用色指定 ctx.strokeStyle = "red"; //[fillRect]用色指定 ctx.fillStyle = "yellow"; //線の幅は3px ctx.lineWidth = 3; //パス開始 ctx.beginPath(); //円描画:中心(100, 100)で半径50pxの円 ctx.arc(100, 100, 50, 0, 2 * Math.PI); //パス終了 ctx.closePath(); //塗りつぶす ctx.fill(); //パスの輪郭の描画 ctx.stroke(); return false; } </script> </head> <body> <h2>test canvas</h2> <canvas id="canvas" width="200" height="200" ></canvas> <br /> <button onclick="drawCircle();">Circle</button> </body> </html>
「Circle」をクリックすると円が描画されます。
PR -
数値の小数点以下の丸め処理を行うには Math オブジェクトを使います。 Math オブジェクトは数学的な定数と関数を提供する組み込みのプロパティとメソッドを持っています。
今回の丸め処理には、以下の様に切り捨て 四捨五入 切り上げ を行うメソッドがあります。- Math.floor() メソッド : 引数として与えた数以下の最大の整数を返します。
- Math.round() メソッド : 引数として与えた数を四捨五入して、もっとも近似の整数を返します。
- Math.ceil() メソッド : 引数として与えた数以上の最小の整数を返します。
今回は、これらのメソッドを使って丸め処理の関数を作成してみました。
丸め処理の関数
/* * 丸め処理 * P_dblVal : 対象値 * P_intRound : 小数点以下丸め処理(1:切り捨て, 2:四捨五入, 3:切り上げ) * return : 丸めた値 */ function calcRound(P_dblVal, P_intRound) { var dblRet; // 丸め処理 switch (parseInt(P_intRound)) { case 1: dblRet = Math.floor(P_dblVal); break; case 2: dblRet = Math.round(P_dblVal); break; case 3: dblRet = Math.ceil(P_dblVal); break; default: dblRet = Math.round(P_dblVal); break; } // 戻り値 return dblRet; }
上記の関数を実行させてみます。console.log('切り捨て:(10.4) = ' + calcRound(10.4, 1)); console.log('四捨五入:(10.4) = ' + calcRound(10.4, 2)); console.log('切り上げ:(10.4) = ' + calcRound(10.4, 3)); console.log('切り捨て:(10.5) = ' + calcRound(10.5, 1)); console.log('四捨五入:(10.5) = ' + calcRound(10.5, 2)); console.log('切り上げ:(10.5) = ' + calcRound(10.5, 3)); console.log('切り捨て:(-10.5) = ' + calcRound(-10.5, 1)); console.log('四捨五入:(-10.5) = ' + calcRound(-10.5, 2)); console.log('切り上げ:(-10.5) = ' + calcRound(-10.5, 3));
実行結果がコンソールには以下の結果が表示されます。
切り捨て:(10.4) = 10 四捨五入:(10.4) = 10 切り上げ:(10.4) = 11 切り捨て:(10.5) = 10 四捨五入:(10.5) = 11 切り上げ:(10.5) = 11 切り捨て:(-10.5) = -11 四捨五入:(-10.5) = -10 切り上げ:(-10.5) = -10
小数点以下1位の丸めは出来たのですが、小数点以下2位や3位での丸めはどうすればいいのでしょうか。 方法としては、小数点以下2位での丸めは数値を一旦10倍してから、丸め処理を行いその結果を10で割れば出来るようです。var valTest = 10.15; console.log('切り捨て:(10.15) = ' + Math.floor(valTest * 10) / 10); console.log('四捨五入:(10.15) = ' + Math.round(valTest * 10) / 10); console.log('切り上げ:(10.15) = ' + Math.ceil(valTest * 10) / 10);
実行結果がコンソールには以下の結果が表示されます。
切り捨て:(10.15) = 10.1 四捨五入:(10.15) = 10.2 切り上げ:(10.15) = 10.2
これを参考に上記の関数を変更してみます。
丸め処理の関数2(小数点以下桁数の引数追加)
/* * 丸め処理・小数点以下の桁数指定 * P_dblVal : 対象値 * P_intRound : 小数点以下丸め処理(1:切り捨て, 2:四捨五入, 3:切り上げ) * P_intDpUnit: 小数点以下桁数 * return : 丸めた値 */ function calcRoundDp(P_dblVal, P_intRound, P_intDpUnit) { var dblRet; var dblPow = Math.pow(10, P_intDpUnit); P_dblVal = P_dblVal * dblPow; // 丸め処理 switch (parseInt(P_intRound)) { case 1: dblRet = Math.floor(P_dblVal); break; case 2: dblRet = Math.round(P_dblVal); break; case 3: dblRet = Math.ceil(P_dblVal); break; default: dblRet = Math.round(P_dblVal); break; } // 戻り値 return dblRet / dblPow; }
上記の関数を実行させてみます。var valTest = 10.15; console.log('小数点以下2位を丸め処理'); console.log('切り捨て:(10.15) = ' + calcRoundDp(valTest, 1, 1)); console.log('四捨五入:(10.15) = ' + calcRoundDp(valTest, 2, 1)); console.log('切り上げ:(10.15) = ' + calcRoundDp(valTest, 3, 1)); console.log('小数点以下1位を丸め処理'); console.log('切り捨て:(10.15) = ' + calcRoundDp(valTest, 1, 0)); console.log('四捨五入:(10.15) = ' + calcRoundDp(valTest, 2, 0)); console.log('切り上げ:(10.15) = ' + calcRoundDp(valTest, 3, 0)); console.log('1の位を丸め処理'); console.log('切り捨て:(10.15) = ' + calcRoundDp(valTest, 1, -1)); console.log('四捨五入:(10.15) = ' + calcRoundDp(valTest, 2, -1)); console.log('切り上げ:(10.15) = ' + calcRoundDp(valTest, 3, -1)); console.log('10の位を丸め処理'); console.log('切り捨て:(10.15) = ' + calcRoundDp(valTest, 1, -2)); console.log('四捨五入:(10.15) = ' + calcRoundDp(valTest, 2, -2)); console.log('切り上げ:(10.15) = ' + calcRoundDp(valTest, 3, -2));
実行結果がコンソールには以下の結果が表示されます。
小数点以下2位を丸め処理 切り捨て:(10.15) = 10.1 四捨五入:(10.15) = 10.2 切り上げ:(10.15) = 10.2 小数点以下1位を丸め処理 切り捨て:(10.15) = 10 四捨五入:(10.15) = 10 切り上げ:(10.15) = 11 1の位を丸め処理 切り捨て:(10.15) = 10 四捨五入:(10.15) = 10 切り上げ:(10.15) = 20 10の位を丸め処理 切り捨て:(10.15) = 0 四捨五入:(10.15) = 0 切り上げ:(10.15) = 100
結果から見て、上手く動作している様です。
小数点以下の桁数に大きな値を与えると、関数内の Math.pow で桁あふれが発生する様です。 そのため、桁数指定は10桁以内ぐらいが妥当かと思います。(もっともそこまでの桁数で計算する処理も無いとは思いますが...)
-
最終的にブロック領域を表示・非表示にする方法を説明しますが、 そのために使用する jQuery の css() メソッドについて説明します。
css() メソッドは要素の style 属性を設定をします。 メソッドの引数の記述方法で、1個の属性のみと複数の属性の設定ができます。// 1個のstyle属性のみ $('要素').css('プロパティ', '設定値'); // 複数のstyle属性 $('要素').css({'プロパティ':'設定値', 'プロパティ':'設定値', ... });
例としてHTML要素で class 名が「class1」とした場合において、1個の場合は「color」属性を「red」に、 複数の場合は「color」属性を「blue」、「font-weight」属性を「bold」に設定するには以下の様にします。// 1個のstyle属性のみ $('class1').css('color', 'red'); // 複数のstyle属性 $('class1').css({'color':'blue', 'font-weight':'bold'});
そこで、ブロック領域を表示・非表示の制御を行うには、「display」属性を「block」(表示)、または「none」(非表示)に設定します。
今回のデモ HTML ファイル側のソースを以下に示します。■ブロック領域を表示・非表示にする
<html> <head> <meta charset="utf-8"> <title>test ajax</title> <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script> <script type="text/javascript"> // 表示・非表示関数 function setDisplay() { // チェック判定 if($("#chkOnOff").prop("checked")){ // 表示設定 $(".msg1").css("display", "block"); $("#area").css("display", "block"); } else { // 非表示設定 $(".msg1").css("display", "none"); $("#area").css("display", "none"); } return false; } </script> </head> <body> <h2>test display ON/OFF</h2> <label> <input id="chkOnOff" type="checkbox" onclick="setDisplay();" checked="checked" value="1" /> 表示ON/OFF </label> <br /> <div id="area" style="display: block;"> <p>aaaaaaaaaaaaaaaaaaaaaaaaaaa</p> <p>11111111111222222222222222</p> </div> <p class="msg1" style="display: block;">テストメッセージ1</p> <p class="msg1" style="display: block;">テストメッセージ2</p> <p class="msg2" style="display: block;">テストメッセージ3</p> </body> </html>
".msg1" のセレクタで class="msg1" の p タグのみが制御され、 "#area" のセレクタで id="area" の div タグが制御されることが分かると思います。
-
今回は checkbox の操作方法について説明します。
先ずは checkbox がチェックされているかを設定・取得するための prop 関数の説明をします。
指定された要素に対して「属性名」のみを引数にすると、属性値が返されます。 また、「属性名」「属性値」を引数にすると対象の「属性名」に指定した「属性値」設定されます。var v = $('要素').prop('属性名'); // 属性値が返る $('要素').prop('属性名', 属性値); // 属性値の設定
これを使った例として以下に HTML ファイル側のソースを示します。■prop を使った例
<html> <head> <meta charset="utf-8"> <title>test checkbox</title> <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script> <!--script src="./jquery-3.4.1.min.js"></script--><!-- IEの場合はこちら --> <script type="text/javascript"> // 初期処理 $(function(){ // 全てのチェックボックスをOFF $('#chk1').prop('checked', false); $('#chk2').prop('checked', false); $('#chk3').prop('checked', false); }); //ON/OFF関数 function getData() { var strMsg = "チェック内容\n"; // 各チェック判定 if($('#chk1').prop('checked')){ // チェックONの場合、自分の親のオブジェクトのTEXT取得 strMsg += $('#chk1').parent().text() + "\n"; } if($('#chk2').prop('checked')){ strMsg += $('#chk2').parent().text() + "\n"; } if($('#chk3').prop('checked')){ strMsg += $('#chk3').parent().text() + "\n"; } alert(strMsg); return false; } </script> </head> <body> <h2>test checkbox</h2> <label><input id="chk1" type="checkbox" value="1" />チェック1</label> <label><input id="chk2" type="checkbox" value="2" />チェック2</label> <label><input id="chk3" type="checkbox" value="3" />チェック3</label> <br /> <button onclick="getData();">状態取得</button> </body> </html>
9行目の $(function(){ ... }); の部分は JQuery で初期処理を記述する時の一般的な方法です。
この関数内に記述された処理が、全てのHTMLソース(DOM)を読込んだ後で実行されます。
この例では全ての checkbox の checked 属性を false に設定しています。
ボタンクリック時に全ての checkbox のチェック状態を取得し、チェックされている場合に 各 checkbox の親の label の要素のテキストを取得しています。
各 checkbox は label タグで囲まれているのですが、これはチェックボックスの右側のテキスト(”チェック1”など)を クリックしてもチェックボックス自身をクリックしたことと同様に動作します。 (四角いボックスだけしか効かないと不便なので)
チェックボックス3個の処理をべた書きしましたが、もう少し JQuery 的な方法で記述してみます。
■prop を使った例2
<html> <head> <meta charset="utf-8"> <title>test checkbox</title> <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script> <script type="text/javascript"> // 初期処理 $(function(){ // 全てのチェックボックスをOFF $('input[type="checkbox"]').prop('checked', false); }); //ON/OFF取得関数 function getData() { var strMsg = "チェック内容\n"; // 選択済チェックボックス $('input[type="checkbox"]:checked').each(function() { strMsg += $(this).parent().text() + "\n"; }); alert(strMsg); return false; } </script> </head> <body> <h2>test checkbox</h2> <label><input id="chk1" type="checkbox" value="1" />チェック1</label> <label><input id="chk2" type="checkbox" value="2" />チェック2</label> <label><input id="chk3" type="checkbox" value="3" />チェック3</label> <br /> <button onclick="getData();">状態取得</button> </body> </html>
初期処理のセレクタはタグ名が input でかつ type 属性が "checkbox" と一致するものが対象となります。
ON/OFF取得関数のセレクタはタグ名が input でかつ type 属性が "checkbox" でチェックされているものが対象となります。
セレクタの書き方を工夫すれば簡単な記述になります。パッと見は分かりづらいですが慣れだと思います。
-
前回の「Ajaxを使いPHPからデータを取得する方法」では例として郵便番号からの住所取得を挙げましたが、 それのデモ的なものを示したいと思います。
先ずは郵便番号のCSVファイルを以下のサイトからダウンロードする必要があります。
⇒郵便番号データダウンロード
今回はデモなので東京都のデータのみを利用しました。
HTML ファイル側のソースですが以下の様になります。
Ajax からの正常戻りの関数で、 PHPからのデータが住所1,住所2,住所3を配列にしたものを返してくるので、 分解してそれぞれの表示タグに設定しています。■Ajaxを使いPHPからデータを取得するHTMLファイルその2
<html> <head> <meta charset="utf-8"> <title>test ajax</title> <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script type="text/javascript"> //Ajax関数 function getData() { // マスタデータの取得 $.ajax({ type: "POST" , url: "./ajax2.php" , data: { zip: $("#zip").val() } }).done(function(res){ // ajaxがOK // JSON形式から文字列に変換 var data = JSON.parse(res); // [,]で分解 var arr = (""+data).split(','); // 住所の表示 $("#addr1").text(arr[0]); $("#addr2").text(arr[1]); $("#addr3").text(arr[2]); }).fail(function() { // 取得エラー alert('取得エラー'); }).always(function() { // 後処理(処理することが在れば) }); return false; } </script> </head> <body> <h2>test ajax json 2</h2> 郵便番号("-"無し):<input type="text" id="zip" size="10" maxlength="7" /><br /> <p id="addr1">テスト住所1</p> <p id="addr2">テスト住所2</p> <p id="addr3">テスト住所3</p> <button onclick="getData();">Ajax</button> </body> </html>
外部PHPファイル ajax2.php 及び 13TOKYO.CSV がこのHTMLファイルと同じディレクトリに存在することにします。
■外部PHPファイル ajax2.php
<?php // 郵便番号CSVファイル読込、配列データで返す // (KEY:郵便番号 => array(住所1, 住所2, 住所3) ) function getZipCsv($filename) { // ZIPデータ配列 $arrZip = array(); // ファイルを開く $fp = fopen($filename, 'r'); // whileで行末までループ処理 while (!feof($fp)) { // fgetsでファイルを読み込み、変数に格納 $txt = fgets($fp); if ($txt == "") continue; // SJISからUTF8への文字コード変換 $txt = mb_convert_encoding($txt, 'UTF-8', 'sjis-win'); // ["]を省く $txt = str_replace('"', '', $txt); // [,]で配列に分解 $arr = explode(',', $txt); // 3カラム目をキーにして住所1, 住所2, 住所3を配列で退避 $arrZip[$arr[2]] = array($arr[6], $arr[7], $arr[8]); } // fcloseでファイルを閉じる fclose($fp); // 郵便番号配列データを返す return $arrZip; } // 郵便番号の取得 $zip = ""; if (isset($_POST["zip"]) == true && $_POST["zip"] != "") { $zip = $_POST["zip"]; } // 東京の郵便番号CSVファイルを変数に格納 $arrZipData = getZipCsv('./13TOKYO.CSV'); $arrRet = array( "", "", ""); if ($zip != "" && array_key_exists($zip, $arrZipData)) { // 郵便番号のキーが存在 $arrRet = $arrZipData[$zip]; } // 結果を返す echo(json_encode($arrRet));
このPHPファイルの関数 getZipCsv は指定されたCSVファイルをオープンし、 1行毎に読込を行い、SJISからUTF8への文字コード変換を行った後で 郵便番号をキーとした配列に住所データを格納しています。
POSTされた zip を取得し、その値をキーとして、郵便番号配列データから 該当データを取得し JSON データに変換して echo 関数で返してやります。
今回は東京都のデータしかありませんが、本当ならば全国のデータに対応する必要があります。 そのためにはこの様なCSVファイルを都度読込んで処理するには重すぎるので、 データベースに郵便番号マスタを作成して、そこから取得するのが一般的だと思います。