20210112のJavaScriptに関する記事は26件です。

p5.jsで書ける図形まとめ

p5.jsで描ける図形についてまとめました。

この記事は以下の記事のp5.js版です。
Processing で描ける図形まとめ - Qiita

円・楕円

circle()ellipse() で描けます。
circleは直径を指定することでまんまるの円(正円、真円)が描けます。
ellipseは横の大きさと縦の大きさを別々に指定できるため、楕円が描けます。

01circle.png

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(0, height / 2, width, height / 2);
  line(width / 2, 0, width / 2, height);

  noFill();
  strokeWeight(2);

  // 赤い楕円
  stroke(200, 0, 0);
  ellipse(width / 2, height / 2, 350, 150);
  ellipse(width / 2, height / 2, 100, 300);

  // 青い正円
  stroke(0, 0, 200);
  circle(width / 2, height / 2, 250);
}

四角(長方形・正方形)

square()rect() で描けます。
squareは辺の長さを指定することで正方形が描けます。
rectは横の大きさと縦の大きさを別々に指定できるため、長方形が描けます。
rectMode() を使うと指定した座標が四角のどこの位置を指すのか変更できます。
デフォルトでは左上が指定されるので、 rectMode(CORNER) と同じ状態になります。

02rect.png

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(0, height / 2, width, height / 2);
  line(width / 2, 0, width / 2, height);

  noFill();
  strokeWeight(2);

  // 赤い長方形
  stroke(200, 0, 0);
  rectMode(CENTER);
  rect(width / 2, height / 2, 150, 300);

  //青い正方形
  stroke(0, 0, 200);
  square(width / 2, height / 2, 230);

  // 緑の長方形
  stroke(0, 200, 0);
  rectMode(CORNER);
  rect(width / 2, height / 2, 180, 100);
}

半円、パイカット図形

半円もしくはパイやピザをカットしたような図形は arc() で描けます。
オプションとしてOPEN(弧の線だけを描いて図形を閉じきらない)、CHORD(弧の線とその間の直線で図形を閉じきる)、PIE(弧と始点の間を線で結びピザのピース状に閉じきる)が指定できます。

03arc.png

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  strokeWeight(2);

  // 左上の赤い半円。線は閉じきっていない
  stroke(200, 0, 0);
  fill(200, 150, 150);
  arc(width / 2, height / 2, 250, 250, -PI, -PI / 2, OPEN);

  // 下の青い半円。線は閉じきっている
  stroke(0, 0, 200);
  fill(150, 150, 200);
  arc(width / 2, height / 2, 250, 250, 0, PI, CHORD);

  // 右上の緑のピース。線は始点を含めて閉じきっている
  stroke(0, 200, 0);
  fill(150, 200, 150);
  arc(width / 2, height / 2, 250, 250, radians(270), radians(320), PIE);
}

angleMode() を使って、角度の指定を度数法で書く方法もあります。

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  strokeWeight(2);

  // 左上の赤い半円。線は閉じきっていない
  stroke(200, 0, 0);
  fill(200, 150, 150);
  arc(width / 2, height / 2, 250, 250, -180, -90, OPEN);

  // 下の青い半円。線は閉じきっている
  stroke(0, 0, 200);
  fill(150, 150, 200);
  arc(width / 2, height / 2, 250, 250, 0, 180, CHORD);

  // 右上の緑のピース。線は始点を含めて閉じきっている
  stroke(0, 200, 0);
  fill(150, 200, 150);
  arc(width / 2, height / 2, 250, 250, 270, 320, PIE);
}

三角形

triangle() で描く方法もありますが、
beginShape()endShape()vertex() を使って描くと扱いやすいのでオススメです。

04triangle.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 灰色の円
  stroke(200);
  ellipse(width / 2, height / 2, 150 * 2, 150 * 2);

  // 三角形
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawTriangle(width / 2, height / 2, 150); // 横の位置、縦の位置、円の半径
}

function drawTriangle(x, y, r) {
  push();
  translate(x, y); // 中心となる座標
  rotate(-90);

  // 円を均等に3分割する点を結び、三角形をつくる
  beginShape();
  for (let i = 0; i < 3; i++) {
    vertex(r * cos(360 * i / 3), r * sin(360 * i / 3));
  }
  endShape(CLOSE);

  pop();
}

ひし形

beginShape()endShape()vertex() で描けます。

05hishigata.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // ひし形
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawDiamond(width / 2, height / 2, 150); // 横の位置、縦の位置、中心点と中心から遠い頂点までの距離
}

function drawDiamond(x, y, r) {
  let R;

  push();
  translate(x, y);

  beginShape();
  for (let i = 0; i < 4; i++) {
    if (i % 2 == 0) {
      R = r / 2;
    } else {
      R = r;
    }
    vertex(R * cos(90 * i), R * sin(90 * i));
  }
  endShape(CLOSE);

  pop();
}

三項演算子を使ってすっきり書くこともできます。

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // ひし形
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawDiamond(width / 2, height / 2, 150); // 横の位置、縦の位置、中心点と中心から遠い頂点までの距離
}

function drawDiamond(x, y, r) {
  push();
  translate(x, y);

  beginShape();
  for (let i = 0; i < 4; i++) {
    let R = i % 2 == 0 ? r / 2 : r;

    vertex(R * cos(90 * i), R * sin(90 * i));
  }
  endShape(CLOSE);

  pop();
}

正多角形

シンプルな書き方

正五角形、正六角形、…正n角形は beginShape()endShape()vertex() を使って描けます。

正六角形を描く例 :

06takakukei_simple.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 正六角形
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawPolygon(width / 2, height / 2, 150, 6); // 横の位置、縦の位置、中心点と頂点までの距離、頂点数
}

function drawPolygon(x, y, r, vertexNum) {
  push();
  translate(x, y);

  beginShape();
  for (let i = 0; i < vertexNum; i++) {
    vertex(r * cos(360 * i / vertexNum), r * sin(360 * i / vertexNum));
  }
  endShape(CLOSE);

  pop();
}

数式を使った書き方

数式を利用して書く方法もあります。
数式は以下のページを参考にしました。
Parametric equation of a regular pentagon – GeoGebra
正多角形とスピログラフの数式 | シキノート

p5.jsにおいては、見た目は先述のシンプルな書き方とあまり変わらないように見えました。

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 正六角形
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawPolygon(width / 2, height / 2, 150, 6); // 横の位置、縦の位置、中心点と頂点までの距離、頂点数
}

function drawPolygon(ox, oy, r, vertexNum) {
  push();
  translate(ox, oy);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let pos = calcPos(r, theta, vertexNum);

    let x = pos.x;
    let y = pos.y;

    vertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

function calcPos(r, t, num) {
  let x = r * cos(t) * func(t, num);
  let y = r * sin(t) * func(t, num);
  let vec = createVector(x, y);

  return vec;
}

function func(t, num) {
  let A = cos(180 / num);
  let b = 360 / num;
  let B = cos(b * (t / b - floor(t / b)) - 180 / num);

  return A / B;
}

シンプルな描き方

星は beginShape()endShape()vertex() を使って描けます。
トゲの数も調整できます。

トゲの数が5つの例 :

07star.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 星
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawStar(width / 2, height / 2, 150, 5); // 横の位置、縦の位置、中心点とトゲの頂点までの距離、トゲの数
}

function drawStar(x, y, r, prickleNum) {
  let vertexNum = prickleNum * 2; // 頂点数(トゲの数*2)
  let R; // 中心点から頂点までの距離

  push();
  translate(x, y);
  rotate(-90);

  beginShape();
  for (let i = 0; i < vertexNum; i++) {
    R = i % 2 == 0 ? r : r / 2;

    vertex(R * cos(360 * i / vertexNum), R * sin(360 * i / vertexNum));
  }
  endShape(CLOSE);

  pop();
}

数式を使った書き方

数式を利用して書く方法もあります。
数式は以下のページを参考にしました。
正多角形とスピログラフの数式 | シキノート

p5.jsにおいては、見た目は先述のシンプルな書き方とあまり変わらないように見えました。

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 星
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawStar(width / 2, height / 2, 150, 5); // 横の位置、縦の位置、中心点とトゲの頂点までの距離、トゲの数
}

function drawStar(ox, oy, r, prickleNum) {
  push();
  translate(ox, oy);
  rotate(-90);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let pos = calcPos(r, theta, prickleNum);

    let x = pos.x;
    let y = pos.y;

    vertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

function calcPos(r, t, num) {
  let x = r * cos(t) * func(t, num);
  let y = r * sin(t) * func(t, num);
  let vec = createVector(x, y);

  return vec;
}

function func(t, num) {
  let a = 360 / num;
  let A = cos(a);
  let b = acos(cos(num * t));
  let B = cos(a - b / num);

  return A / B;
}

キラキラ星(アステロイド曲線 1)

キラキラな星はアステロイド曲線と呼ばれ、 beginShape()endShape()vertex() を使って描けます。
図形を縦方向に大きめに描くとよりそれらしくなります。

08kirakira.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // アステロイド曲線
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawTwinkleStar(width / 2, height / 2, 120); // 横の位置、縦の位置、中心点と横方向の頂点までの距離
}

function drawTwinkleStar(x, y, r) {
  push();
  translate(x, y);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    vertex(r * pow(cos(theta), 3), r * 1.4 * pow(sin(theta), 3));
  }
  endShape(CLOSE);

  pop();
}

びっくり吹き出し(アステロイド曲線 2)

漫画でよく見かける
_人人人人人人人人人人_
> びっくり吹き出し <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y ̄
はアステロイド曲線で表現でき、 beginShape()endShape()vertex() を使って描けます。

09bikkuri.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // アステロイド曲線
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  strokeJoin(ROUND);
  drawAstroid(width / 2, height / 2, 20, 8); // 横の位置、縦の位置、大きさ調整用変数、トゲの数
}

function drawAstroid(ox, oy, r, vertexNum) {
  vertexNum -= 1;

  push();
  translate(ox, oy);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let x = r * (vertexNum * cos(theta) + cos(-vertexNum * theta));
    let y = r * (vertexNum * sin(theta) + sin(-vertexNum * theta));

    vertex(x, y);
  }
  endShape();

  pop();
}

ハート

ハートは beginShape()endShape()vertex() を使って描けます。
strokeJoin() を利用して線のつなぎ目をなめらかにしています。

10heart.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // ハート
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  strokeJoin(ROUND); //線のつなぎ目について設定
  drawHeart(width / 2, height / 2, 8); // 横の位置、縦の位置、大きさ調整用変数
}

function drawHeart(ox, oy, size) {
  push();
  translate(ox, oy);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let x = size * (16 * sin(theta) * sin(theta) * sin(theta));
    let y = (-1) * size * (13 * cos(theta) - 5 * cos(2 * theta) -
      2 * cos(3 * theta) - cos(4 * theta));

    vertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

お花は beginShape()endShape()vertex() を使って描けます。

11flower.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 花
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawFlower(width / 2, height / 2, 100); // 横の位置、縦の位置、大きさ調整用変数
}

function drawFlower(ox, oy, r) {
  push();
  translate(ox, oy);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let R = r * abs(sin(theta * 5)) + r / 2;
    let x = R * cos(theta);
    let y = R * sin(theta);

    curveVertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

花びらが分かれているタイプ

花びらがそれぞれ分かれていて、先端に鋭い切れ込みの入った桜の花は、 beginShape()endShape()vertex() を使って描けます。
数式は以下の記事を参考にさせていただきました。
花の曲線を描く - CinderellaJapan

12sakura_01kirekomi.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 桜
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawSakura(width / 2, height / 2, 200); // 横の位置、縦の位置、大きさ調整用変数
}

function drawSakura(ox, oy, or) {
  let petalNum = 5; // 花びらの数

  push();
  translate(ox, oy);
  rotate(90);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let A = petalNum / 180 * theta;
    let md = floor(A) % 2;
    let r = pow(-1, md) * (A - floor(A)) + md;
    let R = r + 2 * calcH(r);

    let x = or * R * cos(theta);
    let y = or * R * sin(theta);

    vertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

function calcH(x) {
  if (x < 0.8) {
    return 0;
  } else {
    return 0.8 - x;
  }
}

花びらが分かれていないタイプ

花びらが分かれていない、丸みのある桜の花は、 beginShape()endShape()vertex() を使って描けます。
数式は以下の記事を参考にさせていただきました。
~スーパーバラ曲線を作ろう~

12sakura_02simple.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 桜
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawSakura(width / 2, height / 2, 130); // 横の位置、縦の位置、大きさ調整用変数
}

function drawSakura(ox, oy, or) {
  let petalNum = 5; // 花びらの数

  push();
  translate(ox, oy);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let A = (sin(theta * 5) + cos(theta * 10)) / 2.0;
    let B = A * 0.5 + 1.0;
    let R = or * B;

    let x = R * sin(theta + 90);
    let y = R * cos(theta + 90);

    vertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

function calcH(x) {
  if (x < 0.8) {
    return 0;
  } else {
    return 0.8 - x;
  }
}

葉 (麻の葉、紅葉、楓)

葉っぱは beginShape()endShape()vertex() を使って描けます。

13leaf.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 葉っぱ
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  noFill();
  drawLeaf(width / 2, height / 2, 45); // 横の位置、縦の位置、大きさ調整用変数
}

function drawLeaf(ox, oy, r) {
  push();
  translate(ox, oy);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let R = -r * (1 + (9.0 / 10.0) * cos(8 * theta)) * (1 + (1.0 / 10.0) * cos(24 * theta)) * ((9.0 / 10.0) + (1.0 / 10.0) * cos(200 * theta)) * (1 + sin(theta));

    let x = R * cos(theta);
    let y = R * sin(theta);

    vertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

しずく

涙のようなしずく型の図形は beginShape()endShape()vertex() を使って描けます。
コード中、Aという変数がありますが、この値を小さくすると丸みのある形になり、大きくすると細く鋭い形になります。

14drop.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // しずく
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawDrop(width / 2, height / 2, 180, 5); // 横の位置、縦の位置、大きさ調整用変数、鋭さ調整用変数
}

