文字の色を虹色に変化させるスクリプトを書いてみた。またくだらないものを書いてしまった。
function getColor (n) {
  const M = 255;
  let c = n % 360 / 60 | 0;
  let x = n % 60 / 60 * M |0;
  let y = M - x;
  let [r,g,b]=[[M,0,y],[M,x,0],[y,M,0],[0,M,x],[0,y,M],[x,0,M]][c];
  return 'rgb(' + r + ',' + g + ',' + b +')';
}


{
  let e = document.querySelector('#hoge');
  let c = e.textContent.split('');
  e.innerText = null;
  c.forEach (c=>e.appendChild(document.createElement('span')).textContent=c);
  let ss = [...document.querySelectorAll ('span')];
  let col = 0;

  function loop () {
    for (let i = 0; i < ss.length; i += 1) {
      ss[i].style.color = getColor (col + i*2);
    }
    col = (col + 1) % 360;
  }
  setInterval (loop, 10);
}

Test

 

JavaScript 行列演算

let a =[[1,2],
        [3,4]];
       
let b =[[5,6],
        [7,8]];

let r =[[19,22]
        [43,50]];

//行列の加算        
function add (a, i) {
  let b = this[i];
  return a.map ((a, j) => a + b[j]);
}

//行列の減算
function sub (a, i) {
  let b = this[i];
  return a.map ((a, j) => a - b[j]);
}

//行列の積
function mult (a) {
  let b = this;
  return b[0].map ((_,j)=> a.reduce ((d,e,f)=> d + e * b[f][j], 0));
}

//転置
function transpose (_, i, b) {
  return b.map ((_, j)=> b[j][i])
}



let d = a.map (mult, b);

console.log (d);

JavaScript: サーバーの時間を取得する

問題があるとすれば、

  1. 同期で行っていること
  2. リクエスト返ってくるまでの時間差を加味したこと
//サーバーの時間を取得する
function getUTCDateByServer () {
  let xhr = new XMLHttpRequest(), tm0, tm1, tm2;

  xhr.open("GET", "#", false);
  tm0 = new Date; xhr.send (null);
  tm1 = new Date (xhr.getResponseHeader('Date'));
  tm2 = new Date;

  return new Date ((+tm1) + ((+tm2)-(+tm0)) / 2);
}

JavaScript: innerHTML したときに中に含まれる script が実行されない件

function setInnerHTML (node, text) {
  node.innerHTML = text;
  let script = node.querySelectorAll ('script');

  if (script.length) {
    let
      doc = node.ownerDocument,
      org = doc.createElement ('script');

    for (let s of script) {
      let new_script = org.cloneNode (false);
      new_script.textContent = s.textContent;
      s.parentNode.replaceChild (new_script, s);
    }
    
    org = null;
  } 
}

ノードに innerHTML で挿入した後、その中から script ノードを抜き出す。
新しく作ったノードに中身をコピーして、元の script ノードと置き換える

ベジェ曲線を理解する

その前に線分を式にする。端点(p0, p1)とする。

L(t)=(1-t)P_0 + tP_1,  0 < t < 1

この式は実際の線分の長さはどうであれ t が0から1の範囲で線分上の任意の点を表せるようにするという意味である。
これをJavaScript で関数にすると以下のようになる。t の変化は 0.01 単位。

function line (p0, p1) {
  let rst = [ ];
  for (let t = 0; t <= 1; t += 0.01) {
    let pt = (1-t) * p0 + t * p1;
    rst.push (pt);
  }
  return rst;
}

これは関数の中で変数 t を変化させている。この t を関数の外から指定できるようにする

function line (p0, p1) {
  return function (t) {
    return (1-t) * p0 + t * p1;
  };
}
//__
let
  p0 = 0, p1 = 1,
  rst = [ ],
  p = line (p0, p1);

for (let t = 0; t <= 1; t += 0.01) {
  rst.push (p (t));
}

実際には平面上で直線を扱う場合、x座標とy座標の2つの次元が必要になるので
この関数の引数 a と b を配列にして n 次元の計算ができるように拡張する

function line ([...a], [...b]) {
  return  (t) => {
    let u = 1 - t;
    return a.map ((a,i) => u * a + b[i] * t);
  };
}
//__
let
  p0 = [0], p1 = [1],
  rst = [ ],
  p = line (p0, p1);

for (let t = 0; t <= 1; t += 0.01) {
  rst.push (p (t));
}

postd.cc

曲線を理解する

