kintoneでオリジナルティキシールを作ろう!〜後編〜

こんにちは、ジョイゾーTech.チームの田中と川嵜です!

前半では『オリジナルティキ作成』の仕組みについて解説しましたが、
こちらでは、ティキの印刷機能や光るギミック、ティキの世界観に沿った装飾といった『各種ギミック』の仕組みについてお話ししていきます。

その前に「前編」と「リアルティキの作成過程note」もぜひご覧ください!
kintoneでオリジナルティキシールを作ろう!〜前編〜
神の像「ティキ」を動かそう!Cybozu Days 2025 JOYZO Tech.チーム

弊社では初回開発無料の定額39万円でkintoneアプリを開発する定額型開発サービス「システム39」を提供しております。kintoneの導入やアプリ開発でお困りの方は、お気軽にご相談ください。
*Webでの打ち合わせも可能です。

   kintoneのアプリ開発はこちら <相談無料>    

Print Tikiボタン押下以降の処理について

自分のTikiを作ったら、いよいよプリント!
「Print Tiki」ボタンを押下するタイミングでもギミックを何個か入れています。

まずはギミックの全容です。

  1. ①ユーザーが「Tiki Print」ボタンを押すと、カスタムされた進捗ポップアップが表示されます。
  2. ②レコードの「属性」(例:水、炎)を読み取ります。
  3. 【音楽・IoT連携】: 「属性」に応じたBGMが再生され、同時にObnizデバイスのLEDがテーマカラーで光り始めます。
  4. 【帳票出力】: k-ReportのAPIが呼び出され、PDFの生成が開始されます。
  5. 【プリント】: k-Reportダイレクトプリント機能を利用し、プリンターから作成した帳票を出力します。

プリント処理だけではなく、音とLEDを光らせるというギミックも同時に仕込んでいます。

システム全体の構成

メインとなる「Tiki Gallery」アプリを中心にして、いくつかのサービスやコンポーネントが連携することで動いています。

コンポーネント役割
kintone(Tiki Gallery)起点となるボタンを表示、データ(属性)の提供
kintone(Tiki Music Master)5種類の音楽ファイル(mp3ファイル)を格納するマスタ
k-Report帳票(PDF)の生成・kintoneへの添付・ダイレクトプリント
ObnizLED点灯

3つのポイント

それぞれの動きについて掘り下げます!

ポイント1: Obniz連携による「属性」の視覚化

今回は、LEDを光らせるためにIoTデバイス「Obniz」を利用することとしました。
連携についてはcybozu developer networkにも記事があるのでこちらを参考にしてみました。
obnizとkintoneでIoT連携してみよう!

今回の連携では、kintoneの「属性」フィールドが持つ値(水、風、炎など)を読み取り、それをWebで使われる色情報(色相)に変換します。

// kintoneのフィールド値(文字列)を「色相(Hue)」という数値に変換する
  function attrToHue(attrJa) {
    switch (String(attrJa || "").trim()) {
      case "水":
        return 210; // 青
      case "風":
        return 50;  // 黄色
      case "炎":
        return 0;   // 赤
      case "草":
        return 120; // 緑
      case "愛":
        return 330; // ピンク
      default:
        return 200; // デフォルト(シアン系)
    }
  }

ただ光らせるだけだと地味なので、光らせ方も指示をしています。
複雑な光らせ方も、AIでコーディングすることで難なく実装できてしまいました。

  • その色をベースに、美しいグラデーションパターンを自動で計算。
  • 光が流れるようなエフェクトや、キラキラと輝くエフェクトを上乗せ。
// ...(ベースとなるグラデーション base を作成)...

          let head = 0,
            phase = 0;
          const intervalMs = 70; // アニメーションの更新間隔(ミリ秒)

          animTimer = setInterval(() => {
            // 1. グラデーションを1つずらして回転させる
            base = base.slice(1).concat([base[0]]);
            let frame = base.map((rgb) => rgb.slice());

            // 2. コメット(彗星)エフェクト(流れ星)
            head = (head + 1) % NUM_LEDS;
            frame = applyCometTrail(frame, head, 6, 1.0);

            // 3. スパークル(きらめき)エフェクト
            frame = applySparkle(frame, 1);

            // 4. ブレス(呼吸)エフェクト(全体が明暗する)
            phase = (phase + intervalMs / 2400) % 1;
            frame = applyBreathWave(frame, phase, 0.15);

            try {
              // 最終的な光のデータをObnizに送信
              strip.rgbs(frame);
            } catch (e) {}
          }, intervalMs);

