デジタル時計2

テキストにデジタル時計の簡潔な書き方が載っていたのでご紹介します。toLocaleTimeString(“ja-JP”, options)  locale “ja-JP” は省略可

options には、12時制(true)か24時制(デフォルトまたは未定義ではfalse)の選択をする、hour12 やhour,minute,second(デフォルト、未定義ではnumeric) などがあります。

function displayTime() {
  var elt = document.getElementById('clock');
  var now = new Date();
  elt.innerHTML = now.toLocaleTimeString();
  setTimeout(displayTime, 1000);
}
window.onload = displayTime;

参考URL: https://msdn.microsoft.com/ja-jp/library/474de325(v=vs.94).aspx

JavaScriptの日付メソッド

Date オブジェクトに対して”年”、”月”、”日”を得るには、静的メソッドがそれぞれ用意されています。表にまとめてみました。

Date.getFullYear()
getYear()は推奨されていません。
Date.getMonth()
0から11を返し通常1を足して使います。
Date.getDate()
日にちを数値で返します。
曜日 Date.getDay()
日曜日を0として0から6の数値を返します。

今日の年月日を表示する例を示します。曜日を表示させるには、日~土までの値を入力した配列を作り番号で指定します。

曜日表示にバグがあるらしく、日付表示はtoLocaleDateString() メソッドを使うのが無難みたいです。第1引数にja-JPで西暦、ja-JP-u-ca-japanese で和暦が表示できます。

window.onload = function() {
  var myDate = new Date();
  var options = {
    year: "numeric",
    month: "numeric",
    day: "numeric",
    weekday: "long"
  };
  var str = myDate.toLocaleDateString("ja-JP", options);
  document.getElementById("result").innerHTML = str;
}

ttp://catprogram.hatenablog.com/entry/2015/05/06/143753

デジタル時計

デジタルらしく”0″ を付けました。

window.onload = function() {
  function time() {
    var now = new Date();
    var nowHours = now.getHours();
    var nowMinutes = now.getMinutes();
    var nowSeconds = now.getSeconds();
    if (nowMinutes < 10) nowMinutes = "0" + now.getMinutes();
    if (nowSeconds < 10) nowSeconds = "0" + now.getSeconds();
    strTime = nowHours + ':' + nowMinutes + ':' + nowSeconds;
    document.getElementById('clock').innerHTML = strTime;
  }
  setInterval(time, 1000);
}

PHP リロードしない

Google 先生にPHPでページの自動リロード方法を聞いた処、

<?php
    $rel = $_GET['reload'];
    if ($rel == 'true') {
      header("Location: " . $_SERVER['PHP_SELF']);
    }
    /*デバッグ用*/
    echo($_SERVER['PHP_SELF'].'<br/>');
    echo($_SERVER['SCRIPT_NAME'].'<br/>');
?>

header()を書き込むと良いとのことで試してみましたがダメでした。(たぶん、GETするフラグの作り方が分からないことが分かっている。迷推理)次にJavaScript でリファラを参照して特定のページからアクセスした場合にlocation.reload() するとしてみましたが、何故か無限ループになります。

var myRef = document.referrer;
if (myRef.indexOf("http://hoge.jp/foo.php") == 0) {
  location.reload();
  Object.defineProperty(document,"referrer",{value:"null"});
}

http://oshiete.goo.ne.jp/qa/77766.html で紹介されていた方法で

rload = setTimeout( "location.reload()", 100 );
 clearTimeout( rload );

も試しましたがリロードしませんでした。結局、HTMLで手動リンク

<a href="./bar.php">リロード</a>