function drawDrop(x, y, r, A) {
  push();
  translate(x, y);
  rotate(-90);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let R = r / (A * sin(theta / 2) + 1);

    vertex(R * cos(theta), R * sin(theta));
  }
  endShape(CLOSE);

  pop();
}

魚の形は beginShape()endShape()vertex() を使って描けます。
数式は以下のページを参考にしました。
Fish curve - Wikipedia

15fish.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 魚
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawFish(width / 2, height / 2, 150); // 横の位置、縦の位置、大きさ調整用変数
}

function drawFish(ox, oy, r) {
  push();
  translate(ox, oy);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let x = r * cos(theta) - r * pow(sin(theta), 2) / sqrt(2);
    let y = r * cos(theta) * sin(theta);

    vertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

穴あき図形

beginContour()、endContour()を使った書き方

ドーナツのように穴のあいた図形は beginContour()beginShape()endShape()vertex()endContour() を使って描けます。

16anaaki_01con.png

let R; // 星(穴)の大きさ調整用
const vertexNum = 10; // 星の頂点数

const w = 300; // 図形の外枠の横の長さ
const h = 300; // 図形の外枠の縦の長さ

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(0, height / 2, width, height / 2);
  line(width / 2, 0, width / 2, height);

  // 星形穴あき図形
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  fill(200, 100, 100);

  push();
  translate(width / 2, height / 2);
  rotate(-90);

  beginShape();
  vertex(-w / 2, -h / 2);
  vertex(w / 2, -h / 2);
  vertex(w / 2, h / 2);
  vertex(-w / 2, h / 2);
  beginContour();
  for (let i = vertexNum; i > 0; i--) {
    R = i % 2 == 0 ? w * 0.4 : w * 0.2;

    vertex(R * cos(360 * i / vertexNum), R * sin(360 * i / vertexNum));
  }
  endContour();
  endShape(CLOSE);

  pop();
}

erase()を使った書き方

p5.jsでは createGraphics()erase() の組み合わせでも穴あき図形が描けます。

16anaaki_02erase.png

let R; // 星(穴)の大きさ調整用
const vertexNum = 10; // 星の頂点数

const w = 300; // 図形の外枠の横の長さ
const h = 300; // 図形の外枠の縦の長さ

let pg; // 図形の外枠を描くためのgraphics用

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);

  // 画像の基準点を中央に変更
  imageMode(CENTER);

  // 四角いgraphicsを生成
  pg = createGraphics(w, h);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(0, height / 2, width, height / 2);
  line(width / 2, 0, width / 2, height);

  // pgに対して描画
  pg.angleMode(DEGREES);
  pg.background(200, 100, 100);

  // 以降の描画はpgから削除される
  pg.erase();

  // 星型の図形を描画
  pg.push();

  pg.translate(pg.width / 2, pg.height / 2);
  pg.rotate(-90);

  pg.beginShape();
  for (let i = vertexNum; i > 0; i--) {
    R = i % 2 == 0 ? w * 0.4 : w * 0.2;

    pg.vertex(R * cos(360 * i / vertexNum), R * sin(360 * i / vertexNum));
  }
  pg.endShape(CLOSE);

  pg.pop();

  // pgを表示
  image(pg, width / 2, height / 2);
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

p5.jsで描ける図形まとめ

p5.jsで描ける図形についてまとめました。

この記事は以下の記事のp5.js版です。
Processing で描ける図形まとめ - Qiita

円・楕円

circle()ellipse() で描けます。
circleは直径を指定することでまんまるの円(正円、真円)が描けます。
ellipseは横の大きさと縦の大きさを別々に指定できるため、楕円が描けます。

01circle.png

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(0, height / 2, width, height / 2);
  line(width / 2, 0, width / 2, height);

  noFill();
  strokeWeight(2);

  // 赤い楕円
  stroke(200, 0, 0);
  ellipse(width / 2, height / 2, 350, 150);
  ellipse(width / 2, height / 2, 100, 300);

  // 青い正円
  stroke(0, 0, 200);
  circle(width / 2, height / 2, 250);
}

四角(長方形・正方形)

square()rect() で描けます。
squareは辺の長さを指定することで正方形が描けます。
rectは横の大きさと縦の大きさを別々に指定できるため、長方形が描けます。
rectMode() を使うと指定した座標が四角のどこの位置を指すのか変更できます。
デフォルトでは左上が指定されるので、 rectMode(CORNER) と同じ状態になります。

02rect.png

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(0, height / 2, width, height / 2);
  line(width / 2, 0, width / 2, height);

  noFill();
  strokeWeight(2);

  // 赤い長方形
  stroke(200, 0, 0);
  rectMode(CENTER);
  rect(width / 2, height / 2, 150, 300);

  //青い正方形
  stroke(0, 0, 200);
  square(width / 2, height / 2, 230);

  // 緑の長方形
  stroke(0, 200, 0);
  rectMode(CORNER);
  rect(width / 2, height / 2, 180, 100);
}

半円、パイカット図形

半円もしくはパイやピザをカットしたような図形は arc() で描けます。
オプションとしてOPEN(弧の線だけを描いて図形を閉じきらない)、CHORD(弧の線とその間の直線で図形を閉じきる)、PIE(弧と始点の間を線で結びピザのピース状に閉じきる)が指定できます。

03arc.png

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  strokeWeight(2);

  // 左上の赤い半円。線は閉じきっていない
  stroke(200, 0, 0);
  fill(200, 150, 150);
  arc(width / 2, height / 2, 250, 250, -PI, -PI / 2, OPEN);

  // 下の青い半円。線は閉じきっている
  stroke(0, 0, 200);
  fill(150, 150, 200);
  arc(width / 2, height / 2, 250, 250, 0, PI, CHORD);

  // 右上の緑のピース。線は始点を含めて閉じきっている
  stroke(0, 200, 0);
  fill(150, 200, 150);
  arc(width / 2, height / 2, 250, 250, radians(270), radians(320), PIE);
}

angleMode() を使って、角度の指定を度数法で書く方法もあります。

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  strokeWeight(2);

  // 左上の赤い半円。線は閉じきっていない
  stroke(200, 0, 0);
  fill(200, 150, 150);
  arc(width / 2, height / 2, 250, 250, -180, -90, OPEN);

  // 下の青い半円。線は閉じきっている
  stroke(0, 0, 200);
  fill(150, 150, 200);
  arc(width / 2, height / 2, 250, 250, 0, 180, CHORD);

  // 右上の緑のピース。線は始点を含めて閉じきっている
  stroke(0, 200, 0);
  fill(150, 200, 150);
  arc(width / 2, height / 2, 250, 250, 270, 320, PIE);
}

三角形

triangle() で描く方法もありますが、
beginShape()endShape()vertex() を使って描くと扱いやすいのでオススメです。

04triangle.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 灰色の円
  stroke(200);
  ellipse(width / 2, height / 2, 150 * 2, 150 * 2);

  // 三角形
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawTriangle(width / 2, height / 2, 150); // 横の位置、縦の位置、円の半径
}

function drawTriangle(x, y, r) {
  push();
  translate(x, y); // 中心となる座標
  rotate(-90);

  // 円を均等に3分割する点を結び、三角形をつくる
  beginShape();
  for (let i = 0; i < 3; i++) {
    vertex(r * cos(360 * i / 3), r * sin(360 * i / 3));
  }
  endShape(CLOSE);

  pop();
}

ひし形

beginShape()endShape()vertex() で描けます。

05hishigata.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // ひし形
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawDiamond(width / 2, height / 2, 150); // 横の位置、縦の位置、中心点と中心から遠い頂点までの距離
}

function drawDiamond(x, y, r) {
  let R;

  push();
  translate(x, y);

  beginShape();
  for (let i = 0; i < 4; i++) {
    if (i % 2 == 0) {
      R = r / 2;
    } else {
      R = r;
    }
    vertex(R * cos(90 * i), R * sin(90 * i));
  }
  endShape(CLOSE);

  pop();
}

三項演算子を使ってすっきり書くこともできます。

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // ひし形
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawDiamond(width / 2, height / 2, 150); // 横の位置、縦の位置、中心点と中心から遠い頂点までの距離
}

function drawDiamond(x, y, r) {
  push();
  translate(x, y);

  beginShape();
  for (let i = 0; i < 4; i++) {
    let R = i % 2 == 0 ? r / 2 : r;

    vertex(R * cos(90 * i), R * sin(90 * i));
  }
  endShape(CLOSE);

  pop();
}

正多角形

シンプルな書き方

正五角形、正六角形、…正n角形は beginShape()endShape()vertex() を使って描けます。

正六角形を描く例 :

06takakukei_simple.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 正六角形
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawPolygon(width / 2, height / 2, 150, 6); // 横の位置、縦の位置、中心点と頂点までの距離、頂点数
}

function drawPolygon(x, y, r, vertexNum) {
  push();
  translate(x, y);

  beginShape();
  for (let i = 0; i < vertexNum; i++) {
    vertex(r * cos(360 * i / vertexNum), r * sin(360 * i / vertexNum));
  }
  endShape(CLOSE);

  pop();
}

数式を使った書き方

数式を利用して書く方法もあります。
数式は以下のページを参考にしました。
Parametric equation of a regular pentagon – GeoGebra
正多角形とスピログラフの数式 | シキノート

p5.jsにおいては、見た目は先述のシンプルな書き方とあまり変わらないように見えました。

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 正六角形
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawPolygon(width / 2, height / 2, 150, 6); // 横の位置、縦の位置、中心点と頂点までの距離、頂点数
}

function drawPolygon(ox, oy, r, vertexNum) {
  push();
  translate(ox, oy);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let pos = calcPos(r, theta, vertexNum);

    let x = pos.x;
    let y = pos.y;

    vertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

function calcPos(r, t, num) {
  let x = r * cos(t) * func(t, num);
  let y = r * sin(t) * func(t, num);
  let vec = createVector(x, y);

  return vec;
}

function func(t, num) {
  let A = cos(180 / num);
  let b = 360 / num;
  let B = cos(b * (t / b - floor(t / b)) - 180 / num);

  return A / B;
}

シンプルな描き方

星は beginShape()endShape()vertex() を使って描けます。
トゲの数も調整できます。

トゲの数が5つの例 :

07star.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 星
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawStar(width / 2, height / 2, 150, 5); // 横の位置、縦の位置、中心点とトゲの頂点までの距離、トゲの数
}

function drawStar(x, y, r, prickleNum) {
  let vertexNum = prickleNum * 2; // 頂点数(トゲの数*2)
  let R; // 中心点から頂点までの距離

  push();
  translate(x, y);
  rotate(-90);

  beginShape();
  for (let i = 0; i < vertexNum; i++) {
    R = i % 2 == 0 ? r : r / 2;

    vertex(R * cos(360 * i / vertexNum), R * sin(360 * i / vertexNum));
  }
  endShape(CLOSE);

  pop();
}

数式を使った書き方

数式を利用して書く方法もあります。
数式は以下のページを参考にしました。
正多角形とスピログラフの数式 | シキノート

p5.jsにおいては、見た目は先述のシンプルな書き方とあまり変わらないように見えました。

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 星
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawStar(width / 2, height / 2, 150, 5); // 横の位置、縦の位置、中心点とトゲの頂点までの距離、トゲの数
}

function drawStar(ox, oy, r, prickleNum) {
  push();
  translate(ox, oy);
  rotate(-90);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let pos = calcPos(r, theta, prickleNum);

    let x = pos.x;
    let y = pos.y;

    vertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

function calcPos(r, t, num) {
  let x = r * cos(t) * func(t, num);
  let y = r * sin(t) * func(t, num);
  let vec = createVector(x, y);

  return vec;
}

function func(t, num) {
  let a = 360 / num;
  let A = cos(a);
  let b = acos(cos(num * t));
  let B = cos(a - b / num);

  return A / B;
}

キラキラ星(アステロイド曲線 1)

キラキラな星はアステロイド曲線と呼ばれ、 beginShape()endShape()vertex() を使って描けます。
図形を縦方向に大きめに描くとよりそれらしくなります。

08kirakira.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // アステロイド曲線
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawTwinkleStar(width / 2, height / 2, 120); // 横の位置、縦の位置、中心点と横方向の頂点までの距離
}

function drawTwinkleStar(x, y, r) {
  push();
  translate(x, y);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    vertex(r * pow(cos(theta), 3), r * 1.4 * pow(sin(theta), 3));
  }
  endShape(CLOSE);

  pop();
}

びっくり吹き出し(アステロイド曲線 2)

漫画でよく見かける
_人人人人人人人人人人_
> びっくり吹き出し <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y ̄
はアステロイド曲線で表現でき、 beginShape()endShape()vertex() を使って描けます。

09bikkuri.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // アステロイド曲線
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  strokeJoin(ROUND);
  drawAstroid(width / 2, height / 2, 20, 8); // 横の位置、縦の位置、大きさ調整用変数、トゲの数
}

function drawAstroid(ox, oy, r, vertexNum) {
  vertexNum -= 1;

  push();
  translate(ox, oy);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let x = r * (vertexNum * cos(theta) + cos(-vertexNum * theta));
    let y = r * (vertexNum * sin(theta) + sin(-vertexNum * theta));

    vertex(x, y);
  }
  endShape();

  pop();
}

ハート

ハートは beginShape()endShape()vertex() を使って描けます。
strokeJoin() を利用して線のつなぎ目をなめらかにしています。

10heart.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // ハート
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  strokeJoin(ROUND); //線のつなぎ目について設定
  drawHeart(width / 2, height / 2, 8); // 横の位置、縦の位置、大きさ調整用変数
}

function drawHeart(ox, oy, size) {
  push();
  translate(ox, oy);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let x = size * (16 * sin(theta) * sin(theta) * sin(theta));
    let y = (-1) * size * (13 * cos(theta) - 5 * cos(2 * theta) -
      2 * cos(3 * theta) - cos(4 * theta));

    vertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

お花は beginShape()endShape()vertex() を使って描けます。

11flower.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 花
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawFlower(width / 2, height / 2, 100); // 横の位置、縦の位置、大きさ調整用変数
}