この連携によって、単に「処理中」と表示するのではなく、「今、あなたの『炎』属性のTikiを処理していますよ」ということが、光によって直感的に伝わるようにしています!

こんな感じで光る!!(これは「愛」)

ポイント2: K-Report とPrintNodeによる「ダイレクトプリント」の仕組み

帳票出力は、k-Reportをベースに利用しています。
k-Reportを選定した理由としては、
・k-ReportのAPIを利用することで、オリジナルの「Print Tiki」ボタンを押下したタイミングで帳票出力ができる
・PrintNodeと連携してダイレクトプリント機能を実現できる

k-Reportについて詳細はこちら
k-Reportサービスサイト

ダイクトプリントを利用するためには、k-Report側で提供される
・[ k-Report API ] Report TOKEN
・[ k-Report API ] Connection TOKEN
と、
Print Nodeというサービスの登録が必要です。
トークン部分の詳細はオーサムジョブさんが提供しているマニュアルをご参照ください。

PrintNode連携 k-Reportからプリンタへ高速ダイレクト印刷

今回のJavaScriptでは、この「ダイレクトプリント(DP=1)」を指定してAPIを呼び出す部分を、以下のように実装しています。

  // ===== 設定 =====
  // ...(省略)...
  const ATCODE = "出力ファイル";
  
  // ↓↓↓↓ ここで「1(ダイレクトプリント)」を指定 ↓↓↓↓
  const DP = "1"; // 1=ダイレクトプリント, 0=通常
  
  const KREPORT_BASE_URL =
    "[]";
  
  // ...(省略)...

  // ===== PDF出力 =====
  async function runKReportPdfForRecord(recordId) {
    const query = `レコード番号 = "${recordId}"`;
    
    // APIのURLを組み立て
    const url =
      `${KREPORT_BASE_URL}?t=${REPORT_TOKEN}` +
      `&user=${encodeURIComponent(USER_NAME)}` +
      `&query=${encodeURIComponent(query)}` +
      `&atcode=${encodeURIComponent(ATCODE)}` +
      `&bt=${CONNECTION_TOKEN}&dp=${DP}`; // ← ここで DP="1" が使われる

    // APIを呼び出す
    const res = await fetch(url, { method: "GET", cache: "no-store" });
    // ...(エラーハンドリングなど)...
    
    // k-ReportのトリガーURLを叩いて実行
    for (const item of json.records) {
      await fetch(item.trigger, { cache: "no-store" });
    }
  }

また、k-Reportの各種マニュアルの中にある「[11]k-ReportAPIの御利用サンプル」のZipファイルをダウンロードすると、ダイレクトプリントのサンプルコードを入手することができます!
今回はサンプルコードをほぼ変えずに実装することができたのでコードは割愛しますが、気になる方はチェックしてみてください!

k-Report 各種マニュアル&リンク

ポイント3:「属性」に応じたBGMを再生

続いては、BGMを再生する機能についてです。
「Print Tiki」ボタンを押下した際に、
該当レコードに付与されている属性(愛/炎/水/草/風)をに応じて、BGMを再生する機能を実装しました。

音楽を再生するまでのステップ