が丸いと思いました。(粉ミカン

https://www.ipentec.com/document/document.aspx?page=php-page-reload

pushとpop

配列に要素を追加したり、追加した要素を取り出す配列操作のメソッドにpush と popがあります。組み合わせると先入れ後出し(first in, last out)のスタックが実現します。

var stack = [];

stack.push('Lightning Bolt');
 // スタックの内容:['Lightning Bolt'] 1 を返す
stack.push('Brainstorm');
 // スタックのの内容:['Lightning Bolt', 'Brainstorm'] 2を返す
stack.pop();
 // スタックの内容 ['Lightning Bolt'] Brainstorm を返す
stack.push('Counterspell','Price of Progress');
 // スタックの内容['Lightning Bolt','Counterspell','Price of Progress'] 3を返す
stack.pop();
 // スタックの内容['Lightning Bolt','Counterspell'] Price of Progress を返す

stack.pop();
 // スタックの内容['Lightning Bolt']  Counterspellを返す

Counterspell されてもpop() しない限りstack の’Lightning Bolt’ は取り出せませんけど・・・ね。

JavaScriptでCSVファイルを読む

XMLHttpRequest を使って外部CSVファイルを2次元配列として読み込み、テーブルとして出力しています。

.open メソッドの第1引数は、HTTPメソッドを指定します。通常のリクエストにはGETが使われます。URLでリクエストするリソースをすべて表せて、リクエストによりサーバー側に副作用がなく、サーバーのレスポンスがキャッシュ可能であればGETリクエストを使うのが適切です。POSTはフォームデータの送信をするときに使います。
第2引数は、ファイルのURLを指定します。
第3引数は省略可能ですが true で非同期通信、false で同期通信をします。リクエストが完了して、成功した場合 .responseText メソッドを使ってテーブル出力関数に渡しています。

loadCSV.js

window.onload = function() {
  function getText(path) {
    var request = new XMLHttpRequest();  // 新しいリクエストを作成する
    request.open("GET", path, true);    // 取得するファイルパスを指定する
    request.onreadystatechange = function() { // イベントリスナーを定義
      // リクエストが完了し、成功した場合。
      if (request.readyState === 4 && request.status === 200) {
        var type = request.getResponseHeader("Content-Type");
        if (type.match(/^text/))
          parseCSV(request.responseText); // コールバック関数に渡す
      }
    };
    request.send(null);  // ここでリクエストを送信する
  }
  function parseCSV(str) {
    var CR = String.fromCharCode(13);
    var LF = String.fromCharCode(10);
    var csvData = new Array();
    var lines = str.split(LF);
    for (var i = 0; i < lines.length; i++) {
      var cells = lines[i].split(",");
     if( cells.length != 1 ) csvData.push(cells);
    }
    var result = "<table>";
    for (var i = 0; i < csvData.length; i++) {
      result += "<tr>";
      for (var j = 0; j < csvData[i].length; j++) {
        result += "<td>";
        result += csvData[i][j];
        result += "</td>";
      }
      result += "</tr>";
    }
    result += "</table>";
    document.getElementById("result").innerHTML = result;
  }
  getText('./example.csv');
}
<html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 <script type="text/javascript" src="./loadCSV.js"></script>
 </head>
 <body>
 <div id="result"></div>
 </body>
 </html>

CSVファイルは文字化けしないように保存形式によって文字コードを指定しています。

参考URL:http://blog.cles.jp/item/2691

JavaScriptの座標変換の例

今回はJavaScriptの座標変換を使って正五角形をCanvasに描画してみました。

半径 r の円に内接する正五角形の円の中心から各辺に下した垂線の長さ [pmath]ay={{1+sqrt{5}}/{4}}r [/pmath] , 円の中心を原点として各辺の一辺の長さ[pmath]a=2ax={{sqrt{10-2sqrt{5}}}/{2}}r[/pmath] が既知としています。

https://stuffy.mydns.jp/~gusachan/javascript/pentagon.html

var c=document.getElementById("graph");
var ctx=c.getContext("2d");
var dgr =  Math.PI/180;
function pentagon() {
  var r = 160, ax, ay, bx, by;
  ax = -(Math.sqrt(10 - 2*Math.sqrt(5)))*r/4;
  ay = (1 + Math.sqrt(5))*r/4;
  bx = -ax;
  by = ay;
  ctx.beginPath();
  ctx.save();
  ctx.translate(200 + ax, 200 + ay);
  ctx.moveTo(0,0);
  leg();
  ctx.rotate(-72*dgr);
  leg();
  ctx.rotate(-72*dgr);
  leg();
  ctx.rotate(-72*dgr);
  leg();
  ctx.rotate(-72*dgr);
  leg();
  ctx.closePath();
  ctx.restore();
  function leg() {
    ctx.save();
    ctx.lineTo(2*bx,0);
    ctx.restore();
    ctx.translate(2*bx,0);
  }
}
pentagon();
ctx.stroke();
beginPath();
ctx.arc(200,200,160,0,360*dgr,false);
ctx.stroke();

円の中心を原点として五角形の左下隅の角の座標(ax, ay) =(-(Math.sqrt(10 – 2*Math.sqrt(5)))*r/4, -(1 + Math.sqrt(5))*r/4) をCanvasの座標の(左上隅を(0,0)とする)原点からtranslate(200 + ax, 200 + ay)) して始点とし、leg() 関数を呼び出して底辺を一回描画したのち、restore()で座標系変換を元に戻しtranslate(2*bx, 0)でレグの終点を(0,0) になるように移動してrotate(-72*dgr)で72°反時計回りに回転 、次の底辺の再描画~を4回繰り返してstroke()しています。

テキストではフラクタル雪片を再帰レベル4で描画していました。

振り子

回転関数の応用で振り子を作ってみました。振り子 の初期角度 rads(init)=π/6 に対して角運動量 rads(init)*Math.cos(rads(d)), (ただし角振動数、d = +5[°/100ms] )です。ここの所はアバウトにして正確な物理計算はしていません。

https://stuffy.mydns.jp/~gusachan/javascript/pendulum.html

