1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Bラボデジタルサイネージ(長期用テキスト2/3)

Last updated at Posted at 2021-12-16

本記事は、株式会社 函館ラボラトリが運営する「Bラボ」における、大人向け「看板アプリ(デジタルサイネージ)を作るコース」用テキストです。
一からコードを書くわけではなく、あらかじめ用意したコードの一部を改変しながら、デジタルサイネージを作っていきましょう。

テンプレートプログラムは、下記GitHubリポジトリのLongTerm/Part2_Startディレクトリに入っています。

(12/16時点、本テキストは執筆中です)

前回のおさらい

RModuleのスクリーンショットを表示できる状態にしました。

ここからは「時刻」などを表示するモジュールを追加し、RModuleは実際のデータに連動するようにします。

背景画像の表示

まずは背景画像を読み込みます。
関数setup内で読み込みます。

DigitalSignage.pde
void setup() {
  frameRate(1);
  noCursor();
  colorMode(HSB, 360, 100, 100, 100);
  
  // 色の初期設定。
  WHITE_COLOR = color(0, 0, 100);
  NEARLY_WHITE_COLOR = color(100, 2, 98);
  NEARLY_GREEN_COLOR = color(100, 5, 98);
  BLACK_COLOR = color(0, 0, 0);
  LIGHT_COLOR = color(0, 0, 80);
  GRAY_COLOR = color(0, 0, 50);
  GREEN_COLOR = color(150, 100, 60);
  
  // デジタルサイネージの背景画像を読み込む。
  background = pImageCut(loadImage("background.jpg"), CENTER, CENTER, width, height); // 追加
  
  // 初期化用関数initialize()を、draw()で画面が描画されているときに並行し実行(非同期処理)。
  thread("initialize");
}

関数drawModules内で、背景画像を表示できるようにします。

DigitalSignage.pde
void drawModules() {
  image(background, 0, 0); // 追加
  
  if (nowPageID == 0) {
    drawWeatherRModule(Area.area1);
    drawBusRModule(Area.area3);
    drawGomiRModule(Area.area5);
  } else if (nowPageID == 1) {
    // ModuleやRModuleの描画用関数を呼び出す
    drawTemperatureRModule(Area.area1);
    drawBrightnessRModule(Area.area2);
    drawTwitterRModule(Area.area3);
    drawOpenCloseRModule(Area.area5);
  } else if (nowPageID == 2) {
    // ModuleやRModuleの描画用関数を呼び出す
  }
}

実行してみると、背景画像が表示されるようになっています。

0003.jpg

テキスト描画用関数の準備

このあとの実装で、文字を表示する関数textが使われます。
文字を表示するには、「サイズ」「色」「左揃え/中央揃え/右揃え」などの設定が必要です。
これを毎回数行にわたって書かなくてもいいように、1つの関数を呼ぶだけで良くします。

DigitalSignage.pde
// 表示するテキストのスタイルを指定して描画。
void drawText(int alignX, int alignY, color c, int size, String text, int x, int y) {
  pushStyle();
  textAlign(alignX, alignY);
  textSize(size);
  fill(c);
  if (alignY == BASELINE) {
    text(text, x, y+size);
  } else {
    text(text, x, y);
  }
  popStyle();
}

// 表示するテキストのスタイルを指定して描画。テキストの自動改行に対応したバージョン。
void drawText(int alignX, int alignY, color c, int size, String text, int x, int y, int w, int h) {
  pushStyle();
  textAlign(alignX, alignY);
  textSize(size);
  fill(c);
  if (alignY == BASELINE) {
    text(text, x, y+size, w, h);
  } else {
    text(text, x, y, w, h);
  }
  popStyle();
}

デジタルサイネージが設置されている場所を表示する

設置場所を画面の右上に表示してみましょう。
下記記事の「LocationModule」を実装します。

M_Location.pde
void drawLocationModule() {
  // 文字が画像と同化するのを避けるため、背景画像の色に応じて文字色反転。
  blendMode(EXCLUSION);
  
  drawText(RIGHT, BASELINE, WHITE_COLOR, 36, LOCATION, width-100, 30);
  
  // 他モジュールの描画時にも色が反転してしまうため、もとに戻す。
  blendMode(BLEND);
}

関数drawModulesの中で呼び出します。