function drawFlower(ox, oy, r) {
  push();
  translate(ox, oy);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let R = r * abs(sin(theta * 5)) + r / 2;
    let x = R * cos(theta);
    let y = R * sin(theta);

    curveVertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

花びらが分かれているタイプ

花びらがそれぞれ分かれていて、先端に鋭い切れ込みの入った桜の花は、 beginShape()endShape()vertex() を使って描けます。
数式は以下の記事を参考にさせていただきました。
花の曲線を描く - CinderellaJapan

12sakura_01kirekomi.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 桜
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawSakura(width / 2, height / 2, 200); // 横の位置、縦の位置、大きさ調整用変数
}

function drawSakura(ox, oy, or) {
  let petalNum = 5; // 花びらの数

  push();
  translate(ox, oy);
  rotate(90);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let A = petalNum / 180 * theta;
    let md = floor(A) % 2;
    let r = pow(-1, md) * (A - floor(A)) + md;
    let R = r + 2 * calcH(r);

    let x = or * R * cos(theta);
    let y = or * R * sin(theta);

    vertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

function calcH(x) {
  if (x < 0.8) {
    return 0;
  } else {
    return 0.8 - x;
  }
}

花びらが分かれていないタイプ

花びらが分かれていない、丸みのある桜の花は、 beginShape()endShape()vertex() を使って描けます。
数式は以下の記事を参考にさせていただきました。
~スーパーバラ曲線を作ろう~

12sakura_02simple.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 桜
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawSakura(width / 2, height / 2, 130); // 横の位置、縦の位置、大きさ調整用変数
}

function drawSakura(ox, oy, or) {
  let petalNum = 5; // 花びらの数

  push();
  translate(ox, oy);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let A = (sin(theta * 5) + cos(theta * 10)) / 2.0;
    let B = A * 0.5 + 1.0;
    let R = or * B;

    let x = R * sin(theta + 90);
    let y = R * cos(theta + 90);

    vertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

function calcH(x) {
  if (x < 0.8) {
    return 0;
  } else {
    return 0.8 - x;
  }
}

葉 (麻の葉、紅葉、楓)

葉っぱは beginShape()endShape()vertex() を使って描けます。

13leaf.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 葉っぱ
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  noFill();
  drawLeaf(width / 2, height / 2, 45); // 横の位置、縦の位置、大きさ調整用変数
}

function drawLeaf(ox, oy, r) {
  push();
  translate(ox, oy);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let R = -r * (1 + (9.0 / 10.0) * cos(8 * theta)) * (1 + (1.0 / 10.0) * cos(24 * theta)) * ((9.0 / 10.0) + (1.0 / 10.0) * cos(200 * theta)) * (1 + sin(theta));

    let x = R * cos(theta);
    let y = R * sin(theta);

    vertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

しずく

涙のようなしずく型の図形は beginShape()endShape()vertex() を使って描けます。
コード中、Aという変数がありますが、この値を小さくすると丸みのある形になり、大きくすると細く鋭い形になります。

14drop.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // しずく
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawDrop(width / 2, height / 2, 180, 5); // 横の位置、縦の位置、大きさ調整用変数、鋭さ調整用変数
}

function drawDrop(x, y, r, A) {
  push();
  translate(x, y);
  rotate(-90);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let R = r / (A * sin(theta / 2) + 1);

    vertex(R * cos(theta), R * sin(theta));
  }
  endShape(CLOSE);

  pop();
}

魚の形は beginShape()endShape()vertex() を使って描けます。
数式は以下のページを参考にしました。
Fish curve - Wikipedia

15fish.png

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(width / 2, 0, width / 2, height);
  line(0, height / 2, width, height / 2);

  // 魚
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  drawFish(width / 2, height / 2, 150); // 横の位置、縦の位置、大きさ調整用変数
}

function drawFish(ox, oy, r) {
  push();
  translate(ox, oy);

  beginShape();
  for (let theta = 0; theta < 360; theta++) {
    let x = r * cos(theta) - r * pow(sin(theta), 2) / sqrt(2);
    let y = r * cos(theta) * sin(theta);

    vertex(x, y);
  }
  endShape(CLOSE);

  pop();
}

穴あき図形

beginContour()、endContour()を使った書き方

ドーナツのように穴のあいた図形は beginContour()beginShape()endShape()vertex()endContour() を使って描けます。

16anaaki_01con.png

let R; // 星(穴)の大きさ調整用
const vertexNum = 10; // 星の頂点数

const w = 300; // 図形の外枠の横の長さ
const h = 300; // 図形の外枠の縦の長さ

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(0, height / 2, width, height / 2);
  line(width / 2, 0, width / 2, height);

  // 星形穴あき図形
  noFill();
  strokeWeight(2);
  stroke(200, 0, 0);
  fill(200, 100, 100);

  push();
  translate(width / 2, height / 2);
  rotate(-90);

  beginShape();
  vertex(-w / 2, -h / 2);
  vertex(w / 2, -h / 2);
  vertex(w / 2, h / 2);
  vertex(-w / 2, h / 2);
  beginContour();
  for (let i = vertexNum; i > 0; i--) {
    R = i % 2 == 0 ? w * 0.4 : w * 0.2;

    vertex(R * cos(360 * i / vertexNum), R * sin(360 * i / vertexNum));
  }
  endContour();
  endShape(CLOSE);

  pop();
}

erase()を使った書き方

p5.jsでは createGraphics()erase() の組み合わせでも穴あき図形が描けます。

16anaaki_02erase.png

let R; // 星(穴)の大きさ調整用
const vertexNum = 10; // 星の頂点数

const w = 300; // 図形の外枠の横の長さ
const h = 300; // 図形の外枠の縦の長さ

let pg; // 図形の外枠を描くためのgraphics用

function setup() {
  createCanvas(400, 400);
  angleMode(DEGREES);

  // 画像の基準点を中央に変更
  imageMode(CENTER);

  // 四角いgraphicsを生成
  pg = createGraphics(w, h);
}

function draw() {
  background(255);

  // 中心線
  strokeWeight(1);
  stroke(200);
  line(0, height / 2, width, height / 2);
  line(width / 2, 0, width / 2, height);

  // pgに対して描画
  pg.angleMode(DEGREES);
  pg.background(200, 100, 100);

  // 以降の描画はpgから削除される
  pg.erase();

  // 星型の図形を描画
  pg.push();

  pg.translate(pg.width / 2, pg.height / 2);
  pg.rotate(-90);

  pg.beginShape();
  for (let i = vertexNum; i > 0; i--) {
    R = i % 2 == 0 ? w * 0.4 : w * 0.2;

    pg.vertex(R * cos(360 * i / vertexNum), R * sin(360 * i / vertexNum));
  }
  pg.endShape(CLOSE);

  pg.pop();

  // pgを表示
  image(pg, width / 2, height / 2);
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

競プロのJavaScript標準入力まとめ【パターン別】

競技プログラミングのJavaScriptの標準入力がわかりにくかったのでまとめました。
AtCoderのCランクまでしかやったことありませんが、大体以下のパターンかなと思います。

※随時追加していきます

標準入出力の基本形

プログラミング入門学習コンテンツのpaizaラーニングにはlinesで標準入力するやり方が説明されていますが、以下のやり方の方がわかりやすいと思います。

function main(input) {
  var a = input.split(" ");  // 入力

  // コードを入れる

  console.log(a); // 出力
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));

inputの中に標準入力の値が入っています。
最後にconsole.log( )で出力するだけです。

連続文字パターン

入力

a b

入力例

3 4

入出力例

function main(input) {
  var args = input.split(" ");
  var a = parseInt(args[0], 10);
  var b = parseInt(args[1], 10);

  console.log(args); // [ '3', '4' ]
  console.log(a); // 3
  console.log(b); // 4
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));

連続文字パターン(〜n)

入力

n
A1 A2 ... An

入力例

4
2 1 4 8

入出力例

function main(input) {
  var args = input.split("\n");
  var n = parseInt(args[0], 10);
  var a = args[1].split(" ").map((n) => parseInt(n, 10));

  console.log(args); // [ '4', '2 1 4 8' ]
  console.log(n); // 4
  console.log(a); // [ 2, 1, 4, 8 ]
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));

改行パターン

入力

A
B
C
X

入力例

5
1
0
20

入出力例

function main(input) {
  var args = input.split("\n");
  var A = parseInt(args[0], 10);
  var B = parseInt(args[1], 10);
  var C = parseInt(args[2], 10);
  var X = parseInt(args[3], 10);

  console.log(A); // 5
  console.log(B); // 1
  console.log(C); // 0
  console.log(X); // 20
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));

改行パターン(〜n)

入力

n
A1
A2
:
An

入力例

4
10
8
8
6

入出力例

function main(input) {
  var args = input.split("\n");
  var N = args[0];
  var nums = args.slice(1, args.length - 1);

  console.log(args); // ["4", "10", "8", "8", "6"]
  console.log(N); // 4
  console.log(nums); // ["10", "8", "8", "6"]
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));

行列パターン

入力

X1 Y1
X2 Y2
X3 Y3

入力例

3 1
6 1
7 2

入出力例

function main(input) {
  var args = input.split("\n");
  var nums = args.map((n) => n.split(" "));
  var x = nums.map((n) => parseInt(n[0], 10));
  var y = nums.map((n) => parseInt(n[1], 10));

  console.log(args); // [ '3 1', '6 1', '7 2' ]
  console.log(nums); // [ [ '3', '1' ], [ '6', '1' ], [ '7', '2' ] ]
  console.log(x); // [ 3, 6, 7 ]
  console.log(y); // [ 1, 1, 2 ]
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));

行列パターン(〜n)

入力

n
T1 X1 Y1
T2 X2 Y2
:
Tn Xn Yn

入力例

2
3 1 2
6 1 1

入出力例

function main(input) {
  var args = input.split("\n");
  var N = parseInt(args[0], 10);
  var nums = args.slice(1, N + 1).map((n) => n.split(" "));
  var t = nums.map((n) => parseInt(n[0], 10));
  var x = nums.map((n) => parseInt(n[1], 10));
  var y = nums.map((n) => parseInt(n[2], 10));

  console.log(args); // [ '2', '3 1 2', '6 1 1' ]
  console.log(N); // 2
  console.log(nums); // [ [ '3', '1', '2' ], [ '6', '1', '1' ] ]
  console.log(t); // [ 3, 6 ]
  console.log(x); // [ 1, 1 ]
  console.log(y); // [ 2, 1 ]
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

競プロのJavaScript標準入力【パターン別】

競技プログラミングのJavaScriptの標準入力がわかりにくかったのでまとめました。
AtCoderのCランクまでしかやったことありませんが、大体以下のパターンかなと思います。

※随時追加していきます

標準入出力の基本形

プログラミング入門学習コンテンツのpaizaラーニングにはlinesで標準入力するやり方が説明されていますが、以下のやり方の方がわかりやすいと思います。

function main(input) {
  var a = input.split(" ");  // 入力

  // コードを入れる

  console.log(a); // 出力
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));

inputの中に標準入力の値が入っています。
最後にconsole.log( )で出力するだけです。

連続文字パターン

入力

a b

入力例

3 4

入出力例

function main(input) {
  var args = input.split(" ");
  var a = parseInt(args[0], 10);
  var b = parseInt(args[1], 10);

  console.log(args); // [ '3', '4' ]
  console.log(a); // 3
  console.log(b); // 4
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));

連続文字パターン(〜n)

入力

n
A1 A2 ... An

入力例

4
2 1 4 8

入出力例

function main(input) {
  var args = input.split("\n");
  var n = parseInt(args[0], 10);
  var a = args[1].split(" ").map((n) => parseInt(n, 10));

  console.log(args); // [ '4', '2 1 4 8' ]
  console.log(n); // 4
  console.log(a); // [ 2, 1, 4, 8 ]
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));

改行パターン

入力

A
B
C
X

入力例

5
1
0
20

入出力例

function main(input) {
  var args = input.split("\n");
  var A = parseInt(args[0], 10);
  var B = parseInt(args[1], 10);
  var C = parseInt(args[2], 10);
  var X = parseInt(args[3], 10);

  console.log(A); // 5
  console.log(B); // 1
  console.log(C); // 0
  console.log(X); // 20
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));

改行パターン(〜n)

入力

n
A1
A2
:
An

入力例

4
10
8
8
6

入出力例

function main(input) {
  var args = input.split("\n");
  var N = args[0];
  var nums = args.slice(1, args.length - 1);

  console.log(args); // ["4", "10", "8", "8", "6"]
  console.log(N); // 4
  console.log(nums); // ["10", "8", "8", "6"]
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));

行列パターン

入力

X1 Y1
X2 Y2
X3 Y3

入力例

3 1
6 1
7 2

入出力例

function main(input) {
  var args = input.split("\n");
  var nums = args.map((n) => n.split(" "));
  var x = nums.map((n) => parseInt(n[0], 10));
  var y = nums.map((n) => parseInt(n[1], 10));

  console.log(args); // [ '3 1', '6 1', '7 2' ]
  console.log(nums); // [ [ '3', '1' ], [ '6', '1' ], [ '7', '2' ] ]
  console.log(x); // [ 3, 6, 7 ]
  console.log(y); // [ 1, 1, 2 ]
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));

行列パターン(〜n)

入力

n
T1 X1 Y1
T2 X2 Y2
:
Tn Xn Yn

入力例

2
3 1 2
6 1 1

入出力例

function main(input) {
  var args = input.split("\n");
  var N = parseInt(args[0], 10);
  var nums = args.slice(1, N + 1).map((n) => n.split(" "));
  var t = nums.map((n) => parseInt(n[0], 10));
  var x = nums.map((n) => parseInt(n[1], 10));
  var y = nums.map((n) => parseInt(n[2], 10));

  console.log(args); // [ '2', '3 1 2', '6 1 1' ]
  console.log(N); // 2
  console.log(nums); // [ [ '3', '1', '2' ], [ '6', '1', '1' ] ]
  console.log(t); // [ 3, 6 ]
  console.log(x); // [ 1, 1 ]
  console.log(y); // [ 2, 1 ]
}

main(require("fs").readFileSync("/dev/stdin", "utf8"));
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Prototype JavaScript Frameworkを使ってみた感想

当記事では、Prototype JavaScript Frameworkの導入方法や操作方法を解説するとともに、使ってみた感想をつらつらと書いています。

