3
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?

祝 なでしこ20周年! の電光掲示板をキャンバスで作るよ❗️

Last updated at Posted at 2025-11-30

なでしこ20周年.png

 なでしこさんのキャンバスを使って簡単なメディアアート。
 あるいは、描画中コンテキストからキャンバスの色情報を取得したり、描画中コンテキストのプロパティを変更したり参照したりなど、なでしこさんの描画命令だけではできないことをやってみる。

なでしことは

 日本語プログラミング言語「なでしこ」は、その名の通り日本語でプログラミングできる、素敵プログラミング言語です❣️
 なんと、この2025年で開発から20周年を迎えたとのことです。素晴らしいですね🎊
 日本語であることによる分かりやすさや親しみやすさ、そして気軽に始められるとっつきやすさが息の長い人気の秘訣でしょうか。

 なでしこ3なら、プログラム貯蔵庫で誰でも気軽にプログラムを動かして実際の動作を確認できますし、他の方の作ったプログラムで遊んだり、自分で作ったプログラムを投稿することもできます✨️

 
👇詳しくは公式ホームページで!

 とにかくめでたい節目の年ですので、お祝いメッセージを電光掲示板に流したいと思います。

とりあえず文字を流れさせます

電光掲示板の設定

 電光掲示板(canvas)の幅と高さ、流すメッセージと流れる速さを定義します。

掲示板幅400
掲示板高さ100
メッセージ「祝 なでしこ 20周年!」
速さ2

キャンバス

 電光掲示板用のキャンバスは、なでしこ3のプログラム貯蔵庫に標準で設置されているキャンバスを利用することにします。
 貯蔵庫のキャンバスはUIで簡単にサイズの設定が出来るようになっていますが、プログラム中で指定しておいたほうがコピペしたコードでも同様に動かせるし間違いないですね。

描画中キャンバス.幅属性掲示板幅
描画中キャンバス.高さ属性掲示板高さ

フォント

 流すメッセージの色やフォントを定義します。

背景色黒色
文字色金色
フォント「bold 80px sans-serif」
フォント描画フォント設定

 「描画フォント設定」は、cssのfont設定と同様の形式です。
 cssだって、font-stylefont-sizeがあるんだから、それぞれ別々に設定したいよぅ…(fontでまとめて設定するとfont-familyが必須なので、めんどくさいのです😅️)
 とはいえ、実は数値だけ入れれば、フォントサイズのみが設定できるという簡単仕様が搭載されているのですが、今回は太字設定もしたいのでまとめて設定しなきゃです。

📖 なでしこ3 マニュアル > plugin_browser/描画フォント設定

 なでしこはナゼか、v1の時代からフォントスタイルを設定したい人にキビシイ💧️

描画位置

 文字を右から左に流すので、文字描画のxの初期値は右端。つまり掲示板幅と同じで良いですね。

 そして、yですが・・・
 なでしこ1の文字描画で指定するx,yの位置は文字の左肩でしたが、なでしこ3では左下なので、v1の感覚で[0,0]に文字描画しようとすると、あれ? 描画されない!? ってなります。

 また、正確にはジャバスクリプトの規定値であるalphabeticなので、アルファベットのベースラインの左端。英小文字の g や y なんかは、その下にはみ出しますのでご注意です。
 キャンバスの下端ギリギリに設定したりすると、今度は英小文字の足が切れてしまうわけですよよよ。

 今回のメッセージは日本語だから関係ないけど、「Happy new year」とかにしたくなるかもしれないからね!
 日本語の縦位置を中央寄せにしたい場合も、ディセンダ(ベースライン下のはみ出し部分)を考慮に入れないと上に寄って見えちゃいます。

描画X掲示板幅
描画Y掲示板高さ-20

 ちゃんとする方法はいろいろあるのだろうと思いますが、今回は雑にキャンバスの高さからてきとーにマイナスしておきます😅️
 ディセンダは、だいたいフォントサイズの1/4くらいみておけば大丈夫そう?🤔️