上の記事にあるSVGを丸パクリしたが、この図を見てベジェ曲線を理解する
点(p0)から点(p1)まで t で変化する点(pt0) と、
点(p1)から点(p2)まで t で変化する点(pt1) を
結ぶ直線を、これまた t で求めた点(Pt2)をなぞると2次ベジェ曲線となる


P 0 P 1 P 2 P t0 P t1 P t2

上の図をもとにプログラムを書く

const line =([...a],[...b])=>(t,u)=>(u=1-t,a.map((a,i)=>u*a+b[i]*t));
//__
let
  p0 = [0, 0], p1 = [550, 100], p2 = [550, 0];
  rst = [ ],
  L01 = line (p0, p1),
  L12 = line (p1, p2);

for (let t = 0; t <= 1; t += 0.01) {
  let
    pt0 = L01 (t), 
    pt1 = L12 (t), 
    pt2 = line (pt0, pt1) (t);
  rst.push (pt2);
}

3次のベジェ曲線

まず点(p0)、点(p1)、そして点(p2)をもとにベジェ曲線を描く(赤い点線)。
次に点(p1)、点(p2)、新たに追加した点(p3)をもとにベジェ曲線を描く(緑の点線)。
赤い点線上の点(pt2)と緑の点線上の点(pt3)と結ぶ直線(緑の線)を点(pt4)をとする
その点(pt4)の軌跡が、3次ベジェ曲線となる。


P 0 P 1 P 2 P 3 P t2 P t3 P t4

const line =([...a],[...b])=>(t,u)=>(u=1-t,a.map((a,i)=>u*a+b[i]*t));
//__
let
  [p0, p1, p2, p3] = [[50, 50], [50, 150], [550, 50], [550,150]],
  rst = [ ],
  L01 = line (p0, p1),
  L12 = line (p1, p2),
  L23 = line (p2, p3);

for (let t = 0; t <= 1; t += 0.01) {
  let
    pt01 = L01 (t), 
    pt12 = L12 (t),
    pt23 = L23 (t), 
    pt2 = line (pt01, pt12) (t),
    pt3 = line (pt12, pt23) (t),
    pt4 = line (pt2, pt3) (t); 
  rst.push (pt4);
}

JavaScript: Promise を理解する

順不同の工程を順序立てて行わせるときにい使うもの

let obj = new Promise (func);

--

関数 func には実行したい処理を書くのだが、2つの処理用の関数を
引数として受け取らなければならない。1つは、成功したあとに行う関数、
もう1つは失敗したときの関数。なので実行したい関数 func は以下の
ような書き方をする

function hoge (seikou, sippai) {
  //適当な処理
  // new Promise(hoge) ;が実行されるだけで関数hogeも実行される
  成功? seikou (123):  sippai (456);
}

ここで適当な処理を他の関数に丸投げしたい場合には、seikou関数と
sippai 関数を渡してやらなければならない。

function hoge (seikou, sippai) {
  marunage (seikou, sippai);
}

 function marunage (seikou, sippai) {
  //丸投げされた処理
  成功? seikou (123):  sippai (456);
}

関数 seikou が呼ばれた後に処理を実行したい場合

obj.then (/*後処理の関数*/);

 

JavaScript: fetch でテキストを読み込む

fetch ('setupの手順.txt')
   .then (res => {
   if (res.oj) res.text (); //res.json ();
   else throw new Error (''Network response was not ok.');
})
   .then (function (txt) {
   console.log (txt);
  // console.log (JSON.stringify (txt));
})
   .catch (err => console.log (err));

 

SVG で描画してみる

<code>
  <svg width="800" height="800" xmlns="http://www.w3.org/2000/svg" id="hoge">
  </svg>
</code>

<script>
const
  doc = document,
  svg = document.querySelector ('#hoge'),
  { PI, sin, cos } = Math,
  cx = 400, cy = 400,
  polyline = doc.createElementNS ("http://www.w3.org/2000/svg", 'polyline'),
  style = 'fill:none; stroke: red; stroke-width: 1;';

const
  N = 3
  STEP = 4;

polyline.setAttribute ('style', style);

for (let r = 0; r < 400; r += STEP) {
  let
    point = [ ],
    poly  = polyline.cloneNode (true);

  for (let p = r; p < 360 + r; p += 360 / N) {
    let a = p * PI / 180;
    point.push ([cx + sin (a) * r, cy - cos (a) * r]);
  }
  point.push (point[0]);
  
  poly.setAttribute ('points', point.map (([x, y]) => `${x},${y}`).join (' '));
  svg.appendChild (poly);
}

</script>