1. Prototype JavaScript Frameworkとは

Prototype JavaScript Framework、通称prototype.jsは2005年2月に発表されたJavaScriptライブラリです。

公式サイト

公式ドキュメント

GitHub

私が知っているかぎり、JavaScriptフレームワークと呼ばれるライブラリのなかでは最も古いものであり、さらに主要なJavaScriptライブラリのなかで最も古いものでもあり、そしてCSS・JavaScript双方の主要なライブラリのなかでも最も古いものです。

なにせ、あのjQueryが初めて登場したのが2006年8月26日ですから、その1年半前にリリースされたことを考えると、その古さがよく分かると思います。

1-1. 特徴

まずは公式サイトのトップページにある概要を読んでみましょう。原文は英語ですが、Google翻訳にかけて和訳し、さらに意訳しています。

Prototype JavaScript Frameworkは、クライアントサイドのプログラミングから複雑さを取り除きます。このライブラリは現実に直面している問題を解決するために構築されており、ブラウザ組み込みのJavaScriptオブジェクトをprototype拡張して便利な機能を追加し、AjaxとDOMの不器用なインターフェイスの周りにエレガントなAPIを提供します。

1文目に、このライブラリが提供するのは何らかの新機能ではなく、既存の処理を組みやすくすることであると書かれています。そして2文目以降では、そのためにブラウザ組み込みオブジェクトを拡張し、AjaxとDOMの操作を容易にするAPIを実装していると書いてあります。

続けて、公式ドキュメントにある概要も読んでみましょう。こちらもGoogle翻訳にかけたうえで意訳しています。

Prototype JavaScript Frameworkは、動的Webアプリケーションの開発を容易にすることを目的としたJavaScriptフレームワークです。使い慣れたクラスベースのオブジェクト指向プログラミング、Ajaxの広範なサポート、高次のプログラミング構造、および簡単なDOM操作を提供します。

このライブラリを使うことで動的に書き換えるWebアプリ開発が容易になると謳っています。また、そのためにクラスベースのオブジェクト指向プログラミングができるような機能の追加、Ajax関連処理の容易化、高次のプログラミング構造(これがよく分からない)、そして簡単にDOMを操作できるようにすると言っています。

以上の情報をまとめると、このライブラリの特徴が見えてきます。

  • Webコンテンツ、特に動的にWebページを書き換えるWebアプリの開発が容易にする。
  • そのために、組み込みオブジェクトを拡張して便利なメソッドなどを追加する。
  • また、他言語のようにクラスベースのオブジェクト指向プログラミングができるようにする。
  • そしてAjax周辺処理とDOM操作を容易にする。

およそ1年半後に登場するjQueryと似ているところもありますが、Webアプリに言及している点、クラスベースのオブジェクト指向プログラミングに言及している点、この2点は当ライブラリ独自のものです。また、何でもjQueryオブジェクトに包んでしまうjQueryに比べて、組み込みオブジェクトを拡張していくところは決定的に異なります。

2. 導入手順

導入手順はいくつかあるようですが、最も簡単なのは公式サイトから最新バージョンを落としてくることでしょう。

公式サイト ダウンロードページ

当記事執筆時点で、最新バージョンはv1.7.3です。リリース日が2015年9月22日なので、5年以上開発が止まっているようですね。

読み込み方法としては、当ライブラリを参照する.jsファイルよりも先に<script>タグで読み込んでおくタイプの読み込み方法になります。残念ながら、標準ではES Modulesには対応していません。独自にES Modules化しようとしても、組み込みオブジェクトのprototypeをガリガリ書き換える都合上、かなり難しい作業になるでしょう。

依存しているライブラリはなく、単一のファイルで動作します。

3. 使用時の注意点

当ライブラリを使うときはアロー関数の使用は避け、function文・function式で関数を定義することを推奨します。主要なAPIのいくつかはFunctionオブジェクトを引数にとって動作するのですが、アロー関数で定義されたFunctionオブジェクトだと正常に動作しない場合があります。

4. API紹介

詳細は公式ドキュメントに譲り、当記事ではいくつかのAPIを紹介します。

4-1. $$メソッド

\$\$メソッドは、jQueryの$メソッドに相当するものです。document.querySelectorメソッドなどと同様にセレクターを利用して、HTML要素を取得することができます。

ただし、jQueryの$メソッドがjQueryオブジェクトを返すのに対して、こちらは普通のElementオブジェクトを配列に格納して返します。

// <p>タグを全部取得します。
const pElements = $$("p");

// 複雑なセレクターにも対応しています。
const pInBody = $$("body > p:nth-of-type(1)");

4-2. $Fメソッド

$Fメソッドは、引数で指定したidを持つフォーム部品の状態・入力値を返します。

<input id="name">
$F("name");

// 以下処理に相当します。
document.getElementById("name").value;

4-3. $Rメソッド

$Rメソッドは、数値や文字の範囲で生成します。他言語でいうところのrangeメソッドや..演算子のようなものですね。

// 0, 1, 2, 3と表示されます。
$R(0, 3).each(function (value) {
  console.log(value);
});

// 他言語的には、こういう書き方になるのでしょうか。
$R(0..3).each(function (value) {
  console.log(value);
});

// 文字列にも対応しています。
// a, b, cと表示されます。
$R("a", "c").each(function (value) {
  console.log(value);
});

4-4. $wメソッド

\$wメソッドは、半角空白区切りで文字列を分割するような挙動をします。ちなみに、$記号に続くwは小文字ですので、大文字のWと間違えないように注意が必要です。

// ["Hello", "world."] となります。
const array1 = $w("  Hello     world.        ");

// この処理に相当します。
"  Hello     world.        ".split(" ").filter(function (value) {
  if (value === "") {
    return false;
  } else {
    return true;
  }
});

4-5. Class.createメソッド

Class.createメソッドは当ライブラリ独自のクラス定義処理を実行します。このライブラリが登場した2005年当時のJavaScriptにはclass文・class式がなく、フロントエンドエンジニアはFunctionオブジェクトのprototypeを拡張してクラス定義用のFunctionオブジェクトを作っていました。

Google流JavaScriptにおけるクラス定義の実現方法(ES6以前) | yunabe.jp

当ライブラリには、そのような時代に生まれただけあってか、独自のクラス定義処理を実装しているのです。

第1引数にオブジェクトを指定するのですが、initializeプロパティに指定した関数がインスタンス化時に実行されるコンストラクタとなります。また、他プロパティに指定した関数はメソッドとして参照できるようになります。

const Dog = Class.create({
  initialize: function (animaiSound) {
    this.animaiSound = animaiSound;
  },
  call: function () {
    return this.animaiSound;
  }
});

const dog = new Dog("bowwow");
console.log(dog.call()); // bowwow

継承する場合もClass.createメソッドを使用します。ただし、第1引数に継承元となるクラス定義を格納した変数を指定します。

const Dog = Class.create({
  initialize: function (animaiSound) {
    this.animaiSound = animaiSound;
  },
  call: function () {
    return this.animaiSound;
  }
});

const Doge = Class.create(Dog);

const doge = new Doge("ワンワン");
console.log(doge.call()); // ワンワン

サブクラス側で実装したいメソッドなどは、第2引数にオブジェクトとして指定します。

const Dog = Class.create({
  initialize: function (animaiSound) {
    this.animaiSound = animaiSound;
  },
  call: function () {
    return this.animaiSound;
  }
});

const Doge = Class.create(Dog, {
  jump: function () {
    return "Wow";
  }
});

const doge = new Doge("ワンワン");
console.log(doge.call()); // ワンワン
console.log(doge.jump()); // Wow

もちろん、オーバーライドできます。

const Dog = Class.create({
  initialize: function (animaiSound) {
    this.animaiSound = animaiSound;
  },
  call: function () {
    return this.animaiSound;
  }
});

const Doge = Class.create(Dog, {
  call: function () {
    return this.animaiSound + "";
  }
});

const doge = new Doge("ワンワン");
console.log(doge.call()); // ワンワン!

オーバーライドされたメソッドを呼び出すときは、オーバーライドしたメソッドの定義の第1引数に$superという名前の引数を定義します。そして、オーバーライドしたメソッド内で当該引数を関数として呼び出します。ただし、インスタンスから呼び出すときは、この特殊な第1引数のことは無視します。

4-6. Ajax.Requestオブジェクト

Ajax.Requestオブジェクトをインスタンス化すると非同期通信を実行します。第1引数に通信先、第2引数にイベントリスナーを定義したオブジェクトを指定します。

いくつかのイベントが用意されており、イベント名と対応したプロパティに指定された関数が実行されます。基本的には以下3つのイベントを使うことになるでしょう。なお、onCompleteはonSuccess・onFailureの後に呼び出されます。

new Ajax.Request("./example.php", {
  onComplete: function (responce) {
    console.log("通信完了");
  },
  onFailure: function (responce) {
    console.log("通信失敗");
  },
  onSuccess: function (responce) {
    console.log("通信成功");
  }
});

4-7. Ajax.Updaterオブジェクト

Ajax.Updaterオブジェクトをインスタンス化すると非同期通信を実行し、通信結果を表す文字列を任意のidを持つHTML要素に挿入します。

<p id="result"></p>
new Ajax.Updater("result", "./example.php");

4-8. Ajax.PeriodicalUpdaterオブジェクト

Ajax.PeriodicalUpdaterオブジェクトはAjax.Updaterオブジェクトを繰り返し実行します。例えば、初期設定では2秒間隔でサーバーと通信し、その戻り値を任意のHTML要素に挿入します。

<p id="result"></p>
new Ajax.PeriodicalUpdater("result", "./example.php");

4-9. Abstract.TimedObserverオブジェクト

Abstract.TimedObserverオブジェクトは一定秒間隔で、任意のidを持つフォーム部品の変更を監視するイベントリスナーを実装することができます。

第1引数に対象のid、第2引数で通知間のクールタイムとなる秒数、第3引数に通知が来たときに実行する処理となる関数を指定します。

document.addEventListerメソッドにinputイベントを指定することで似たようなことはできますが、何らかの変化が生ずるたびに通知されて鬱陶しいという場合があるでしょう。そんなときに便利なオブジェクトです。

<input id="text-box">
// まずはインスタンスを作成します。
// 引数に指定した関数内の処理は無視してもらってかまいません。
const TimedObserver = Class.create(Abstract.TimedObserver, {
  getValue: function() {
    return Form.Element.getValue(this.element);
  }
});

// イベントリスナーを実装します。
// text-boxというidを持つフォーム部品の状態の変移を監視します。
// ただし、最後に通知してから0.5秒間は、変移しても通知しません。
new TimedObserver("text-box", 0.5, function (element, value) {
  console.log(element.id); // text-box
  console.log(value); // 変化後の値
});

5. 使ってみた感想

組み込みオブジェクトの積極的な拡張・DOM操作の容易化・Ajax操作の容易化・独自のクラス処理・フォーム部品の状態監視などなど、とにかく色々なことをやっているライブラリという印象を持ちました。Prototype JavaScript Frameworkという名前どおり、既存のプログラムに後付けするライブラリというよりは、処理全体の土台となるフレームワークと呼ぶに相応しいでしょう。

また、Classオブジェクトを使って、プロトタイプベースのJavaScriptをクラスベースのオブジェクト指向言語っぽく表現しようとしているあたりに、開発者の(当時の)JavaScriptに対する思いが見え隠れしている気もします。

ただ、さすがに登場時期が時期だけあって、ES2015以後のフロントエンド開発環境が一般的となった2021年現在では、jQueryと同様に「わざわざ採用する必要あるかな?」と疑問を禁じ得ません。jQueryと違い、プラグインが豊富というわけでもなく、コミュニティも小さく、5年以上開発が進捗していない点などからも、このライブラリを採用するのは厳しいです。

強いて挙げるとすれば、このライブラリはIE6以降に対応しています――つまり、おそらく大半のブラウザで動作します。IE11などのレガシーなブラウザへの対応をしなければならない案件で、クラスベースのオブジェクト指向プログラミングを行いたいという場合は、もしかすると候補に入ってくるかもしれません。あるいは、フォーム部品がたくさんあって、しかも非同期通信による動的な書き換えを頻繁に実施する必要があるようなWebアプリとは相性が良いでしょう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者】いいね機能をJavascriptで意地の実装

いいね機能をjQueryではなく、Javascriptで実装したい(意地)

ただの意地、だけではないです。
Javascriptの理解が浅い自覚があったので、理解が浅いままjQueryで実装するのではなく
Javascriptで実装したい。が正しいですかね(笑)

 バージョンなど

  • ruby 2.6.5
  • bundler 2.1.4
  • rails 6.0.0

実装のながれ

流れとしては最初にrailsで実装→Javascriptで非同期になるように実装しました。

liked.js
function liked(){

  // elementがいいね/いいね解除ボタンかどうかを判定する
  const isLikeButtons = (element) => {
    const isLikeButton = element.classList.contains('liked_btn');
    const isUnLikeButton = element.classList.contains('liked_destroy_btn');
    return isLikeButton || isUnLikeButton;
  }

  // ajax成功時の処理
  document.body.addEventListener('ajax:success', function(e) {
    const response = e.detail[0]; // ajaxのレスポンスデータ
    if (! isLikeButtons(e.target)) {
      return;
    }
    // e.target.insertAdjacentHTML("afterend", response.html);
    e.target.closest('.liked_destroy_area, .like_area').outerHTML = response.html
  });

  // ajaxエラー時の処理
  document.body.addEventListener('ajax:error', function(e) {
    if (! isLikeButtons(e.target)) {
      return;
    }
    const xhr =  e.detail[2];  // XMLHttpRequestオブジェクト
    alert(`Error ${xhr.status}: ${xhr.statusText}`);
  });
}

window.addEventListener("load", liked);

要素がいいねボタンなのか、いいね解除(既にいいね済)ボタンなのかの判断

ajax成功、失敗で分岐して書きました。

index.html.erb

<%# 該当部分のみ記載 %>

<% if user_signed_in? && current_user.already_liked?(@preschool) %>
  <div class= "liked_destroy_area">
    <%= link_to "★", preschool_likes_path(@preschool), data: {id: @preschool.id}, remote:true, method: :delete, class: "liked_destroy_btn" %>
    <span class="like-count"><%= @preschool.likes.count %></span>
  </div>