メッセージの描画幅を取得

 メッセージが流れて左端に消えたら再び右側から出てくるようにするために、メッセージの実際の描画幅を取得します。
 描画中キャンバスに設定されているフォント情報でのサイズです。

メッセージ幅(メッセージ文字描画幅取得).width

 なでしこ1では、「文字幅取得」「文字高さ取得」で簡単に取得することができました。
 ところが、なでしこ3には「文字描画幅取得」という命令があるのですが、返り値は「TextMetricsオブジェクト」となっており、TextMetricsオブジェクトの内容を知らないと使えないという、なぜかちょっと賢い人向けの命令となっています。
 すべてのプロパティを利用できるようにということなのか、両方取得するときにいちいちTextMetricsオブジェクト取得しなおすのもったいないということなのか知らんが、正直ちょっと使いにくい😓️

 まあ、幅はwidthだからまだいいんですけど、高さはheightが無いんだよね~。
 こんなの綴れるわけないじゃーん💦️ って感じです。
 マニュアルにはv1と同じようにできるサンプルを載せています。

📖 なでしこ3 マニュアル > plugin_browser/文字描画幅取得

文字を流すアニメーション

 いったん背景色に塗りつぶし、描画Xを減らしながらメッセージを描画することを「画面更新時実行」でループさせるだけ。
 そして、描画Xがメッセージ幅だけマイナスになったら描画Xを右端に戻します。

電光掲示板描画
●電光掲示板描画
    背景色塗り色設定
    [0,0,掲示板幅,掲示板高さ]四角描画
    文字色塗り色設定
    [描画X,描画Y]メッセージ文字描画
    描画X速さだけ減らす
    もし描画Xメッセージ幅*-1ならば描画X掲示板幅
    「電光掲示板描画」画面更新時実行
ここまで

 できました!

👇️動作確認

 簡単ですね✨️

 でも、これは単に文字が流れているというだけのことです。
 もっとちゃんと電光掲示板っぽくしたいよね~。
 冒頭の画像みたいにLEDのドットで文字が描かれている的な?

リアル電光掲示板

 決まった文字を流すだけなら自分でドットのデータを作るという手もありますが、好きに入力したどんなメッセージでも流せるようにしたいです。
 というわけで、メッセージ文字列をドットに変換してみます。

LEDメッセージ作成

 まず、LEDのサイズと間隔を決めて、ドットのデータを収める配列と、電光掲示板とは別に、LEDメッセージを作成する裏キャンバスを作成します。
 裏キャンバスはユーザーから見えないように可視をオフにしておきます。

LEDサイズ3
LED間隔6
LEDデータ空配列
LEDキャンバス[メッセージ幅,掲示板高さ]キャンバス作成
LEDキャンバス.可視オフ

 そして、黒地に白でメッセージを描画して、その色データを取得し、LED間隔置きにデータを確認して、白だったら(一応中間値の128以上としています)LEDデータに配列追加していけばドットのデータが出来上がり!
 今度はそのデータをもとに円描画していけば、LED風のメッセージが出来上がるって寸法です。

# 黒地に白でメッセージを描画
黒色塗り色設定
[0,0,メッセージ幅,掲示板高さ]四角描画
白色塗り色設定
フォント描画フォント設定
[0,描画Y]メッセージ文字描画

# 色データを取得し、白い部分からドットを作成
変数 色データ[0,0,メッセージ幅,掲示板高さ]色データ取得
LEDデータ空配列
y0から掲示板高さまでLED間隔ずつ増やし繰り返す
    x0からメッセージ幅までLED間隔ずつ増やし繰り返す
        ID(y*メッセージ幅+x)*4
        もし色データ[ID]128ならばLEDデータ[x,y]配列追加
    ここまで
ここまで

# いったんクリアして背景を透明にし、LEDデータに従って円を描く。
全描画クリア
文字色塗り色設定背景色線色設定
LEDデータ反復
    対象LEDサイズ円描画
ここまで

 でも、色データの取得?🤔️

色データの取得

 なでしこの命令にはありませんが、描画中コンテキストのgetImageDataというメソッドを使って、キャンバスの色データをまるっと取得することができます。