var d = 0;
var c=document.getElementById("graph");
var ctx=c.getContext("2d");
var init = Number(document.getElementById('degree').value);
window.onload = function() {
  function rads(x) {
    return Math.PI*x/180;
  }
  function coordinate() {
    ctx.beginPath();
    ctx.moveTo(0,200);
    ctx.lineTo(400,200);
    ctx.moveTo(200,0);
    ctx.lineTo(200,400);
    ctx.closePath();
    ctx.stroke();
    ctx.beginPath();
    ctx.arc(200,200,150,0,rads(360),false);
    ctx.stroke();
  }
  function furiko() {
    var init = Number(document.getElementById('degree').value);
    d += 5;
    arg = rads(init)*Math.cos(rads(d))+rads(-90);
    ctx.clearRect(0,0,400,400);
    coordinate();
    ctx.beginPath();
    ctx.moveTo(200,200);
    ctx.lineTo(200 + 150*Math.cos(arg), 200 - 150*Math.sin(arg));
    ctx.closePath();
    ctx.stroke();
  }
  coordinate();
  setInterval(furiko, 100);
}

参考URL: http://www.daido-it.ac.jp/~harashin/pdf/note/10riki2_note9.pdf

pendulum_

 

アナログ時計

コードは以下。ポイントは、時刻を取得するvar now = new date(); をローカル関数のdgr() とdraw() の2か所で宣言、hand(d, r, w) 関数で針の角度と長さと太さの引数を渡して、短針と長針、秒針を描き分けています。それと前回の回転関数から x → 90-d と回転角を変換しています。setInterval(draw,1000) で1秒ごとに再描画しています。

https://stuffy.mydns.jp/~gusachan/javascript/clock.html

var c=document.getElementById("clock");
var ctx=c.getContext("2d");
window.onload = function() {
  var rads =  function(x) {
    return Math.PI*x/180;
  }
  var coordinate = function () {
    ctx.beginPath();
    ctx.lineWidth = 1;
    ctx.arc(200,200,150,0,rads(360),false);
    ctx.stroke();
  }
  var hand = function(d,r,w) {
    ctx.beginPath();
    ctx.moveTo(200,200);
    ctx.lineTo(200 + r*Math.cos(rads(90-d)), 200 - r*Math.sin(rads(90-d)));
    ctx.closePath();
    ctx.lineWidth = w;
    ctx.stroke();
  }
  var dgr = function(needle) {
      var now = new Date(); 
      if (needle == 'hours') {
        var arg = 30*((now.getHours()%12) + (now.getMinutes()/60));
      }
      else if (needle =='minutes') {
        var arg = 6*now.getMinutes();
      }
      else if (needle =='seconds') {
        var arg = 6*now.getSeconds();
      }
      return arg;
  }
  function draw() {
    var now = new Date();   // (追記:ここの宣言はなくても動いた
    ctx.clearRect(0,0,400,400);
    hand(dgr('hours'),110,4);
    hand(dgr('minutes'),140,2);
    hand(dgr('seconds'),130,1);
    coordinate();
  }
  setInterval(draw,1000);
}

clock

値の変換

JavaScript では、Number()で数値以外の文字列を数値に変換しようとすると、関数はNaNを返します。NaNをtypeof演算子で判定しようとしても’number’と判定されて上手く行きません。テキストボックスから入力された値をgetElementByIdで受け取るときに、数値か文字列かを判定するには isFinite関数を使って

if (isFinite(arg)) {
  (処理)
}
else {
  alert('半角数値を入力してください!');
  return false;
}

と例外処理します。

変換先
文字列 数値 論理値 オブジェクト
undifined
null
“undifined”
“null”
NaN
0
false
false
TypeError 例外
TypeError 例外
true
false
“true”
“false”
1
0
new Boolean(true)
new Boolean(false)
“”(空文字列)
“1.2”(数値文字列)
“one”
(数値以外の文字列)
0
1.2
NaN
false
true
true
new String(“”)
new String(“1.2”)
new String(“one”)
0
-0
NaN
Infinity
-Infinity
1(有限値, 0以外)
“0”
“0”
“NaN”
“Infinity”
“-Infinity”
“1”
false
false
false
true
true
true
new Number(0)
new Number(-0)
new Number(NaN)
new Number(Infinity)
new Number(-Infinity)
new Number(1)

追記)JavaScript Good Parts 「良いパーツによるベストプラクティス」に興味深い記述がありましたので転載します。
JavaScript は、isNaN 関数を提供しており、これを使えば数値とNaN を区別することができる。

isNaN(NaN)  // true
isNaN(0)    // false
isNaN(‘oops’)  // true
isNaN(‘0’)   // false

isFinite 関数は値が利用可能な数値であるかを調べるもっともよい方法だ。なぜならこの関数は、NaN と Infinity をどちらも false と判断してくれるからである。しかし、残念なことに、isFinite は与えられたオペランドをまず数値に変換しようとしてしまう。したがって調べたい値が数値型ではなかった場合には、これは良いテスト方法とは言えない。もしかしたらあなたは、isNumber 関数を自分で定義したくなるかもしれない。

var isNumber = function isNumber(value) {
  return typeof value === 'number' && isFinite(value);
};