別れと出会いの季節
会うは別れの始めとか。会者定離(えしゃじょうり)、春は別れと出会いが交錯します。親子ならばスープの冷めない距離で過ごせたら最高と言われています。手元で仲良く暮らせたらと願うものです。
一方、「かわいい子には旅させよ」、「他人の釜の飯を食え」、「世界に羽ばたけ」、「大志を抱け」など、ぬるま湯に浸っていてはせいぜい、町内会の世話役で終わりそうな若者を励ます言葉に事欠きません。
たくさんの選択肢で迷うほどです。
卯月4月、餞(はなむけ)の言葉を受けて旅立つ若者に幸あれ!
会うは別れの始めとか。会者定離(えしゃじょうり)、春は別れと出会いが交錯します。親子ならばスープの冷めない距離で過ごせたら最高と言われています。手元で仲良く暮らせたらと願うものです。
一方、「かわいい子には旅させよ」、「他人の釜の飯を食え」、「世界に羽ばたけ」、「大志を抱け」など、ぬるま湯に浸っていてはせいぜい、町内会の世話役で終わりそうな若者を励ます言葉に事欠きません。
たくさんの選択肢で迷うほどです。
卯月4月、餞(はなむけ)の言葉を受けて旅立つ若者に幸あれ!
商売を始めるにあたり、資金や労力が用意できれば十分というわけではありません。書類には表すことのできない、秘伝、ノウハウなど人知を超えたものが成功・不成功を決定づけることがあります。
JavaScriptを用いてHTML文書を作るにも、ツールを使って価値の高い文書に近づけます。
このたび、Svg要素で矢印付き円弧を含む図形を作成するための小さな道具を作りましたのでお知らせします。
Svg(Scalable Vector Graphics)はテキストを含めて、図形を表示するにあたり、すべて文字で表現するので、図形を拡大しても画面が粗くなることがありません。曲線や直線を表すには、豊富なコマンドを使います。コマンドはHTMLリファレンスマニュアルにしたがって作りますが思い通りになるとは限りません。
矢印の角度や長さが適切でないと寸胴のようで醜く、誤差で矢印が逆向きになることがあります。そこで動作を確認できるサポートツールを作りました。
矢印付きの円弧はpaint.netなどを使うと作成可能ですが、容易ではありません。今回のツールは描画するためのコマンドを仮に作り表示させます。
そのとき、そのコマンドをファイルに出力します。そして、満足のいく結果が得られたときに、ファイルにセーブしたコマンドをソースに反映します。console.logデバッグ文にてファイル出力を代替します。
コマンドをsvg要素のなかに設置すれば、JavaScriptを使わずにきれいな図形を描くことができます。上の図は今回のツールを用いて円弧に矢印を付けています。
<html> <head> <svg width="500px" height="500px" version="2.0" xmlns="http://www.w3.org/2000/svg" style="border:1px solid pink;"> <text x="5" y="16" font-family="sans-serif" font-size="12px" fill="navy">©2017 TacM, Ver 0.01</text> <marker viewBox="0 -3 10 10" refX="5" refY="0" orient="auto-start-reverse" markerWidth="10" markerHeight="10" id="mk1"> <polygon points="10,0, 0,3 0,-3"/> </marker> <path id="cm0" d="M 430 246 A 180 180 0 0 0 343.46410161513774 96.11542731880104" fill="none" stroke="orange" marker-start="url(#mk1)" marker-end="url(#mk1)"/> <path id="cm1" d="M 336.53589838486226 92.11542731880104 A 180 180 0 0 0 82.22340883183918 184.67760371823599" fill="none" stroke="orange" marker-start="url(#mk1)" marker-end="url(#mk1)"/> <path id="cm2" d="M 79.48724768523383 192.19514468452323 A 180 180 0 0 0 214.80409700790372 426.5708028315297" fill="none" stroke="orange" marker-start="url(#mk1)" marker-end="url(#mk1)"/> <path id="cm3" d="M 222.68255903200136 427.9599882528652 A 180 180 0 0 0 430 254.0" fill="none" stroke="orange" marker-start="url(#mk1)" marker-end="url(#mk1)"/> <path id="ln0" d="M 250 250 L 350 76.8" fill="none" stroke="green"/> <path id="ln1" d="M 250 250 L 62.06147584281834 181.59597133486622" fill="none" stroke="green"/> <path id="ln2" d="M 250 250 L 215.27036446661393 446.9615506024416" fill="none" stroke="green"/> <path id="ln3" d="M 250 250 L 450 250.0" fill="none" stroke="green"/> <path d="M 0 250 L 500 250" stroke="aliceblue" fill="none" stroke-width="1"/> <path d="M 250 0 L 250 500" stroke="aliceblue" fill="none" stroke-width="1"/> </svg> </head> <body onLoad="rose1()"><BR> 開始角度<input id="step1" type="number" min="0" max="360" value="0" style="width:52px;"/> 終了角度<input id="step2" type="number" min="0" max="360" value="60" style="width:52px;"/> 矢印円径<input id="step3" type="number" min="40" max="120" value="72" style="width:52px;"/> 仕切り長<input id="step4" type="number" min="40" max="120" value="90" style="width:52px;"/> <input id="msg3" type="button" onClick="display('step1', 'step2', 'step3', 'step4')" value="描画" style="font-weight:bold; background-color:cyan; border-color:red; border-width:1px"/> </body> <script type="text/javascript" charset="Shift_JIS"> const COM1="M "; // const COM2="A "; // const ZX=250; const ZY=250; var count=0; var RADIUS=72; var LENGTH=90; function rose1(){ console.log("Start SvgArcGen."); } function display(target1, target2, target3, target4){ //描画ボタンが押下されたとき起動 if(count >= 4) alert("終わっています"); else{ //開始 if(count==0){ cm0.setAttribute("d", "");ln0.setAttribute("d", "");//#1 cm1.setAttribute("d", "");ln1.setAttribute("d", "");//#2 cm2.setAttribute("d", "");ln2.setAttribute("d", "");//#3 cm3.setAttribute("d", "");ln3.setAttribute("d", "");//#4 } var tg1 = document.getElementById(target1).value; //ステッパー値を算出 var tg2 = document.getElementById(target2).value; //ステッパー値を算出 RADIUS = document.getElementById(target3).value; //ステッパー値を算出 LENGTH = document.getElementById(target4).value; //ステッパー値を算出 var x1 = ZX+RADIUS * Math.cos(tg1 * Math.PI / 180); var y1 = ZY-RADIUS * Math.sin(tg1 * Math.PI / 180); var x2 = ZX+RADIUS * Math.cos(tg2 * Math.PI / 180); var y2 = ZY-RADIUS * Math.sin(tg2 * Math.PI / 180); var f2 = (tg2 - tg1) < 180 ? 0 : 1; var xb1 = 4 * Math.sin(tg1 * Math.PI / 180); var yb1 = 4 * Math.cos(tg1 * Math.PI / 180); var xb2 = 4 * Math.sin(tg2 * Math.PI / 180); var yb2 = 4 * Math.cos(tg2 * Math.PI / 180); var vx = ZX+LENGTH * Math.cos(tg2 * Math.PI / 180); var vy = ZY-LENGTH * Math.sin(tg2 * Math.PI / 180); //console.log("LX="+vx+" LY="+vy); var md1 = COM1 + (x1-xb1) + " " + (y1-yb1) + " "; var md2 = COM2 + RADIUS + " "+ RADIUS + " 0 "; var md3 = md1 + md2 + f2 + " 0 " + (x2+xb2) + " " + (y2+yb2); md2 = COM1 + ZX + " "+ ZY + " L " + vx + " " + vy; console.log("cm"+count+" : "+md3+" ln"+count+" : "+md2); switch(count){ case 0: cm0.setAttribute("d", md3);ln0.setAttribute("d", md2);break; //#1 case 1: cm1.setAttribute("d", md3);ln1.setAttribute("d", md2);break; //#2 case 2: cm2.setAttribute("d", md3);ln2.setAttribute("d", md2);break; //#3 case 3: cm3.setAttribute("d", md3);ln3.setAttribute("d", md2);break; //#4 } step1.setAttribute("value", tg2); //開始角度 var tg3 = (tg2 > 260) ? 360 : Number(tg2) + 100; step2.setAttribute("value", tg3); //終了角度 ++count; } } </script> </html>
サンプルコードの3,5行目に示すように、Svgのバージョンは2.0でorient属性のパラメータはauto-start-reverse指定でなければなりません。開始角度、終了角度、矢印円径、仕切り長を入力して描画ボタンをクリックすると下図のような円弧と仕切り線が描画されます。
次の開始角度は前回の終了角度がコピーされます。よって、2回目以降、連続した領域に円弧を描くには終了角度だけを入力して描画ボタンをクリックします。描画は4回で終了になります。
デバッガを起動しconsole.logで出力したメッセージをコマンドに使えるように、コピー&ペーストで取り込み、テキストエディタで編集しHTMLコードを作成します。
このたびの例題では360度を最高4つの領域に分割するにとどまっています。せっかくの矢印が期待した向きにならない場合は、chrome, opera, firefoxなどのブラウザをお使いください。デバッガはどのブラウザにも付属されています。デバッガの使い方については別の機会に譲りますが、右クリックし「検証」から進みます。
canvasはHTML5でサポートされた図形を描く時の描画仕様です。最近、設定された歴史が浅い規格だからか、漢字がきれいに表示されません。
動的な表現は、CANVASでしかできないと思っていましたが、従来からのdivタグやspanタグでもメッセージや画像データを動的に切り替えられるので動的表現は可能です。
CANVASでのテキスト表示はきれいとは言いがたいです。CANVASで動的にテキストを変更するやり方をマスターできたので、最近はdocument.getElementById(“div2”).innerHTMLのような使い方をしています。
<html> <body onLoad="starting();"> <canvas id="canv" width="580" height="80" style="border: 1px blue solid"></canvas> <div id="dv2" style="width:580; height:80; font-family:sans-serif; font-size:28px; color: red; border: 1px red solid"> あいうえお </div> </body> <script type="text/javascript"> const TTL10 = "とりたて産直野菜、うまさ安さ一挙両得"; var ctx; // コンテキスト function starting(){ document.getElementById("dv2").innerHTML = TTL10; // メッセージを変更 var canvas = document.getElementById('canv'); // canvasの要素を取得する if(canvas.getContext){ // canvasオブジェクト ctx = canvas.getContext('2d'); // canvasのコンテキスト ctx.font = "normal 28px sans-serif"; // テキストのフォント ctx.fillStyle = "orange"; // メッセージの色 ctx.fillText(TTL10, 0, 30); // メッセージを出力 } } </script> </html>
両者を比較するとDIV要素で表示したテキストが鮮明です。これだけの例では差は少ないですがもっと、顕著です。これからは図形はCANVAS、テキストはなるべくDIV,SPANを使っていきたいと考えています。
世の中、いろいろなことが起こりすぎています。犯罪を防止するために監視カメラがいたるところに設置されています。暗いところ、人通りの少ないところには危険が潜んでいます。だから、そこに監視カメラを設置という有様です。
収穫期になると丹精込めて作った果物を根こそぎ盗んでいく行為も後を絶ちません。確たる証拠がないだけに泣き寝入りが多くなります。ただし、痕跡は残っています。
他人の振る舞いを見極めることはある程度、可能です。パソコンの音量、TV視聴直前チャンネルなどは履歴が残っています。
他に帽子、スーツまでは高級品を揃えても靴がエナメルの安物だったので詐欺師と見破ることができたと聞きました。
アランドロン主演映画のワンシーンにありました。趣味として小鳥を飼っていると思っていたら、無断で家宅捜索を受けたときの対策でした。小鳥により飼い主以外の人が知らぬ間に入室したかを知ることができるようです。
実印を押す角度を少し傾け、自分で押したか勝手に利用されたかが分かるようにする話はよく聞きますが、角度はまっすぐにして力のかけ具合で左上を薄めに押印するなど高度なセキュリティを施す達人もおられるようです。
TV、ラジオ、新聞は無料かそこそこの料金で見ることができます。ネット検索も無料に近いです。そこには運営者が広告収入で賄っているからです。
グーグルなどの検索提供者には通常の人には到底、集めることのできない情報が得られます。それらを必要な人に提供して別の収入を得ることができます。
ブログに広告を載せると収入が得られます。そのためにオーバーな表現で広告収入を増やす大企業や個人も存在します。当ブログの広告収入は年間、数百円です。額は少ないですが運営者には閲覧ツールの種類など得難い情報を入手できます。
まとめサイトなど、本来の目的から離れて開設されるいるものがあります。ブログなどのSNSも同じ穴の貉(むじな)でしょうか。要自戒!。
掲載される広告を選ぶこともできますが、細かな設定は無理です。困ることはブログ記事に反応して広告内容が変わることです。ブログには愚痴めいたことを書く時があります。そのような主張(なかは単なる愚痴)に広告が反応するのは本当に困ります。
愚痴は年に二度ほどは許されると思っていますが、四六時中、広告にでてくるのは本意ではありません。
たとえば、『今どきの若者は…』は、たまには許されますが、たびたび出てくると『若者は頑張っているぞ』と言いたくなります。
お節介もほどほどにしてもらいたいし、介入するのならば、もっと真意を理解してもらいたいものです。
「みつを」はせんだみつお氏ではありません。相田みつをさんの名言を参照させていただきました。
地図を目次にする簡潔方法では、47都道府県をすべて長方形に見立てて、クリックした位置から詳細な情報にたどり着くために道筋を立てられるような内容でした。
地図画像の複数点をクリックして、その位置に応じた流れにするには、ある点が多角形に内包するかという問題に帰着します。今回はもう少し、複雑な領域をサポートしてみます。
《多角形に点が含まれるかどうか判定する》には、点と多角形の1辺が作る符号付き角度(a,b,c,d)の総和が 360 度であれば、その点は多角形の内部にあり、そうでなければ外にあると判定する簡便法があります。
多角形が単純な凸型ならば問題は起きませんが、左図のような凹部があると期待した動作にならないことが知られています。
これらの問題をクリアした、点から正の方向に伸ばした x 軸(半直線)が多角形境界線と交差する回数を数える方式(crossing Number Algorithm)があります。
この回数(cN)が奇数ならば、その点は多角形の内側にあり、偶数ならば外側にあると判定されます。Crossing Number Algorithm は Ray Casting Algorithm とも呼ばれています。
符号付き角度(a,b,c,d)の総和が 360 度であるかどうかで判定する方法では、九州・沖縄の地図を図のように簡略化して実装したときに、鹿児島県をクリックしたときに誤動作しました。
これらを解決するために、多くの研究者が技術を公開しており、二次元多角形領域内部に点が含まれるかどうかを判定を参考にさせていただきました。
ここでは、九州・沖縄に限定して実装を試みました。1ヶ所で独立しているのは北海道と沖縄だけであり、この課題をクリアすれば47都道府県をカバーできるでしょう。
<html> ray casting algorithm<BR> <body onload="starting()"><canvas id="kyu8" width="300" height="444" style="border: 1px orange solid"></canvas></body> <audio id="sound3" src="https://aidesign.lolipop.jp/wp-content/uploads/2015/09/select06.mp3"></audio> <script type="text/javascript" charset="Shift_JIS"> const KX=160; // 表示位置x const KY=400; // 表示位置y const pref=["長崎", "佐賀", "福岡", "大分", "熊本", "宮崎", "鹿児島", "沖縄"]; // # n 県名 const poly=[[ 10, 9, 96, 9, 96,100, 10,100], // 0 4 長崎 [ 96, 9, 170, 9, 170,100, 96,100], // 1 4 佐賀 [170, 9, 288, 9, 288,101, 214,101, 214,149, 129,149, 129,100, 170,100],// 2 8 福岡 [214,101, 288,101, 288,198, 214,198], // 3 4 大分 [129,149, 214,149, 214,268, 129,268], // 4 4 熊本 [214,198, 288,198, 288,314, 214,314], // 5 4 宮崎 [129,268, 214,268, 214,314, 288,314, 288,357, 129,357], // 6 6 鹿児島 [ 14,341, 79,341, 79,423, 14,423]]; // 7 4 沖縄 var img1 = new Image(); // 画像オブジェクト,ロードする img1.src = "https://aidesign.lolipop.jp/wp-content/uploads/2017/03/Kyushu08.png"; // 九州・沖縄の地図 var ctx; // コンテキスト //------------------------------------------------------// 2017-03-20 Completed. function starting(){ // draw-top、ページの読み込み時に実行される var canvas = document.getElementById('kyu8'); // canvasの要素を取得する if(canvas.getContext){ // canvasオブジェクト ctx = canvas.getContext('2d'); // canvasのコンテキスト canvas.addEventListener('click', clickfunc , false);// マウスイベントを取り付ける ctx.drawImage(img1, 0, 0, 300, 444); // <<<<< 九州・沖縄の地図を描画 >>>>> ctx.fillStyle = "navy"; // 現在地名の色 ctx.fillText("\xA9TacM,2017 Ver0.01", KX, 430); // copyright } } // draw-bottom function clickfunc(event){ // クリックされた時の処理 document.getElementById("sound3").play(); // キー押下音 ctx.clearRect(KX, KY-30, 120, 34); // 前に表示した内容をクリアする ctx.font = "30px Gill Sans MT Bold"; // set font. ctx.fillStyle = "red"; // メッセージの色 for(var i=0; i<poly.length; ++i){ // 地点を検索する if(pointInPolygon(event.offsetX, event.offsetY, poly, i)){// judgeInclusion 検索地の左端・上端~右端・下端 ctx.fillText(pref[i]+"県", KX, KY); // 検索にヒットした return; // breakはNG、returnの省略は不可 } } ctx.fillText("該当なし", KX, KY); // 検索にヒットしない return; // 戻り値のない関数は省略可能 } function pointInPolygon(px, py, Array, m){ // px:event.offsetX, py:event.offsetY, Array:array-addr, m:index var crossingNumber=0; // cNが奇数ならば点Pは多角形Tの内側に、偶数ならば外側にあると判定 for(var i=Array[m].length-2,j=0,yi,yj,counterClockwise; i>=0; j=i,i-=2){// Arrayテーブルの大きさ:8, 6 4 2 0 yi=Array[m][i+1]-py; // <<<<< 点の多角形に対する内外判定 >>>>> yj=Array[m][j+1]-py; // role-1:上向きの辺。点Pがy軸方向について、始点と終点の間にある。 if((yi>0)!=(yj>0) && (counterClockwise=sign(yj,yi))==sign(yj*(Array[m][i]-px), yi*(Array[m][j]-px))){ crossingNumber+=counterClockwise; // role-2:下向きの辺。点Pがy軸方向について、始点と終点の間にある。 } // role-3:ルール1,ルール2を確認することで、ルール3も確認できる。 } // role-4:辺は点pよりも右側にある。 return crossingNumber%2==1; // ray casting algorithm } function sign(a, b) { // 両者を比較して、-1 0 1を返す return (a > b) ? 1 : (a < b) ? -1 : 0; } </script> </html>
福岡県は8角形、鹿児島県は6角形でありともに凹部を含んでいます。他県はすべて4角形です。本格的な処理に発展させるには38行と42行を拡張させるとよいでしょう。県内、県外の領域をクリックし、納得のいくメッセージが表示されるかを試してください。
ray casting algorithm
以前も比叡山延暦寺までご案内でハイパーラプスによる道案内を載せました。ストリートビュー用の動画が完成するまで時間がかかるのが難点です。
今回はその時間を利用して、名所のイラストや写真をスクロール表示してみました。
コマ落としのストリートビュー動画が完成するまでの工程。
1.開始
2.地図データ作成、地図上に進行経過を表示
3.動画をロード中、延暦寺の略歴を表示
4.マップ上をドライビング
5.京都駅-延暦寺バスセンターをストリートビュー
ハイパーラプス動画は準備に時間がかかる割には、表示があっという間に終わってしまうことが残念です。遅らせて表示する方法を模索中です。
以前に、地図を目次にするウィジェットの作り方で本格的な地図の利用法を掲載しましたが、今回は違う仕組みで簡単な地図目次を作ってみます。
ここでは、canvas要素にaddEventListenerを用いてマウスイベントを取り付けて、クリック位置を管理します。マウスイベント関数では、地図上にあらかじめ定義された領域とクリックされたポイントを突き合わせてどの県都が選択されたかを決定します。
関東地方、一都六県の地図の所定位置をクリックするとその県都の情報が表示されるものです。
①基準となる地図を用意する
例として最後の方に示す関東地方の地図(KantoArea1.png)を考えます。地図は自然な形で画面に収まるサイズが望ましいです。もう少し小さい方が更に引き立つと思われるますが、他に表示するものがないので横550px、縦520pxにしました。
➁クリック有効領域を地図にマークする
県や都の地図上の形は複雑ですが、長方形で代表することにします。下のような地図(KantoArea2.png)を作成します。オリジナルな地図(KantoArea1.png)を残しておくことが大切です。
③補助線付き地図とクリック位置が表示されるJavaScriptコードを作成します。このサンプルコードは栃木県から群馬県まで時計回りに、黄色に象られた長方形の左上と右下を順にクリックして、領域の範囲をテーブル化するためだけにあります。入力を失敗したときは再読み込みをしてやり直します。
<html> <script type="text/javascript" charset="Shift_JIS"> const mesg=["左上", "右下"]; const pref=["栃木", "茨城", "千葉", "神奈川", "東京", "埼玉", "群馬"]; const point=[226, 46,374,173, 380, 58,505,294, 325,302,503,508, // 画面上の位置 174,235,305,321, 165,322,312,371, 141,383,303,483, 54, 81,212,206]; var img1 = new Image(); // 画像オブジェクト,ロードする img1.src = "../material/KantoArea2.png"; // 1都6県 var m=n=0; // n:0~6、訪問地番号 var ctx; //------------------------------------------------------// 2017-03-11 function starting(){ // draw-top、ページの読み込み時に実行される var canvas = document.getElementById('east'); // canvasの要素を取得する if(canvas.getContext){ // canvasオブジェクト ctx = canvas.getContext('2d'); // canvasのコンテキスト canvas.addEventListener('click', clickfunc , false);// マウスイベントを取り付ける ctx.drawImage(img1, 0, 0, 550, 520); // <<<<< 奥の細道全行程図を描画 >>>>> } } // draw-bottom function clickfunc (event) { // クリックされた時の処理 document.getElementById("sound3").play(); // キー押下音 m = Math.floor(n / 2); console.log("N="+n+" : "+pref[m]+" "+mesg[n%2]+" X="+event.offsetX+" Y="+event.offsetY); ++n; return; // 戻り値のない関数は省略可能 } </script> <body onload="starting()"><canvas id="east" width="550" height="520" style="border: 0px #999 solid"></canvas></body> <audio id="sound3" src="https://aidesign.lolipop.jp/wp-content/uploads/2015/09/select06.mp3"></audio> </html>
④上の関東地方地図の右にデバッグ情報として出力されたクリック位置の値を参照してpointテーブルを編集します。
⑤次に、これまでの開発用コードを保存し、補助線なしの地図に切り替え、クリックされた都県を認識する目次の機能を追加します。
⑥デバッグ用ステートメントを削除するかコメント文にします。使わなくなったmesgテーブルや変数mなども削除します。完成版サンプルコードを以下に掲載します。27行の三項演算子で東京では都を、その他では県が付加されます。33行のreturnは省力できますが、29行のreturnを省略すると正しく動作しません。
<html> <script type="text/javascript" charset="Shift_JIS"> const pref=["栃木", "茨城", "千葉", "神奈川", "東京", "埼玉", "群馬"]; const point=[233, 6,364,188, 370, 42,536,289, 345,297,532,514, // 画面上の位置 138,381,301,486, 134,322,338,372, 116,217,329,314, 66, 46,217,206]; var img1 = new Image(); // 画像オブジェクト,ロードする img1.src = "../material/KantoArea1.png"; // 1都6県 var n=0; // n:0~6、訪問地番号 var ctx; //------------------------------------------------------// 2017-03-11 Completed. function starting(){ // draw-top、ページの読み込み時に実行される var canvas = document.getElementById('east'); // canvasの要素を取得する if(canvas.getContext){ // canvasオブジェクト ctx = canvas.getContext('2d'); // canvasのコンテキスト canvas.addEventListener('click', clickfunc , false);// マウスイベントを取り付ける ctx.drawImage(img1, 0, 0, 550, 520); // <<<<< 奥の細道全行程図を描画 >>>>> } } // draw-bottom function clickfunc (event) { // クリックされた時の処理 document.getElementById("sound3").play(); // キー押下音 //console.log("X="+event.offsetX+" Y="+event.offsetY); ctx.clearRect(210, 10, 220, 24); ctx.font = "18px Gill Sans MT Bold"; // set font. ctx.fillStyle = "red"; // メッセージの色 for(var i=0; i<7; ++i){ // 地点を検索する if(ck(event.offsetX, event.offsetY, i)){ // x,yをチェック 検索地の左端・上端~右端・下端 var s = (i != 4) ? "県" : "都"; // 東京ならば「都」 ctx.fillText(pref[i]+s+"が選択されました", 210, 30); return; // breakはNG } } ctx.fillText("該当する都県がありません", 210, 30); // 検出にヒットしない return; // 戻り値のない関数は省略可能 } function ck(x, y, j){ // クリックされた位置の有効性をチェック if(x>=point[j*4] && x<=point[j*4+2] && y>=point[j*4+1] && y<=point[j*4+3])return true;//範囲内,左端・上端~右端・下端 return false; // 範囲外 } </script> <body onload="starting()"><canvas id="east" width="550" height="520" style="border: 0px #999 solid"></canvas></body> <audio id="sound3" src="https://aidesign.lolipop.jp/wp-content/uploads/2015/09/select06.mp3"></audio> </html>
多角形で象られた複雑な領域をクリックして制御するデータを作成するツールが出回っていますが、ここでは単純な長方形だけをサポートしています。
長方形だけでは県境で誤差が出て正確さを欠きますが、それでも県庁所在地付近では正確に都県を選択することが可能です。まずは簡単な仕組みを理解して高みを目指しましょう。
詳細な都県情報を出力するには、上記コードの28行を拡張して都県が運営するホームページにジャンプするように編集します。
人口の多いところでは、食事提供の専門店が繁盛しています。中でも都市部ではラーメン店が多いです。地方では峠の一軒家の食事処と言えば、日本そばです。ラーメン店は少なく、いまでは差別用語ととられかねない支那そばという呼び名を使っているお店もあるようです。
大都市では店がひしめいている激戦区や大手レストラン等との競争も熾烈を極めます。
細い麺が特徴で店主が一人で切り盛りしている一味違うラーメン店に通い始めた頃、居酒屋チェーン店が道向かいにできて、昼食客を採算度外視で誘導するためにチラシ配りを始めました。客が激減してラーメン店は廃業のやむなきに至りました。
小船が大きな波に飲みこまれた例です。
かつて、青梅マラソンが長距離の登竜門として人気を博していました。国際大会ではないのに高い知名度に支えられていたようです。ところが同じ時期に東京マラソンが新設され、青梅マラソンは著しく地盤沈下しました。
人や物の評価は相対的です。毒舌で有名なラジオ中心の人気司会者は、気の利いた言葉を発する客に対して「俺より目立つことを言ってら」とわめき立てます。似たようなことで、庶民的な家並みに豪邸ができると周りがくすみます。
世の中、割り切れないことが多いです。難題や危機は自衛することで避けられることもあれば、何百年に一度と言われるような大災害や隕石の落下などは避けることが難しいです。
そのために逃げるが勝ちという諺があります。ただ、いつも逃げてばかりいると信用をなくします。「やる時はやる」という気概を示さないと誰もついてこなくなります。
いつの世も栄枯盛衰はついて回るものであり、衰退は怠慢だけで起きるものではありませんが、時代の流れを読み切れなかったというそしりは受け止めなければならないでしょう。
長くやっていると、逆風が吹いてきたと思っていたら追い風が吹いてウハウハしたこともありました。如何にして逆境を切り抜けるかです。特効薬があったら教えてほしいものです。
春に因んで漢詩から著名な詩のひとつを掲載します。戦乱で荒廃した故郷を歌った詩です。外国語を日本語で朗読するものであり、漢字のフリガナと読みが違う箇所があります。参照サイト:(http://roudoku-heike.seesaa.net/article/125009597.html、朗読、杜甫『春望』)
別れと出会いの季節、センチメンタルな気分もたまにはいかがでしょうか。
寒さに耐え忍んでいた草木が生い茂る季節となりました。
うららかな春日和(はるびより)は心地よいものです。日当たりの良い野原につくしが生え、もうすぐ蝶が飛びかう頃です。
ほのかな雪洞の灯りに安らぎを感じます。
女の子の幸せを願う桃の節句ひなの祭りはもうすぐです。ひな祭りが終わるとひな人形のあと片付けに忙しいことでしょう。