<% elsif user_signed_in?  %>
  <div class="like_area">
    <%= link_to "☆", preschool_likes_path(@preschool), data: {id: @preschool.id}, remote:true, method: :post, class: "liked_btn" %>
    <span class="like-count"><%= @preschool.likes.count %></span>
  </div>
<% end %>

※ここではrailsでの実装は割愛しますが、該当部分のビューのみ書いておきます。
★が文字のままなのでさすがにここは変更予定です。

長かった。。。。

エラーの沼に入り、確実にjQueryで記載するより数倍時間がかかりましたが
これで多少なりとも理解が深まったかと。

もし書き方ミスやもっといい方法があればコメントいただけばと思います!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[2021年1月](Typescript)ESLintでStaticを使う

ESLintでは以下のようなコードを書くと、エラーになってしまう。

public static instance: HogeInstance;

調べるといくつか出てくるが、取り急ぎ以下のプラグインを入れれば解決する。

npm install @babel/eslint-parser --save-dev

そして.eslintrc.jsonにparserの指定を追加してあげる。

.eslintrc.json
{
  "parser": "eslint-parser",
  // 以下他のパラメーター
}

検索して出てくるのは結構古くて、babel-eslint をみんな使っていました。
でも自分の7.12以降だとうまくいかなかったので、今のBabelのバージョンだとこれだと思います。
https://github.com/babel/babel/tree/master/eslint/babel-eslint-parser#usage

https://github.com/babel/babel-eslint
babel-eslintに移行してる旨も書いてある。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScriptのメールアドレスのバリデーションサンプル

やること

入力されたメールアドレスの形式をチェックし、NGならアラートを表示してフォームは送信しない

<form name="form">
  <input id="email" type="email">
  <input id="submit" type="submit">
</form>

ステップ1

入力されたメールアドレスの値を取得する。

const email = document.form.email.value;
const email = document.getElementById('email').value;

どちらでも取得可能です。今の書き方だと後者ですね。

ステップ2

「メールアドレスの形式」とみなす条件を決定する。

例えば、

「任意の文字1文字以上」「@」「任意の文字1文字以上」「.」「任意の文字1文字以上」
をメールアドレスの形式とみなすのであれば、正規表現にすると

  • 「任意の文字」→ .
  • 「1文字以上」→ +
  • 「.」→\.

と変換し、つなげると

.+@.+\..+

となります。

「半角英数1文字以上」「半角英数または.-のいずれか0文字以上」「@」「半角英数または-のいずれか1文字以上」「半角英数または._-のいずれか1文字以上」
をメールアドレスの形式とみなすのであれば、正規表現にすると

  • 「半角英数」→[a-zA-Z0-9]
  • 「1文字以上」→+
  • 「半角英数または.-のいずれか」→ [a-zA-Z0-9\._-]
  • 「0文字以上」→*

と変換し、つなげると

[a-zA-Z0-9]+[a-zA-Z0-9\._-]*@[a-zA-Z0-9_-]+[a-zA-Z0-9\._-]+

となります。

どこまで厳しいバリデーションにするかを考え、まずは日本語で整理してみましょう。
その後正規表現の書き方に変換します。

ステップ3

入力されたメールアドレスと「メールアドレスの形式」とみなす条件を比較する。

入力されたメールアドレス = email
「メールアドレスの形式」とみなす条件 = .+@.+\..+
です。
比較にはmatchを使います。

const email = document.getElementById('email').value;
if (!email.match(/.+@.+\..+/)) {
  window.alert('メールアドレスをご確認ください'); 
}

これで、入力されたメールアドレスがメールアドレスの形式でない場合はアラートが出るようになります。

今回やらないこと

ハイフンを置換する。

const email = document.getElementById('email').value.replace(/[━.*‐.*―.*-.*\-.*ー.*\-]/gi, '');

取得したメールアドレスの値に対して、置換をかけています。
replaceのかっこ内の1つ目の引数は変更前の「ハイフンらしきもの」、2つ目の引数は変更後の空欄です。
「ハイフンらしきものを空欄に置換する」という書き方になります。

なぜやらないかというと、ハイフンを空欄に変換してから比較すると、変換前の入力が正しかったのかわからなくなるためです。例えば、

0-8-0-1-2-3-4-5-6-7-8

のような入力も通ってしまいますよね。

そのため、入力を置換するのではなく、入力された値のまま「メールアドレスの形式」とみなす条件、「電話番号の形式」とみなす条件と比較するべきです。

参考リンク

https://www.tagindex.com/javascript/form/check3.html
https://its-office.jp/blog/js/2017/08/19/telmatch.html

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

配列をx個に分割し、配列ごとの累計を新しい配列に格納する

配列に1時間毎のデータが1年分格納されています。
この配列を日別のデータに変換し、新しい配列に格納する方法について書きます。

やること

  1. 配列をx個ごとに分割する
  2. 分割した配列内の累計をy回出す
  3. 新しい配列に累計を入れる

今回の場合、x=24,y=365

引用

配列をn個ごとに分割する関数

const sliceByNumber = (array, number) => {
    const length = Math.ceil(array.length / number)
    return new Array(length).fill().map((_, i) =>
      array.slice(i * number, (i + 1) * number)
    )
}

累計を出す

var result = array.reduce(function (accumulator, currentValue, currentIndex, array) {
        return accumulator + currentValue;
});

コード

var array1 = [1, 2, 3, 1, 2, 3, ...];//省略

const sliceByNumber = function(array, number){
    const length = Math.ceil(array.length / number)//Math.ceilで引数以上の最小の整数を返す
    return new Array(length).fill().map(function(_, i){ 
            return array.slice(i * number, (i + 1) * number);
        }//_はcurrentValueが空の意。iは配列のインデックス/添字
    )//fillがインデックス付き配列を返す。mapは与えられた関数を配列のすべての要素に対して呼び出し、返された値を追加
}

array2 = sliceByNumber(array1, 24);//配列の分割。array2.lengthは365

newArray = new Array();//新しい配列を作成

for(var i = 0; i < array2.length; i++){
    var result = array2[i].reduce(function (accumulator, currentValue, currentIndex, array) {
        return accumulator + currentValue;
    });
    newArray[i] = result;//累計を新しい配列に格納。それを365回繰り返す
}

引用元の著者に感謝です。
ありがとうございました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

fuse-box+TypeScriptで公式通りやったらimport使えないって言われた

?概要

fuse-box v4.0.0のgetting-startedをstep1からやっていったらこんなエラーが出る

fusebox % ./node_modules/.bin/ts-node fuse.ts
(node:42058) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/Users/fusebox/fuse.ts:1
import { fusebox } from 'fuse-box';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:979:16)
    at Module._compile (internal/modules/cjs/loader.js:1027:27)
    at Module.m._compile (/Users/fusebox/node_modules/ts-node/src/index.ts:1056:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Object.require.extensions.<computed> [as .ts] (/Users/fusebox/node_modules/ts-node/src/index.ts:1059:12)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
    at main (/Users/fusebox/node_modules/ts-node/src/bin.ts:198:14)
    at Object.<anonymous> (/Users/fusebox/node_modules/ts-node/src/bin.ts:288:3)

✨解決

tsconfig.jsonmodulecommonjs にすれば解決!

tsconfig.json
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "commonjs",
    "outDir": "./dist",
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": [
    "./src/**/*.ts"
  ]
}

?参考

https://stackoverflow.com/questions/63445821/ts-node-execute-typescript-with-module-import-and-module-defined

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ジブリの画像一枚一枚保存するのが面倒臭いので一括ダウンロードできるスクリプトを書いてみた

まえおき

現在、スタジオジブリが各タイトルのシーン画像を大量公開していますね。

Twitterでも大喜利など行われたりして盛り上がっていました。(もう一回見返しても面白い)

「客先には業務経験3年ってことにしてあるからね」業界の闇とわかりみが詰まった#ジブリIT業界あるある まとめ

去年の12月に最後のタイトル、5作品が追加がされましたので、いつ提供が終わってもおかしくないですね。

公開されている画像を一括保存するスクリプトをJSでせこせこと書いたのですが、Chromeの拡張機能で簡単にできるやつがありました。
image downloader

車輪の再発明ですね。とはいえ学びもあったしせっかく書いたスクリプトを抹消してしまうのも悲しい為、記事に残しておこうと思います。

ということで早速、拡張機能を知る前の私は画像を見ながら好きなシーンを保存していくことにしました。

michida「画像選ぶぞ〜よし、やっぱりまずは千と千尋から見ていこう。」
chihiro001.jpeg
michida「あー最初の車に揺られる千尋ね〜〜いいねいいね保存」

chihiro006.jpeg
michida「うわー豚のお父さん拡大して見ると迫力あるなーーー保存」

chihiro011.jpeg
michida「あー良い保存」

chihiro015.jpeg
michida「うん良い保存」
chihiro022.jpeg
michida「保存」
chihiro026.jpeg

chihiro032.jpeg
chihiro037.jpeg
chihiro048.jpeg
michida「保存保存保存保存保存保存保存保存保存保存」

保存したい画像が多すぎる!!!!!!!!!!
保存したい画像が多すぎるのか保存したくない画像が少なすぎるのか。

ちなみに画像を保存するのはWEBページからデスクトップやフォルダなどにドラッグ&ドロップすれば保存できると思いますが、このジブリのサイトは一覧の画像をドラッグ&ドロップするとサムネイルの画像が保存となり、クリックしてモーダルを開いてドラッグ&ドロップしようとすると横スクロールが効いてしまいます。
期待する一枚絵を保存するには右クリックで名前をつけて保存をしないといけないのでサクサクできないんですよね。

非常に手間ですね。
いえ、文句ではないです。そんなこと言いません。

感謝の気持ちでいっぱいです。
ほんとにありがとうございます。

スクリプト書きます。(拡張機能があるとも知らず。。。)

本題

ということで書いたのがこちらです。

function makeGalleryIndex(index) {
  let galleryNumber = {};
  return index < 10
    ? galleryNumber.name = '00'+index
    : galleryNumber.name = '0'+index;
}

function download(i){
  return new Promise(resolve => {
    setTimeout(() => {
      // urlから作品名切り取り
      let contentName = location.href.split('/')[4];
      console.log(contentName);

      // aタグ作成
      let link = document.createElement('a');
      // ファイル名xxx001.jpegのインデックス部分を作成
      let galleryIndex = makeGalleryIndex(i);
      // 画像取得先設定
      link.href = 'https://www.ghibli.jp/gallery/'+ contentName + galleryIndex+'.jpg';
      console.log(link.href);
      // ダウンロード属性をつけ、保存する名前を決める
      link.setAttribute('download', contentName + galleryIndex)
      // 保存
      link.click();

      // 負荷をかけないように1秒待ちましょう
      resolve('1秒待ちます');
    }, 1000);
  })
}

async function galleryDownload() {
  const gallery = document.getElementsByClassName('row gallery');
  const galleriesSize = gallery[0].getElementsByTagName('figure').length;
  console.log(galleriesSize);
  for (let i = 1; i <= galleriesSize; i++) {
    console.log(await download(i));
  }
}

// 画像ダウンロード関数呼び出し。成功時、例外補足などは特に処理は書きません。
galleryDownload().then().catch();

一秒おきにsleepさせたいのでsetTimeoutとPromiseで実行してます。

実際に動かしてみましょう。

保存したい作品のページに遷移しデベロッパーツールのConsoleに貼り実行するとページ内の画像を保存してくれます。

ezgif.com-gif-maker.gif

うまく保存されていってますね。
保存先などは特に設定してないのでダウンロードフォルダに保存されています。

個人的にConsoleでのPromiseの使い方がうまくできずに詰まりましたが同僚に聞きながら無事動かすことができました。

「あーダウンロードしておけば良かったー」となる前に急いでみなさん保存しましょう(誰)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

jestでCannot find module 'spdx-license-ids'というエラーになった時の対処

どんなエラーが出たのか

jestでテストを実行した時に以下のエラーが出ました

Test suite failed to run

Cannot find module 'spdx-license-ids' from 'node_modules/spdx-expression-parse/scan.js'

Require stack:
  node_modules/spdx-expression-parse/scan.js
  node_modules/spdx-expression-parse/index.js
  node_modules/validate-npm-package-license/index.js
  node_modules/normalize-package-data/lib/fixer.js
  node_modules/normalize-package-data/lib/normalize.js
  node_modules/meow/index.js
  src/bin.ts
  src/tests/bin.test.ts

  at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:306:11)
  at Object.<anonymous> (node_modules/spdx-expression-parse/scan.js:4:11)

どうやって治したか

jestのconfigの moduleFileExtensionsjson を追加したら直りました

  • 変更前
package.jsonから一部
"jest": {
    "moduleFileExtensions": ["ts", "js"]
}
  • 変更後
package.jsonから一部
"jest": {
    "moduleFileExtensions": ["ts", "js", "json"]
}

なぜ治ったのか