●(xywhの|xywhを)色データ取得
 (描画中コンテキスト「getImageData」xywhJSメソッド実行).data戻す
ここまで

 内容は1ピクセルごとにRGBAの順に値が入った一次元配列です。

[0,0,0,1,255,255,255,1...]

 見た目には区切りも何もなく数値の並んだ一次元配列ですが、

[R,G,B,A,R,G,B,A...]

 となっていますから、四つ飛びでアクセスしていけば、高速に任意の点のRGBA値を取得したり、変更したりもできるって寸法です。

 
 色データをまるっと取得したり戻したりする命令は、あって良いと思うんだよねぇ~。
 思えばv1にも、画像から色情報を取得できる命令が、壊滅的に遅い「点取得」しかなくて、とてもとても辛かった記憶が・・・😢️

消灯しているLEDの表示

 実際の電光掲示板って背景は真っ黒じゃなく、点灯していない部分もうっすら見えているじゃないですか?

 背景を丸で埋め尽くすのは簡単です。
 xとyをLED間隔ずつ増やしながらひたすら円描画していけばよいだけ!

y0から掲示板高さまでLED間隔ずつ増やし繰り返す
    x0からLEDキャンバス幅までLED間隔ずつ増やし繰り返す
        [x,y]LEDサイズ円描画
    ここまで
ここまで

 円の色は、文字色、つまり点灯したLEDの色の透明度を落として薄くした感じにしたいなぁ~。

・・・ところが‼️

 文字色は「金色」と設定しており、このなでしこさんの色定数はカラーネームを日本語にしたものなので、金色には「gold」が設定されています。
 v1の場合は赤とか黒とかの色定数は「0xff0000」とか「0x000000」とかの十六進数が設定されており、rgbの値は計算で求めることができるのですが、なでしこ3で色定数を使い、その色を色々しようとすると、あれれ~? ということになってしまうんです。

 いやベツにgoldは「rgb(255,215,0)」と分かっているんですから、最初から文字色にそれを設定するなり、消灯したLEDの色をrgba(255,215,0,0.2)とでも設定してやればよいだけの話なんだけどもさー。
 なにしろとにかく日本語で設定したいワケですよ🤣️

 調べてみると描画中コンテキストのglobalAlphaの値を設定してやるのがカンタンらしい。
 一度設定すると、以降の描画はすべてその透明度で描かれるということなので、文字色は金色のままで、

描画中コンテキスト.globalAlpha0.2

 とか設定して消灯LEDを描画し、その後1に戻すだけでOKそう。

 
 また、もう一つの方法として、描画中コンテキストのfillStyleの値を参照すれば、カラーネームを設定していても16進数のカラーコードになっているようです。

金色塗り色設定
描画中コンテキスト.fillStyle表示。  //#ffd700

 これなら、透明度の設定のみならず、色を色々したい場合にも使えそうです。

 globalAlphaを設定すると描画のすべてがその透明度になってしまうのですが、輪郭線を黒色とすることでLEDの境界がくっきりとするようにしたいため、線色は半透明にしたくないので、今回は塗り色を取得し、16進数のカラーコードをRGB値に分解し、透明度を足してRGBAのカラーコードとして塗り色設定することにしてみます。

透明度0.2
文字色塗り色設定
塗り色描画中コンテキスト.fillStyle
塗り色RGB分解
消灯LED色「rgba({それ[0]},{それ[1]},{それ[2]},{透明度})」

●(色を|色の)RGB分解
 分色とは変数分色空配列
 「#」「0x」置換
 整数変換
 からまで繰り返す
  分色[]%256
  (-分色[])/256
 ここまで
 分色戻る
ここまで

 できました。
 日本語でやろうとしてムダに大変になってる感がありますが、わざとです。わざとなんですぅ~🤣️🤣️🤣️
 色を色々することや、描画中コンテキストのプロパティについて書きたかったのでっ。

 こういったキャンバスのコンテキストのプロパティは、なでしこのマニュアルでは用が足りず、ちょっとこんなこと出来ないかな? と思うとjavascriptのcanvas操作について検索しまくらなきゃならなくなるのでツライ~💧️
 検索して知ることができれば、オブジェクトプロパティ構文によりjavascriptのと同じように描画中コンテキストの参照や設定ができるので良いのですが、なんかもうちょっとこうDOMの和属性や和スタイルのように日本語でなんとかならないものかな?