DigitalSignage.pde
void drawModules() {
  image(background, 0, 0);
  
  if (nowPageID == 0) {
    drawWeatherRModule(Area.area1);
    drawBusRModule(Area.area3);
    drawGomiRModule(Area.area5);
  } else if (nowPageID == 1) {
    // ModuleやRModuleの描画用関数を呼び出す
    drawTemperatureRModule(Area.area1);
    drawBrightnessRModule(Area.area2);
    drawTwitterRModule(Area.area3);
    drawOpenCloseRModule(Area.area5);
  } else if (nowPageID == 2) {
    // ModuleやRModuleの描画用関数を呼び出す
  }

  drawLocationModule(); // 追加
}

時刻を表示する

時刻を画面の左上に表示してみましょう。
下記記事にある内容を進めていきます。

曜日を算出する関数をつくります。

M_Date.pde
// Zellerの公式を使った曜日計算
Youbi calcYoubi(int year, int month, int day) {
  final Youbi[] youbi = Youbi.values();
  if (month < 3) {
    year--;
    month += 12;
  }
  return youbi[(year+year/4-year/100+year/400+(13*month+8)/5+day)%7];
}

曜日を文字列として出すための関数をつくります。

M_Date.pde
// 曜日を日本語表記にする。月〜金でも祝日の場合は「月・祝」のように表示。
String youbiToString(Youbi youbi) {
  String str = "";
  switch (youbi) {
    case Sun:
      str = "日";
      break;
    case Mon:
      str = "月";
      if (isHoliday) str += "・祝";
      break;
    case Tue:
      str = "火";
      if (isHoliday) str += "・祝";
      break;
    case Wed:
      str = "水";
      if (isHoliday) str += "・祝";
      break;
    case Thu:
      str = "木";
      if (isHoliday) str += "・祝";
      break;
    case Fri:
      str = "金";
      if (isHoliday) str += "・祝";
      break;
    case Sat:
      str = "土";
      break;
  }
  return str;
}

日付と時刻を表示します。

M_Date.pde
void drawDateModule() {
  // 文字が画像と同化するのを避けるため、背景画像の色に応じて文字色反転。
  blendMode(EXCLUSION);
  
  String timeText = month + "月" + day + "日" + "(" + youbiString + ")" + nf(hour, 2) + ":" + nf(minute, 2) + ":" + nf(second, 2);
  drawText(LEFT, BASELINE, WHITE_COLOR, 36, timeText, 100, 30);
  
  // 他モジュールの描画時にも色が反転してしまうため、もとに戻す。
  blendMode(BLEND);
}

関数setup()内で、フォントを使用できるように設定します。

DigitalSignage.pde
void setup() {
  frameRate(1);
  noCursor();
  colorMode(HSB, 360, 100, 100, 100);
  
  // 色の初期設定。
  WHITE_COLOR = color(0, 0, 100);
  NEARLY_WHITE_COLOR = color(100, 2, 98);
  NEARLY_GREEN_COLOR = color(100, 5, 98);
  BLACK_COLOR = color(0, 0, 0);
  LIGHT_COLOR = color(0, 0, 80);
  GRAY_COLOR = color(0, 0, 50);
  GREEN_COLOR = color(150, 100, 60);
  
  // フォントを読み込み、デジタルサイネージで使うフォントとして設定。
  textFont(createFont("Noto Sans CJK jp Bold", 32)); // 追加
  
  // デジタルサイネージの背景画像を読み込む。
  background = pImageCut(loadImage("background.jpg"), CENTER, CENTER, width, height);
  
  // 初期化用関数initialize()を、draw()で画面が描画されているときに並行し実行(非同期処理)。
  thread("initialize");
}

関数drawModulesの中で呼び出します。

DigitalSignage.pde
void drawModules() {
  image(background, 0, 0);
  
  if (nowPageID == 0) {
    drawWeatherRModule(Area.area1);
    drawBusRModule(Area.area3);
    drawGomiRModule(Area.area5);
  } else if (nowPageID == 1) {
    // ModuleやRModuleの描画用関数を呼び出す
    drawTemperatureRModule(Area.area1);
    drawBrightnessRModule(Area.area2);
    drawTwitterRModule(Area.area3);
    drawOpenCloseRModule(Area.area5);
  } else if (nowPageID == 2) {
    // ModuleやRModuleの描画用関数を呼び出す
  }

  drawDateModule(); // 追加
  drawLocationModule();
}

実行すると、左上に時刻が表示されます。
(ただし、現時点では曜日は「null」になります)

0117.jpg

ページ切り替えまでの時間がわかるようにする

ページが切り替わってから、1秒経つごとに伸びていくバーを作ります。
下記記事で解説されている「ProgressBarModule」です。

ProgressBarModuleを描画する関数を作ります。