今回エラーしたパッケージはspdx-license-ids(https://github.com/jslicense/spdx-license-ids) なのですが、内部でjsonファイルが使われています。
jestはconfigのmoduleFileExtensionsに指定された拡張子のファイルしか読み込みません。(https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring)
なので、spdx-license-idsで使われていたjsonファイルを読み込むことができずエラーしました。

ちなみに、jestのmoduleFileExtensionsの初期値は

["js", "json", "jsx", "ts", "tsx", "node"]

なので、私が余計な設定をしていなければこのエラーは発生しませんでしたね?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【react-modal-hook】モーダルコンポーネントに便利なhooksを解説【on Next.js】

前書き

Next.jsの上でモーダルコンポーネントを実装する手順を解説していこうと思います。ご指摘等ありましたら、コメントしていただけますとありがたいです?‍♂️

以下、本題です。

react-modal-hook

react-modal-hookはUIを提供しません。代わりに他の場所で定義されたモーダルコンポーネントをレンダリングする便利な方法を提供してくれます。モーダルのUIを提供してくれるReactのライブラリであるreact-modalと一緒に使うと良いかもしれませんね。公式でも「相性が良い」と書かれていますしね。

For a simple modal component check out react-modal, which works well with this library.

この記事でもreact-modalを使って解説していきます。

react-modal別の記事で解説しています。

以降から具体的な使い方を解説していきます!

シンプルなモーダルコンポーネントを実装してみる

最初に全体的なコードを示しておきます。以降から順番に解説していこうと思います。

src/pages/react-modal-hook.tsx
import ReactModal from "react-modal"
import { useModal, ModalProvider } from "react-modal-hook"

// アプリのルートを識別するクエリセレクタを指定する。
ReactModal.setAppElement('#__next')

const App = () => {
  const [showModal, hideModal] = useModal(() => (
    <>
      <ReactModal isOpen>
        <p>Modal content</p>
        <button onClick={hideModal}>Hide modal</button>
      </ReactModal>
    </>
  ))

  return <button onClick={showModal}>Show modal</button>
}

const Hoge = () => {
  return(
    <ModalProvider>
      <App/>
    </ModalProvider>
  )
}

export default Hoge

説明のために、むりやり1ファイルにまとめていますが、実際は別ファイルにまとめておくと良いかもしれません。

【1】必要なコンポーネントをimportする

import ReactModal from "react-modal"
import { useModal, ModalProvider } from "react-modal-hook"
  • react-modal:モーダルのUIを提供してくれるライブラリ
  • useModal:今回の主役。
  • ModalProvider:プロバイダー。モーダル用のcontextを提供してくれる。

【2】useModalの引数にコールバック関数としてモーダルを定義

今回は、モーダルのUIとしてreact-modalを使うので、useModal関数の引数の中のコールバック関数としてreact-modalを定義してください。

(コードは【3】とまとめて示します。)

【3】useModalの返り値を配列の形で受け取る

const App = () => {
  const [showModal, hideModal] = useModal(() => (
    <>
      <ReactModal isOpen>
        <p>Modal content</p>
        <button onClick={hideModal}>Hide modal</button>
      </ReactModal>
    </>
  ));

  return <button onClick={showModal}>Show modal</button>;
}
  • showModalモーダルを表示する関数
  • hideModalモーダルを閉じる関数

上記のようにuseModalの返り値がモーダルの表示/非表示の関数が自動的に返ってきます。便利!

蛇足ですが、<ReactModal isOpen>isOpentrueになる時にモーダルが表示されます。(これはreact-modalの機能です。)

【4】ModalProviderでラップする

const Hoge = () => {
  return(
    <ModalProvider>
      <App/>
    </ModalProvider>
  )
}

上記のようにuseModalを使っている関数コンポーネントをModalProviderでラップしてあげてださい。

基本的な形は以上です!

モーダル内部の更新

モーダル内部で何らかの値を更新する場合は、useModal関数の第二引数に配列の形で参照する値を渡してください。(コードは公式のコピペ)

const App = () => {
  const [count, setCount] = useState(0);
  const [showModal] = useModal(
    () => (
      <ReactModal isOpen>
        <span>The count is {count}</span>
        <button onClick={() => setCount(count + 1)}>Increment</button>
      </ReactModal>
    ),
    [count]
  );

  return <button onClick={showModal}>Show modal</button>;
}

第二引数に配列の形で渡した値の変化をみて、レンダリングされるのだと思います。(多分。useEffectと同じニュアンスなのだと思う。)

参考記事:【React hooks】噛み砕いて解説してみた~useEffect編~

以上です!個人的にはreact-modalでUIを整えて、react-modal-hookで表示/非表示の関数をコンポーネント化させておくと爆速でモーダル実装できるのかなあ〜なんて思ったりします!

ではでは〜?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Next.js】モーダルコンポーネントの実装を解説【hooks編】

前書き

Next.jsの上でモーダルコンポーネントを実装する手順を解説していこうと思います。ご指摘等ありましたら、コメントしていただけますとありがたいです?‍♂️

以下、本題です。

react-modal-hook

react-modal-hookはUIを提供しません。代わりに他の場所で定義されたモーダルコンポーネントをレンダリングする便利な方法を提供してくれます。モーダルのUIを提供してくれるReactのライブラリであるreact-modalと一緒に使うと良いかもしれませんね。公式でも「相性が良い」と書かれていますしね。

For a simple modal component check out react-modal, which works well with this library.

この記事でもreact-modalを使って解説していきます。

react-modal別の記事で解説しています。

以降から具体的な使い方を解説していきます!

シンプルなモーダルコンポーネントを実装してみる

最初に全体的なコードを示しておきます。以降から順番に解説していこうと思います。

src/pages/react-modal-hook.tsx
import ReactModal from "react-modal"
import { useModal, ModalProvider } from "react-modal-hook"

// アプリのルートを識別するクエリセレクタを指定する。
ReactModal.setAppElement('#__next')

const App = () => {
  const [showModal, hideModal] = useModal(() => (
    <>
      <ReactModal isOpen>
        <p>Modal content</p>
        <button onClick={hideModal}>Hide modal</button>
      </ReactModal>
    </>
  ))

  return <button onClick={showModal}>Show modal</button>
}

const Hoge = () => {
  return(
    <ModalProvider>
      <App/>
    </ModalProvider>
  )
}

export default Hoge

説明のために、むりやり1ファイルにまとめていますが、実際は別ファイルにまとめておくと良いかもしれません。

【1】必要なコンポーネントをimportする

import ReactModal from "react-modal"
import { useModal, ModalProvider } from "react-modal-hook"
  • react-modal:モーダルのUIを提供してくれるライブラリ
  • useModal:今回の主役。
  • ModalProvider:プロバイダー。モーダル用のcontextを提供してくれる。

【2】useModalの引数にコールバック関数としてモーダルを定義

今回は、モーダルのUIとしてreact-modalを使うので、useModal関数の引数の中のコールバック関数としてreact-modalを定義してください。

(コードは【3】とまとめて示します。)

【3】useModalの返り値を配列の形で受け取る

const App = () => {
  const [showModal, hideModal] = useModal(() => (
    <>
      <ReactModal isOpen>
        <p>Modal content</p>
        <button onClick={hideModal}>Hide modal</button>
      </ReactModal>
    </>
  ));

  return <button onClick={showModal}>Show modal</button>;
}
  • showModalモーダルを表示する関数
  • hideModalモーダルを閉じる関数

上記のようにuseModalの返り値がモーダルの表示/非表示の関数が自動的に返ってきます。便利!

蛇足ですが、<ReactModal isOpen>isOpentrueになる時にモーダルが表示されます。(これはreact-modalの機能です。)

【4】ModalProviderでラップする

const Hoge = () => {
  return(
    <ModalProvider>
      <App/>
    </ModalProvider>
  )
}

上記のようにuseModalを使っている関数コンポーネントをModalProviderでラップしてあげてださい。

基本的な形は以上です!

モーダル内部の更新

モーダル内部で何らかの値を更新する場合は、useModal関数の第二引数に配列の形で参照する値を渡してください。(コードは公式のコピペ)

const App = () => {
  const [count, setCount] = useState(0);
  const [showModal] = useModal(
    () => (
      <ReactModal isOpen>
        <span>The count is {count}</span>
        <button onClick={() => setCount(count + 1)}>Increment</button>
      </ReactModal>
    ),
    [count]
  );

  return <button onClick={showModal}>Show modal</button>;
}

第二引数に配列の形で渡した値の変化をみて、レンダリングされるのだと思います。(多分。useEffectと同じニュアンスなのだと思う。)

参考記事:【React hooks】噛み砕いて解説してみた~useEffect編~

以上です!個人的にはreact-modalでUIを整えて、react-modal-hookで表示/非表示の関数をコンポーネント化させておくと爆速でモーダル実装できるのかなあ〜なんて思ったりします!

ではでは〜?

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

フロントエンドの参考用

概要

フロントエンドを作成する上で役に立つサイトまとめてみました!!

メインレイアウト

bootstrap

みんな大好きBootstrap。説明不要。

Bootstrap

image.png

tailwindcss

cssのフレームワークでBootstrapを抜いて1位になったcssフレームワーク。
様々なレイアウトを提供している。

tailwindcss

image.png

Google Fonts

googleが提供するfontで、google fontsをfont familyに設定するとどのコンピュータからでもfontが崩れずに表示できるという利点がある。

Google Fonts

使いかた

image.png

アニメーション生成

Animista

rotateやscaleアップなどのアニメーションを自動生成してくれるサイト。

Animista

image.png

Animate On Scroll Library

スクロールアニメーションを提供。

Animate On Scroll Library

image.png

slick

簡単にスライダーを実現。

slick

image.png

css生成

ストライプ生成

css背景のストライプを生成。

Pure CSS Stripe Generator

image.png

グラデーション生成

cssのグラデーションを生成。

CSS Gradient
image.png

背景の境界線を生成

背景をモダンなサイトのような形状にしてくれるcssを生成してくれるサイト。

Shape Divider App

image.png

動くグラデーションの生成

背景が動くグラデーションを生成できる。

FUZE

image.png

各パーツ

ボタンレイアウト

120種類以上のボタンのサンプルとcssを提供。
コピペで使える。

CSSボタンデザイン120個以上!どこよりも詳しく作り方を解説!

image.png

ハンバーガーメニュー①

ハンバーガーメニューを好みに合わせて生成。

Burger Generator

image.png

ハンバーガーメニュー②

17種類のハンバーガーメニューを提供。

Tasty CSS-animated hamburgers

image.png

スライドサイドメニュー

サイドメニューを実現できるプラグイン。

Drawer

image.png

素材サイト

モダンなサイドバー

今風なサイドバーを紹介。

今風に作られたスライド式サイドバーのコードスニペット9選

image.png

スライダー

jqueryで作成されたスライダーの紹介。

jQueryスライダープラグイン9選!スライドショーを手軽に作成

image.png

デザイン参考

モダンなデザインを参考にできる。

【初心者必見】Webデザインを楽にするコツ&便利なサイト集!

image.png

Adobe XDデザインカンプ

Adobe XDのデザインカンプの紹介がされており、ダウンロードしてコーディングの練習ができる。

Adobe XDの無料テンプレート配布サイト

image.png

学習サイト

keyframeアニメーション

keyframeを利用したアニメーションについてよくまとまっていて非常に学びになる。

CSSでアニメーション!「animation」と「keyframes」の使い方のおさらい

ボタンの中の要素の上下左右中央揃え

FontAwesomeのアイコンを真ん中に表示したい

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React-modal】モーダルコンポーネントを実装 【on Next.js】

前書き

Next.jsの上でモーダルコンポーネントを実装する手順を解説していこうと思います。ご指摘等ありましたら、コメントしていただけますとありがたいです?‍♂️

以下、本題です。

React-modal

React-modalReactのライブラリの一種です。React-modalを使うことで手軽にモーダルコンポーネントを実装することができます。

以降から具体的な使い方を解説していきます。

シンプルなモーダルコンポーネントを実装してみる

【1】インストール

npm or yarnreact-modalをインストールしてください。

npm install react-modal
yarn add react-modal

【2】モーダル用のファイルを追加

pages/modal.tsxを追加してください。(基本的にはこのpages/modal.tsxファイルにコードを追加していきます。)こうすることでhttp://localhost:3000/modalにアクセスすることでモーダルを実装したページを確認することができます。

これはNext.jsのデフォルトの機能です。便利!!

【3】実際にコードを記述していく(全体像)

先に、コードの全体像を示しておきます。

pages/modal.tsx
import Modal from 'react-modal'
import { useState } from 'react'

// スタイリング
const customStyles = {
  overlay: {
    position: "fixed",
    top: 0,
    left: 0,
    backgroundColor: "rgba(0,0,0,0.3)"
  },

  content : {
    top                   : '50%',
    left                  : '50%',
    right                 : 'auto',
    bottom                : 'auto',
    marginRight           : '-50%',
    width                 : '500px',
    height                : '300px',
    transform             : 'translate(-50%, -50%)'
  }
};

// アプリのルートを識別するクエリセレクタを指定する。
Modal.setAppElement('#__next')

const App = () => {
  const [modalIsOpen,setIsOpen] = useState(false)

  // モーダルを開く処理
  const openModal = () => {
    setIsOpen(true)
  }

  const afterOpenModal = () => {
    // モーダルが開いた後の処理
  }

  // モーダルを閉じる処理
  const closeModal = () => {
    setIsOpen(false)
  }

    return (
      <>
        <button onClick={openModal}>Open Modal</button>
        <Modal
          // isOpenがtrueならモダールが起動する
          isOpen={modalIsOpen}
          // モーダルが開いた後の処理を定義
          onAfterOpen={afterOpenModal}
          // モーダルを閉じる処理を定義
          onRequestClose={closeModal}
          // スタイリングを定義
          style={customStyles}
        >

          <h2>Hello</h2>
          <button onClick={closeModal}>close</button>
        </Modal>
      </>
    )
}

export default App

実際に描画される画面は下記です。

スクリーンショット 2021-01-12 12.42.48(2).png

以降から順番に解説していきます。

【4】必要なコンポーネントをimport

react-modalState管理のためのuseStateを追加しておきます。

import Modal from 'react-modal'
import { useState } from 'react'

useStateの記事はこちらの記事を読むと理解が深まると思います。

【5】Modalのプロパティを解説

import Modal from 'react-modal'importしてきたModalコンポーネントの中身(プロパティ)から解説していきます。

return (
  <div>
    <button onClick={openModal}>Open Modal</button>
      <Modal
        // isOpenがtrueならモダールが起動する
        isOpen={modalIsOpen}
        // モーダルが開いた後の処理を定義
        onAfterOpen={afterOpenModal}
        // モーダルを閉じる処理を定義
        onRequestClose={closeModal}
        // スタイリングを定義
        style={customStyles}
      >

        <h2>Hello</h2>
        <button onClick={closeModal}>close</button>
      </Modal>
  </div>
  • isOpen:モーダルを表示する否かのbooleanを指定
  • onRequestClose:モーダルを閉じるための関数を指定
  • onAfterOpen:モーダルを開いた後に実行する関数を指定
  • style:スタイリングを定義

他にも多くのプロパティがあります。気になる方はドキュメントを読んでみてください。

【6】アプリのルートを識別するクエリセレクタを指定する。

モーダルが開いている時、他のコンテンツを隠すと思います。これを可能にするためにreact-modalでは、アプリのルートを識別するクエリセレクタを指定してModal.setAppElementを呼び出す必要があります。

Next.jsでは#__nextがルートに指定されるので。下記のようにコードを追加します。

Modal.setAppElement('#__next')

【7】スタイリングと関数を定義

スタイリングと、関数(モーダルを開いたりする)をAppコンポーネント内に定義します。

まずはスタイリングから。

const customStyles = {
  overlay: {
    position: "fixed",
    top: 0,
    left: 0,
    backgroundColor: "rgba(0,0,0,0.3)"
  },

  content : {
    top                   : '50%',
    left                  : '50%',
    right                 : 'auto',
    bottom                : 'auto',
    marginRight           : '-50%',
    width                 : '500px',
    height                : '300px',
    transform             : 'translate(-50%, -50%)'
  }
}

overlayはモーダルが開いている時の背景のスタイリング、contentはモーダル自体のスタイリングを定義しています。

ここで定義した定数customStylesModalコンポーネント内のstyleプロパティ内に追加してください。

<Modal
  //略
  // スタイリングを定義
  style={customStyles}
>

次に関数コンポーネント内にモーダルを閉じたり、開いたりするする関数を定義していきます。

const App = () => {
  const [modalIsOpen,setIsOpen] = useState(false);

  // モーダルを開く処理
  const openModal = () => {
    setIsOpen(true);
  }

  const afterOpenModal = () => {
    // モーダルが開いた後の処理
  }

  // モーダルを閉じる処理
  const closeModal = () => {
    setIsOpen(false);
  }

これらの関数はModalコンポーネント内のプロパティ内で下記のように使われます。

<Modal
  // isOpenがtrueならモダールが起動する
  isOpen={modalIsOpen}
  // モーダルが開いた後の処理を定義
  onAfterOpen={afterOpenModal}
  // モーダルを閉じる処理を定義
  onRequestClose={closeModal}
  // スタイリングを定義
  style={customStyles}
>

以上です!基本的なところは解説したので、もっと詳しく知りたい方はGithubドキュメントを読むと理解が深まるかと思います!!

ではでは~!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【react-modal】モーダルコンポーネントを実装 【on Next.js】

前書き

Next.jsの上でモーダルコンポーネントを実装する手順を解説していこうと思います。ご指摘等ありましたら、コメントしていただけますとありがたいです?‍♂️

以下、本題です。

React-modal

React-modalReactのライブラリの一種です。React-modalを使うことで手軽にモーダルコンポーネントを実装することができます。

以降から具体的な使い方を解説していきます。

シンプルなモーダルコンポーネントを実装してみる

【1】インストール

npm or yarnreact-modalをインストールしてください。

npm install react-modal
yarn add react-modal

【2】モーダル用のファイルを追加

pages/modal.tsxを追加してください。(基本的にはこのpages/modal.tsxファイルにコードを追加していきます。)こうすることでhttp://localhost:3000/modalにアクセスすることでモーダルを実装したページを確認することができます。

これはNext.jsのデフォルトの機能です。便利!!

【3】実際にコードを記述していく(全体像)

先に、コードの全体像を示しておきます。

pages/modal.tsx
import Modal from 'react-modal'
import { useState } from 'react'

// スタイリング
const customStyles = {
  overlay: {
    position: "fixed",
    top: 0,
    left: 0,
    backgroundColor: "rgba(0,0,0,0.3)"
  },

  content : {
    top                   : '50%',
    left                  : '50%',
    right                 : 'auto',
    bottom                : 'auto',
    marginRight           : '-50%',
    width                 : '500px',
    height                : '300px',
    transform             : 'translate(-50%, -50%)'
  }
};

// アプリのルートを識別するクエリセレクタを指定する。
Modal.setAppElement('#__next')

const App = () => {
  const [modalIsOpen,setIsOpen] = useState(false)

  // モーダルを開く処理
  const openModal = () => {
    setIsOpen(true)
  }

  const afterOpenModal = () => {
    // モーダルが開いた後の処理
  }

  // モーダルを閉じる処理
  const closeModal = () => {
    setIsOpen(false)
  }

    return (
      <>
        <button onClick={openModal}>Open Modal</button>
        <Modal
          // isOpenがtrueならモダールが起動する
          isOpen={modalIsOpen}
          // モーダルが開いた後の処理を定義
          onAfterOpen={afterOpenModal}
          // モーダルを閉じる処理を定義
          onRequestClose={closeModal}
          // スタイリングを定義
          style={customStyles}
        >

          <h2>Hello</h2>
          <button onClick={closeModal}>close</button>
        </Modal>
      </>
    )
}

export default App

実際に描画される画面は下記です。

スクリーンショット 2021-01-12 12.42.48(2).png

以降から順番に解説していきます。

【4】必要なコンポーネントをimport

react-modalState管理のためのuseStateを追加しておきます。

import Modal from 'react-modal'
import { useState } from 'react'

useStateの記事はこちらの記事を読むと理解が深まると思います。

【5】Modalのプロパティを解説

import Modal from 'react-modal'importしてきたModalコンポーネントの中身(プロパティ)から解説していきます。

return (
  <div>
    <button onClick={openModal}>Open Modal</button>
      <Modal
        // isOpenがtrueならモダールが起動する
        isOpen={modalIsOpen}
        // モーダルが開いた後の処理を定義
        onAfterOpen={afterOpenModal}
        // モーダルを閉じる処理を定義
        onRequestClose={closeModal}
        // スタイリングを定義
        style={customStyles}
      >

        <h2>Hello</h2>
        <button onClick={closeModal}>close</button>
      </Modal>
  </div>
  • isOpen:モーダルを表示する否かのbooleanを指定
  • onRequestClose:モーダルを閉じるための関数を指定
  • onAfterOpen:モーダルを開いた後に実行する関数を指定
  • style:スタイリングを定義

他にも多くのプロパティがあります。気になる方はドキュメントを読んでみてください。

【6】アプリのルートを識別するクエリセレクタを指定する。

モーダルが開いている時、他のコンテンツを隠すと思います。これを可能にするためにreact-modalでは、アプリのルートを識別するクエリセレクタを指定してModal.setAppElementを呼び出す必要があります。

Next.jsでは#__nextがルートに指定されるので。下記のようにコードを追加します。

Modal.setAppElement('#__next')

【7】スタイリングと関数を定義

スタイリングと、関数(モーダルを開いたりする)をAppコンポーネント内に定義します。

まずはスタイリングから。

const customStyles = {
  overlay: {
    position: "fixed",
    top: 0,
    left: 0,
    backgroundColor: "rgba(0,0,0,0.3)"
  },

  content : {
    top                   : '50%',
    left                  : '50%',
    right                 : 'auto',
    bottom                : 'auto',
    marginRight           : '-50%',
    width                 : '500px',
    height                : '300px',
    transform             : 'translate(-50%, -50%)'
  }
}

overlayはモーダルが開いている時の背景のスタイリング、contentはモーダル自体のスタイリングを定義しています。

ここで定義した定数customStylesModalコンポーネント内のstyleプロパティ内に追加してください。

<Modal
  //略
  // スタイリングを定義
  style={customStyles}
>

次に関数コンポーネント内にモーダルを閉じたり、開いたりするする関数を定義していきます。

const App = () => {
  const [modalIsOpen,setIsOpen] = useState(false);

  // モーダルを開く処理
  const openModal = () => {
    setIsOpen(true);
  }

  const afterOpenModal = () => {
    // モーダルが開いた後の処理
  }

  // モーダルを閉じる処理
  const closeModal = () => {
    setIsOpen(false);
  }

これらの関数はModalコンポーネント内のプロパティ内で下記のように使われます。

<Modal
  // isOpenがtrueならモダールが起動する
  isOpen={modalIsOpen}
  // モーダルが開いた後の処理を定義
  onAfterOpen={afterOpenModal}
  // モーダルを閉じる処理を定義
  onRequestClose={closeModal}
  // スタイリングを定義
  style={customStyles}
>

以上です!基本的なところは解説したので、もっと詳しく知りたい方はGithubドキュメントを読むと理解が深まるかと思います!!

ではでは~!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Next.js】モーダルコンポーネントの実装を解説【UI編】

前書き

Next.jsの上でモーダルコンポーネントを実装する手順を解説していこうと思います。ご指摘等ありましたら、コメントしていただけますとありがたいです?‍♂️

以下、本題です。

React-modal

React-modalReactのライブラリの一種です。React-modalを使うことで手軽にモーダルコンポーネントを実装することができます。

以降から具体的な使い方を解説していきます。

シンプルなモーダルコンポーネントを実装してみる

【1】インストール

npm or yarnreact-modalをインストールしてください。

npm install react-modal
yarn add react-modal

【2】モーダル用のファイルを追加

pages/modal.tsxを追加してください。(基本的にはこのpages/modal.tsxファイルにコードを追加していきます。)こうすることでhttp://localhost:3000/modalにアクセスすることでモーダルを実装したページを確認することができます。

これはNext.jsのデフォルトの機能です。便利!!

【3】実際にコードを記述していく(全体像)

先に、コードの全体像を示しておきます。

pages/modal.tsx
import Modal from 'react-modal'
import { useState } from 'react'

// スタイリング
const customStyles = {
  overlay: {
    position: "fixed",
    top: 0,
    left: 0,
    backgroundColor: "rgba(0,0,0,0.3)"
  },

  content : {
    top                   : '50%',
    left                  : '50%',
    right                 : 'auto',
    bottom                : 'auto',
    marginRight           : '-50%',
    width                 : '500px',
    height                : '300px',
    transform             : 'translate(-50%, -50%)'
  }
};

// アプリのルートを識別するクエリセレクタを指定する。
Modal.setAppElement('#__next')

const App = () => {
  const [modalIsOpen,setIsOpen] = useState(false)

  // モーダルを開く処理
  const openModal = () => {
    setIsOpen(true)
  }

  const afterOpenModal = () => {
    // モーダルが開いた後の処理
  }

  // モーダルを閉じる処理
  const closeModal = () => {
    setIsOpen(false)
  }

    return (
      <>
        <button onClick={openModal}>Open Modal</button>
        <Modal
          // isOpenがtrueならモダールが起動する
          isOpen={modalIsOpen}
          // モーダルが開いた後の処理を定義
          onAfterOpen={afterOpenModal}
          // モーダルを閉じる処理を定義
          onRequestClose={closeModal}
          // スタイリングを定義
          style={customStyles}
        >

          <h2>Hello</h2>
          <button onClick={closeModal}>close</button>
        </Modal>
      </>
    )
}

export default App

実際に描画される画面は下記です。

スクリーンショット 2021-01-12 12.42.48(2).png

以降から順番に解説していきます。

【4】必要なコンポーネントをimport

react-modalState管理のためのuseStateを追加しておきます。

import Modal from 'react-modal'
import { useState } from 'react'

useStateの記事はこちらの記事を読むと理解が深まると思います。

【5】Modalのプロパティを解説

import Modal from 'react-modal'importしてきたModalコンポーネントの中身(プロパティ)から解説していきます。

return (
  <div>
    <button onClick={openModal}>Open Modal</button>
      <Modal
        // isOpenがtrueならモダールが起動する
        isOpen={modalIsOpen}
        // モーダルが開いた後の処理を定義
        onAfterOpen={afterOpenModal}
        // モーダルを閉じる処理を定義
        onRequestClose={closeModal}
        // スタイリングを定義
        style={customStyles}
      >

        <h2>Hello</h2>
        <button onClick={closeModal}>close</button>
      </Modal>
  </div>
  • isOpen:モーダルを表示する否かのbooleanを指定
  • onRequestClose:モーダルを閉じるための関数を指定
  • onAfterOpen:モーダルを開いた後に実行する関数を指定
  • style:スタイリングを定義

他にも多くのプロパティがあります。気になる方はドキュメントを読んでみてください。

【6】アプリのルートを識別するクエリセレクタを指定する。

モーダルが開いている時、他のコンテンツを隠すと思います。これを可能にするためにreact-modalでは、アプリのルートを識別するクエリセレクタを指定してModal.setAppElementを呼び出す必要があります。

Next.jsでは#__nextがルートに指定されるので。下記のようにコードを追加します。

Modal.setAppElement('#__next')

【7】スタイリングと関数を定義

スタイリングと、関数(モーダルを開いたりする)をAppコンポーネント内に定義します。

まずはスタイリングから。

const customStyles = {
  overlay: {
    position: "fixed",
    top: 0,
    left: 0,
    backgroundColor: "rgba(0,0,0,0.3)"
  },

  content : {
    top                   : '50%',
    left                  : '50%',
    right                 : 'auto',
    bottom                : 'auto',
    marginRight           : '-50%',
    width                 : '500px',
    height                : '300px',
    transform             : 'translate(-50%, -50%)'
  }
}

overlayはモーダルが開いている時の背景のスタイリング、contentはモーダル自体のスタイリングを定義しています。

ここで定義した定数customStylesModalコンポーネント内のstyleプロパティ内に追加してください。

<Modal
  //略
  // スタイリングを定義
  style={customStyles}
>

次に関数コンポーネント内にモーダルを閉じたり、開いたりするする関数を定義していきます。

const App = () => {
  const [modalIsOpen,setIsOpen] = useState(false);

  // モーダルを開く処理
  const openModal = () => {
    setIsOpen(true);
  }

  const afterOpenModal = () => {
    // モーダルが開いた後の処理
  }

  // モーダルを閉じる処理
  const closeModal = () => {
    setIsOpen(false);
  }

これらの関数はModalコンポーネント内のプロパティ内で下記のように使われます。

<Modal
  // isOpenがtrueならモダールが起動する
  isOpen={modalIsOpen}
  // モーダルが開いた後の処理を定義
  onAfterOpen={afterOpenModal}
  // モーダルを閉じる処理を定義
  onRequestClose={closeModal}
  // スタイリングを定義
  style={customStyles}
>

以上です!基本的なところは解説したので、もっと詳しく知りたい方はGithubドキュメントを読むと理解が深まるかと思います!!

ではでは~!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSのメニューと説明の一覧を手軽に取得できたから単語帳にしてみた

はじめに

ほんとなんとなく思い立ったので、なんとなく作りました
100%自分用のメモです

成果物

https://ankilot.com/view/?pr=XMeFbkUKa8

手順

  • AWSにサインインする
  • AWSの上のメニューをひらく
    image.png

  • F12をおす

  • consoleで下記を実行する

copy($$('._142-PMgGBA2POWI1QZQeIW').map(e=>[e.textContent,e.title].join(',')).join('\n'))

image.png

  • エディタにはりつける
  • 2つめのEC2の上までは左の最近アクセスした履歴なので削除する

image.png

  • ファイル名をつけてCSVで保存する
  • https://ankilot.com/ を開いて単語帳をつくる

おわり

補足

  • 下記の3つは説明がありませんでした

    • Personal Health Dashboard
    • サポート
    • CloudShell
  • ほんとはカテゴリも入れたかったのですが、うまい具合に手軽に取得できないのであきらめました

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Pythonを使う人がJavaScriptの空辞書の判定ではまった話

普段は機械学習系のプログラミングでPythonを使うことが多いのですが、画面回りもやる必要があり、その時JavaScriptの辞書を if 文で判定するコードであれ?と思ったこと。勘違いと言ってしまうとそれまでですが。

Pythonの場合

Python で辞書が空かどうか判定するのに以下のような if 文を書いていました。x が空辞書やnullの時は False になります。

sample.py
x = {}
if x:
  print("xは空ではない");
else:
  print("xは空です");

実行結果

xは空です

JavaScriptの場合

一方で JavaScript だと空辞書の場合 True になります。

sample.js
var x = {};
if (x) {
  console.log("xは空ではない");
} else {
  console.log("xは空です");
}
xは空ではない

空かどうか判定する方法はいろいろあるようですが Object.keys(x) でキーの数を調べることでできるようです。

sample.js
var x = {};
if (Object.keys(x).length) {
  console.log("xは空ではない");
} else {
  console.log("xは空です");
}

つい、うっかりPythonと同じように考えてコーディングしてしまい、「うまく動かないな」と悩んでしまいました・・・

参考文献

JavaScriptの if(x) での判定結果がオブジェクトごと True/False どちらになるかはこちらに纏められていてわかりやすいです。
- [JavaScript] null とか undefined とか 0 とか 空文字(”) とか false とかの判定について

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ダチョウ倶楽部げーーっむ

「俺がやるボタン」を押した数だけ
「どうぞボタン」を押すといっぺんに「どうぞ」が返ってくる

ボタンでカウントアップして

どうぞボタンでそれを受け取りrepeatメソッドで「どうぞどうぞ」を繰り返してポップアップに表示

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./style.css">
    <title>DatyoukurabuGame</title>
</head>
<body>
    <h1>ダチョウ倶楽部ゲーム</h1>
    <button onclick="countup()">俺がやる!!!</button>
    <button onclick="douzo()">どうぞどうぞぉ~</button>
    <script src="./index.js"></script>
</html>
var count = 0
function countup() {
    return count++ 
}

function douzo(countup) {
    console.log(count)
    const str ="どうぞどうぞ"
    const action =str.repeat(count)
    alert(action)
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プログラムを少しかじった私がバックエンドエンジニアとして働くためにECサイトを作り始めてみた その⑤

対象者

・バックエンドエンジニアを志す人
・web開発初学者
・ECサイトを作成しようと思っている人
・初学者の勉強仮定を見たい方

はじめに

こんにちは!
この投稿はその④の続きです。

前回は年末年始を挟んであんまり実装が進まない状態でした。
実装する機能の洗い出し、スケジュール、実装を進めていきました。
並行で行っている開発との兼ね合いもあり今回の更新内容は少なめです。

目次

1.今回の作業報告
2.反省点
3.次回までの目標
4.最後に

1.今回の作業報告

まずは改めて実装する機能を洗いだしてスケジュールを立て直しました。

ざっくり機能を洗い出してスケジュールを立てています。
スケジュール崩れは間違いなく起こると思うので毎日スケジュールを引きなおすように設定しました。
スクリーンショット 2021-01-12 7.47.08.png

ECサイトの作成としてメールでのログイン機能の実装に取り掛かりました。
現在は実装途中です。さっそくスケジュールが崩れましたので調整しなおします。

2.振り返り
作業項目を改めて書き出した事により作業内容が明確になったのは良かったかと思います。
項目の抜け漏れはあるかと思いますが、それは実装進めていくなかで分かってくるのかなと思います。

スケジュールを立てたことにより多少やることが明確になりました。
ただ、作業ボリュームが不明確の中で立てているのであんまり当てにならないのかな
と思っています。今回はペースメーカー的な役割で利用するようになると思います。

締め切りよりかなり前に作業が終わるように設定していますが、結局、ギリギリまでかかるのかなと思っています。

3.次のステップ:引き続き実装!
機能ごとに予定を立てたのであとは実装を進めるだけかなと思います。
次回は実装結果の報告と振り返りがメインになりそうです。

4.次のステップ:最後に
今回のECサイトの制作にあたりqiitaの記事をはじめて書くことを習慣にしました。

・作業途中の自分の思考の振り返りことにより反省点の明確化になっている
・思い出すことによる記憶の定着が起こっている
・反省点を踏まえてのアクションプランへの転換のしやすい

などを感じており書いてよかったなと思っています。

文章の見直しなどほとんど行っておらず個人の雑記のようになっているので
読まれる投稿にして技術コミュニティに貢献していければと思っています。
(文章の書き方もちゃんと振り返らないと良くならないだろうな・・)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

条件分岐JavaScript

JavaScriptで使える条件分岐についてまとめてみました。
条件分岐とは、記述した条件式がTrue/Falseによって判断され、その後の実行結果が変化することです。
以下に、それぞれの条件分岐にいついて説明します。

項目

・if文
・?で条件分岐
・switch
・for
以上の4点です。

if文

main.js
if(条件式){
 条件式がTrueの処理
}else if(条件式){
 条件式がTrueの処理
}else{
 条件式がFalseの処理
};

ifの条件式がTrueならifの中身の処理を実行
ifの条件式がFalseでelse ifの条件式がTrueならelse ifの中身の処理を実行
どの条件にも当てはまらない場合、elseの処理を実行

?で条件分岐

main.js
条件式 ? Trueの処理:Falseの処理;

条件式を記述し、Trueの処理とFalseの処理を記述
それぞれの処理の文の長さが短いときに使いやすい。

switch

main.js
switch(定数などの比較される式){
 case 条件式1:
 条件式1に該当する処理;
 break;

 case 条件式2:
 条件式2に該当する処理;
 break;

 case 条件式3:
 条件式3に該当する処理;
 break;

 default:
 どの条件にも当てはまらない場合の処理;
};

switch~case~breakによって条件式に合った処理を実行していく。
条件式が多い場合はこの書き方を使用するとすっきりする。

for

main.js
for(定数などの比較される式;条件式;実行された後の処理){
 条件式がTrueの間の処理
}

forは繰り返し処理を行う。上記だと分かりにくいので具体例を以下に示す。

main.js
for(let i=0;i<10;i++){
 console.log(i);
};

for(変数を定義;条件がTrueの時の処理;変数に1づつ足していく)
この場合だとiが10未満の時に値が出力される。

参考文献

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/for

https://www.pu-kumamoto.ac.jp/~matsuno/zemi2/JavaScript/JSBranch.html

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[TypeScript] nullとundefined、! と ? の意味

トピックに関する個人的ブックマークでございます。

nullとundefined

リンク : nullとundefined

JavaScript(と、TypeScript)は、nullとundefinedという2つのボトム型(bottom type)があります。これらは異なる意味を持っています。

TypeScriptのコードレビューを依頼された人のための!と?の解説

リンク : TypeScriptのコードレビューを依頼された人のための!と?の解説

TypeScriptのコードレビューをしていて、 ! と ? の意味を改めて確認したら意外とややこしかったのでまとめておきます。

ご注意: 本記事では、nullとundefinedを厳密に区別せず、どちらも含めてnon-null/nullableと表現しています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Next.jsでのtailwindcssの導入の仕方

流行りのスタイルのtailwindcssの導入の仕方(Next.js)

npx create-next-app next-jsで導入したファイルに

1.npm install

npx create-next-app . --use-npm

npm i tailwindcss

npx tailwindcss init -p

2.?stylesのglobal.cssの中身を書き換える

@tailwind base;
@tailwind components;
@tailwind utilities;

3.?pagesにimport文を追加

import '../styles/globals.css';
import 'tailwindcss/tailwind.css';

4.下記のサイトを参考にclassName内に記述

tailwindcssのチートシート

[例です]
<div classnName="flex justify-center items-center flex-col min-h-screen text-gray-600 text-sm font-mono"></div> 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScript 分割代入講座

JavaScript 分割代入講座

こんにちは、フロントエンド初心者です。
JavaScript には ES2015(ES6)から"分割代入(Destructuring Assignment)"
と呼ばれる機能が実装されました。
簡単に言うと、「代入の文を完結に書けるやり方」と言って良いと思います。
この機能は必ずしも取り入れなくてもコードは動きます。
しかし導入することでコード量は大幅に削減され、
見通しの良いスッキリしたコードになることは間違いありません。

現代の React 開発などでは、当たり前のように分割代入で
記述されているサンプルコードもよく目にしますので、
是非この記事で分割代入に慣れておきましょう。

分割代入はAirbnbの提供する JavaScript スタイルガイドでも推奨されています。

基本

“分割” は “破壊的” を意味しません
これは、項目を変数にコピーすることによって “非構造化(destructurizes)” するため、“分割代入(destructuring assignment)” と呼ばれています。 配列自体は変更されません。

分割代入の元の配列やオブジェクトはこの操作によって影響を受けることはありません。

配列

const [va1,var2,var3] = 配列
のように記述することで配列の中に入っている要素を
左辺の変数に分配していく形になります。
代入先の変数名はなんでもOKです。

// スマートじゃない書き方
const foods = ["?","?","?"];
const sushi = foods[0]
const meat = foods[1]
const pizza = foods[2]

// 分割代入の書き方
const animals = ["?","?","?"];
const [cat, dog, bear] = animals;
const [neko, inu, kuma] = animals; // OK

オブジェクト

const {va1,var2,var3} = オブジェクト
のように中括弧を使う点に注意しましょう。
また、代入先の変数名はプロパティ値と一致していなければいけないことに注意しましょう。
プロパティ値と異なる名前で代入する方法は後述します。

// スマートじゃない書き方
const foods = { 
  sushi: "?",
  meat: "?",
  pizza: "?" 
};

const sushi = foods['sushi']
const meat = foods['meat']
const pizza = foods['pizza']

// 分割代入の書き方
const animals = {
  cat: "?",                
  dog: "?", 
  bear: "?"
};

const { cat, dog, bear } = animals;
// 以下はNG。
// const { neko, inu, kuma } = animals;

応用編 - こんな時はどうすれば?

オブジェクトのプロパティ値と異なる名前で分割代入したい

オブジェクトの基本構文の通り、デフォルトではプロパティ値と同じ値でないと
分割代入ができません、でも違う名前で保存したい。そんな時。

const animals = {
  cat: "?",                
  dog: "?", 
  bear: "?"
};

// こんな書き方になる、可読性は低い。
const { cat: neko, dog: inu, bear: kuma } = animals;
console.log(neko,inu,kuma) // => "?","?","?"

左辺の変数が右辺の配列要素(オブジェクトプロパティ)より多い場合

エラーにはなりませんが、右辺の要素数で足りない分はundifinedとなります。

const animals = ["?","?","?"]

// エラーにはならない
const [cat,dog,bear,rabbit] = animals;
console.log(cat,dog,bear,rabbit) // => "?" "?" "?" undefined

左辺の変数が右辺の配列要素(オブジェクトプロパティ)より少ない場合

溢れる分を無視したい

この書き方で無視されて、左辺に存在する変数の数までを代入します。

// ウサギと豚が要らない!
const animals = ["?","?","?","?","?"];
// これでOK。
const [cat, dog, bear] = animals;
console.log(cat,dog,bear); // => "?","?","?"

溢れる分は最後の変数にまとめたい

スプレッド構文を使います。
なお、スプレッド構文でまとめられるのは最後の複数要素です。
間にスプレッド構文を使うと
「Uncaught SyntaxError: Rest element must be last element」
と怒られます。

// 熊とウサギと豚はまとめたい!
const animals = ["?","?","?","?","?"];
// これでOK。
const [cat, dog, ...other] = animals;
console.log(cat,dog,other); // => "?" "?" ["?", "?", "?"]

// これはNG。
const [cat, ...other, pig] = animals;

右辺の配列要素の最初の部分だけ要らない

カンマで左辺を区切ることにより、最初の要素を無視することができます。

// 猫と犬は要らない!
const animals = ["?","?","?","?","?"];
// これでOK。
const [,,bear,rabbit,pig] = animals;

左辺の変数にデフォルト値を用意したい

オブジェクトで、もし右辺のプロパティの中に該当するものがなかった場合に備えて
デフォルト値を用意しておくことができます。
例えば、右辺にユーザ情報のオブジェクトがくる場合で、プロフィール画像を設定している
ユーザとそうでないユーザがいるケースなどで結構使う気がします。

const animals = {
  cat: "?",                
  dog: "?", 
  bear: "?"
};

// animalsにはfoxはいないので左辺のデフォルト値が適用される
const { cat, dog, fox = "?" } = animals; 
console.log(cat, dog, fox); // => "?" "?" "?"

まとめ

さっと書けるとかっこいいので是非とも習得したいと思います。

最近見るのは、ReactのPropsをpropsという風に受け取らず
{username, description, children}などにして
以降のコードでprops.usernameといちいち書かずに
usernameと直接propsの名前にアクセスできるやり方です。

初見だと理解し辛いところがあるので、慣れておきましょう!

参考

https://ja.javascript.info/destructuring-assignment
https://qiita.com/uto-usui/items/a9d17447fe81c17c41fa
https://qiita.com/amamamaou/items/1ec21316b8bf05ba9c34

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む