描画中コンテキスト.透明度
描画中コンテキスト.塗り色

みたいに!!!

できました

 あとは黒く塗りつぶして文字描画する代わりに、背景キャンバスを画像描画してLEDキャンバスを画像描画していけばOK!

#--- 電光掲示板の設定 ----------
掲示板幅400
掲示板高さ100
メッセージ「祝 なでしこ 20周年!」
速さ3

# キャンバス
電光掲示板描画中キャンバス
電光掲示板.幅属性掲示板幅
電光掲示板.高さ属性掲示板高さ

# フォントと描画位置
背景色黒色
文字色金色
フォント「bold 80px sans-serif」

# 描画位置
描画X掲示板幅
描画Y掲示板高さ-20

# メッセージの描画幅
フォント描画フォント設定
メッセージ幅(メッセージ文字描画幅取得).width整数変換

#--- LEDメッセージ作成 ----------
LEDサイズ3
LED間隔6
LEDデータ空配列
LEDキャンバス[メッセージ幅,掲示板高さ]キャンバス作成
LEDキャンバス.可視オフ

# 黒地に白でメッセージを描画
黒色塗り色設定
[0,0,メッセージ幅,掲示板高さ]四角描画
白色塗り色設定
フォント描画フォント設定
[0,描画Y]メッセージ文字描画

# 色データを取得し、白い部分からドットを作成
変数 色データ[0,0,メッセージ幅,掲示板高さ]色データ取得
LEDデータ空配列
y0から掲示板高さまでLED間隔ずつ増やし繰り返す
    x0からメッセージ幅までLED間隔ずつ増やし繰り返す
        ID(y*メッセージ幅+x)*4
        もし色データ[ID]128ならばLEDデータ[x,y]配列追加
    ここまで
ここまで

# いったんクリアして背景を透明にし、LEDデータに従って円を描く。
全描画クリア
文字色塗り色設定背景色線色設定
LEDデータ反復
    対象LEDサイズ円描画
ここまで

#--- 背景作成 ----------
背景キャンバス[掲示板幅,掲示板高さ]キャンバス作成
背景キャンバス.可視オフ

透明度0.2
文字色塗り色設定
塗り色描画中コンテキスト.fillStyle
塗り色RGB分解
消灯LED色「rgba({それ[0]},{それ[1]},{それ[2]},{透明度})」

背景色塗り色設定
[0,0,掲示板幅,掲示板高さ]四角描画
消灯LED色塗り色設定
y0から掲示板高さまでLED間隔ずつ増やし繰り返す
    x0からメッセージ幅までLED間隔ずつ増やし繰り返す
        [x,y]LEDサイズ円描画
    ここまで
ここまで

#--- 電光掲示板描画アニメーション ----------
電光掲示板描画開始
電光掲示板描画

●電光掲示板描画
    [0,0]背景キャンバス画像描画
    [描画X,0]LEDキャンバス画像描画
    
    描画XLED間隔だけ減らす
    もし描画Xメッセージ幅*-1ならば描画X掲示板幅
    (0.1/速さ)秒待つ
    「電光掲示板描画」画面更新時実行
ここまで

#-----------------------------------------------
●(xywhの|xywhを)色データ取得
 (描画中コンテキスト「getImageData」xywhJSメソッド実行).data戻す
ここまで

●(色を|色の)RGB分解
 分色とは変数分色空配列
 「#」「0x」置換
 整数変換
 からまで繰り返す
  分色[]%256
  (-分色[])/256
 ここまで
 分色戻る
ここまで
#-----------------------------------------------

 できました!
電光掲示板.gif

👇️動作確認

おわります

 今年もアドベントカレンダー始まりました。
 めでたい節目の年です。
 みなさん奮ってご参加ください!

3
1
3

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
3
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?