この機能は、以下の4ステップで実現することができました。

  1. ①「Print Tiki」ボタンを押下する
  2. ②「Tiki Gallery」アプリの該当レコードから、付与されている属性を取得する
  3. ③「Tiki Music Master」アプリから、取得した属性と合致するBGMを取得する
  4. ④取得したBGMをブラウザ上で再生する
 // STEP1~4の処理以外は省略しています。 
 // STEP 1: Print Tiki ボタンを押下する
  const registerPrintTikiButton = () => {
    const btn = document.getElementById("btn_tikiPrint");
    if (!btn || btn.dataset.listenerAdded) return;
    btn.addEventListener("click", async () => {
      const attribute = getAttributeFromGallery();
      if (!attribute) return;
      const fileKey = await fetchBgmFileKey(attribute);
      if (!fileKey) return;
      await playBgmInBrowser(fileKey);
    });
    btn.dataset.listenerAdded = "true";
  };

  // STEP 2: Tiki Gallery から属性を取得する
  const getAttributeFromGallery = () => {
    if (!currentRecord) return null;
    return currentRecord[ATTRIBUTE_FIELD]?.value;
  };

  // STEP 3: Tiki Music Master から BGM 情報を取得する
  const fetchBgmFileKey = async (attribute) => {
    const query = `${MUSIC_ATTRIBUTE_FIELD} in ("${attribute}")`;
    const response = await kintone.api(
      kintone.api.url("/k/v1/records", true),
      "GET",
      {
        app: MUSIC_APP_ID,
        query
      }
    );
    const match = response.records?.[0];
    return match?.[FILE_FIELD_CODE]?.value?.[0]?.fileKey || null;
  };

  // STEP 4: 取得した BGM をブラウザで再生する
  const playBgmInBrowser = async (fileKey) => {
    const fileUrl = `${kintone.api.url("/k/v1/file", true)}?fileKey=${fileKey}`;
    const res = await fetch(fileUrl, {
      headers: { "X-Requested-With": "XMLHttpRequest" }
    });
    const blob = await res.blob();
    let player = document.getElementById("musicPlayer");
    if (!player) {
      player = document.createElement("audio");
      player.id = "musicPlayer";
      player.controls = true;
      document.body.appendChild(player);
    }
    player.src = URL.createObjectURL(blob);
    await player.play();
  };

これまでこのようなカスタマイズ経験はありませんでしたが、
AIを活用することで、「ボタン押下→属性取得→BGM取得→音楽を再生」
という「BGM再生機能」を短時間で作り上げることができました!

AIを用いて属性別のBGMを作成

初めはフリーBGMの中から、属性に近しいものを探して使用していましたが、
イメージにピッタリ合うものが見つかりませんでした。

そこで、この課題を解決するために、音楽もAIを活用してイメージに合うものを作ってみよう!ということでやってみました。

今回使ったのはSuno AIというもので、曲やBGMが生成できるAIツールです。
普通にAIを使う時と同様にプロンプトを入力することで、その内容に沿った音楽を作り出すことができます。

Suno AIのサイトはこちら
Suno AI

BGM制作の過程

プロンプトには、主に以下の要素を入れていきました。

  • ハワイの伝統的な音楽にする
  • 太鼓などの打楽器を用いた「ドコドコ感」を入れる
  • 属性に応じたイメージの曲調にする
  • 歌詞入れずに15秒程度のBGMにしてほしい

このような感じに要望をまとめて試しに一曲作ってみてもらった所、想像以上に出来が良かったため、本格的に作業に取り掛かりました。
作業に取り掛かるといっても、プロンプトを正確な内容にするだけですが、
それによってかなりイメージに近しいものが出来上がったので、採用してアプリに反映をさせていきました。

※ Suno AIをフリープランで利用する場合は、ダウンロード回数やリクエスト回数などの制限があるのでご注意ください。

CSSでアプリ全体を装飾

最後に仕上げとして、CSSでアプリ全体の装飾を行いました。
こちらもAIをフル活用して、作業を進めていきました!

また、自分で作ったティキの画像にサインができるように、ジョイゾーの「手書き2プラグイン」を使用しているのですが、こちらにもティキの世界観と合うよう手を加えていきました。

手書きエリアが波のようにホバーするアニメーション、様々な箇所にティキを配置し動かせる、ジャングルのテーマの適用などの装飾を加えていきました。

CSSとAIを駆使してアプリ全体を装飾し、
ティキの世界観に合わせた以下のような見た目に変えることができました!

まとめ

本記事では、「Print Tiki」ボタン押下時に発動する、各種ギミックの仕組みと、それを支える技術についてご紹介しました。

AIをフル活用してコーディングすることで、開発スピードを大幅に向上させ、ティキの世界観を深く表現することを可能にしました。
このプロジェクトは、既存のツール(kintone、k-Report)と新しい技術(IoT、生成AI)を組み合わせることで、「楽しさと驚きのギミックを仕掛ける」という遊び心を形にできた好例となりました。

今後もこうした技術的なチャレンジを通じて、次にどんな「面白いこと」ができるのか追求し続けていきます!

弊社では初回開発無料の定額39万円でkintoneアプリを開発する定額型開発サービス「システム39」を提供しております。kintoneの導入やアプリ開発でお困りの方は、お気軽にご相談ください。
*Webでの打ち合わせも可能です。

   kintoneのアプリ開発はこちら <相談無料>    

同じカテゴリーの記事