M_ProgressBar.pde
void drawProgressBarModule() {
  // 残り秒数を割合として算出(%)
  float progressRate = (second % STAY_SECOND) / float(STAY_SECOND-1);
  // 時間が経過したぶんだけ、白いバーが緑で塗りつぶされていく
  noStroke();
  fill(WHITE_COLOR);
  rect(0, height-PROGRESSBAR_HEIGHT, width, PROGRESSBAR_HEIGHT);
  fill(GREEN_COLOR);
  rect(0, height-PROGRESSBAR_HEIGHT, width * progressRate, PROGRESSBAR_HEIGHT);
}

関数drawModules内で呼び出します。

DigitalSignage.pde
void drawModules() {
  image(background, 0, 0);
  
  if (nowPageID == 0) {
    drawWeatherRModule(Area.area1);
    drawBusRModule(Area.area3);
    drawGomiRModule(Area.area5);
  } else if (nowPageID == 1) {
    // ModuleやRModuleの描画用関数を呼び出す
    drawTemperatureRModule(Area.area1);
    drawBrightnessRModule(Area.area2);
    drawTwitterRModule(Area.area3);
    drawOpenCloseRModule(Area.area5);
  } else if (nowPageID == 2) {
    // ModuleやRModuleの描画用関数を呼び出す
  }

  drawDateModule();
  drawLocationModule();
  drawProgressBarModule(); // 追加
}

実行すると、画面下にバーが表示されます。

0028.jpg

現在表示中のページが何番目かを可視化する

複数のページがあるうちで、現在何ページ目が表示されているかを可視化します。
下記記事で解説されている「PageControlModule」です。

PageControlModuleを描画する関数を作ります。

M_PageControl.pde
void drawPageControlModule() {
  for (int page = 0; page < PAGE_ALL_COUNT; page++) {
    // ページ番号をもとに点を横に並べる
    float x = width/2 + 30 * (page-(PAGE_ALL_COUNT-1)/2.0);
    float y = 1020;
    // 現在のページだけは白の点(緑の枠線付き)、それ以外は緑の点を打つ
    if (page == nowPageID) {
      fill(WHITE_COLOR);
      stroke(GREEN_COLOR);
      strokeWeight(5);
      circle(x, y, 20);
    } else {
      fill(GREEN_COLOR);
      noStroke();
      circle(x, y, 15);
    }
  }
}

関数drawModules内で呼び出します。

DigitalSignage.pde
void drawModules() {
  image(background, 0, 0);
  
  if (nowPageID == 0) {
    drawWeatherRModule(Area.area1);
    drawBusRModule(Area.area3);
    drawGomiRModule(Area.area5);
  } else if (nowPageID == 1) {
    // ModuleやRModuleの描画用関数を呼び出す
    drawTemperatureRModule(Area.area1);
    drawBrightnessRModule(Area.area2);
    drawTwitterRModule(Area.area3);
    drawOpenCloseRModule(Area.area5);
  } else if (nowPageID == 2) {
    // ModuleやRModuleの描画用関数を呼び出す
  }
  
  drawDateModule();
  drawLocationModule();
  drawProgressBarModule();
  drawPageControlModule(); // 追加
}

実行すると、画面下に点がいくつか表示されます。

0005.jpg

画像を全画面表示する

広告画像を全画面表示するために、「FullImageModule」を実装します。
下記記事で解説しているものです。

描画用関数を実装します。

M_FullImage.pde
void drawFullImageModule(PImage pImage) {
  image(pImage, 0, 0, width, height);
}

関数drawModules内で呼び出します。

DigitalSignage.pde
void drawModules() {
  image(background, 0, 0);
  
  if (nowPageID == 0) {
    drawWeatherRModule(Area.area1);
    drawBusRModule(Area.area3);
    drawGomiRModule(Area.area5);
  } else if (nowPageID == 1) {
    // ModuleやRModuleの描画用関数を呼び出す
    drawTemperatureRModule(Area.area1);
    drawBrightnessRModule(Area.area2);
    drawTwitterRModule(Area.area3);
    drawOpenCloseRModule(Area.area5);
  } else if (nowPageID == 2) {
    // ModuleやRModuleの描画用関数を呼び出す
    drawFullImageModule(adImage[0]); // 追加
  }

  drawDateModule();
  drawLocationModule();
  drawProgressBarModule();
  drawPageControlModule();
}

実行すると、3ページ目に全画面表示の画像が表示されるようになっています。

0021.jpg

次回

次はPart3です。
Part3では、Part2時点でスクリーンショットになっている部分を、Web APIやセンサなどに連動させていきます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?