まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

2020/05

GitHub が提供をはじめた CI/CD 機能である GitHub Actions を使って IBM Cloud の IKS(IBM Kubernetes Services) にアプリケーションをデプロイできることを確認したので、一連の手順を紹介します。


【何をする?】
簡単に言うと、GitHub のリポジトリにアプリケーションのソースコードをコミット&プッシュすると、その最新コードのアプリケーションが IBM Cloud 内の Kubernetes サービスへ自動デプロイされて公開される、ということを GitHub 内の機能だけで実現します。

なお、GitHub Actions は GitHub の無料アカウントで使える機能であることに加え、IBM Cloud の IKS も(クレジットカード登録が必要な BASIC アカウントに切り替える必要はありますが)Kubernetes のシングルワーカーノードが 30 日間無料で利用できます。 以下に紹介する内容は全て無料で試すことができる内容です。

では以下に IKS の準備、GitHub の準備に続けて実際にアプリケーションコードをコミットして IKS 上で動かす所までの手順を紹介します。


【IKS の準備】
IBM Cloud で IKS サービスを作成します。IBM Cloud にログインします。ライトアカウントの場合は IKS が利用できないため、クレジットカードを登録して BASIC アカウントに切り替えるか、または新たにアカウントを作成して BASIC アカウントに切り替える必要があります。

BASIC アカウントでログイン後、画面右上の「リソースの作成」ボタンをクリックします:
2020052701


作成するサービスを一覧から選択します。画面左メニューから「サービス」-「コンピュート」を選択し、画面右の一覧から "Kubernetes Service(以下 IKS)" を選択します:
2020052702


IKS は有償版と無償版(30日経過後に削除)があります。以下は無償版である「無料クラスター」を選択している想定で紹介を続けます。クラスター名は "mycluster" 、リソースグループは "Default"(いずれも既定値)として画面右の「作成」ボタンをクリックします:
2020052703


ここから IKS 環境の作成が始まります。操作できる状態になるまでしばらく(数10分程度)かかります:
2020052704


この IKS の準備をしている時間を使って、この後の作業で利用する API キーを用意しておきます。画面右上のメニューから「管理」を選び、「アクセス(IAM)」を右クリックしてリンクを新しいタブで開く形で(つまり別ウィンドウや別タブで開く形で)選択します:
2020052706


別ウィンドウでアクセス設定画面が開いたら、画面左メニューで「API キー」を選び、「IBM Cloud API キーの作成」ボタンをクリックします:
2020052707


ダイアログが表示されるので API キーの名称(任意ですが、例えば "API Key for GitHub Actions" など)を入力して「作成」します:
2020052708


正しく実行できると以下のような画面になります。作成された API キーはマスクされ、表示されていません。この画面をこのまま閉じてしまうと作成された API キーの内容を再度確認することはできなくなるため、ファイルでダウンロードしておくか、クリップボードにコピーしておくか、目のアイコンをクリックして、マスクを外して表示し、その内容をどこかに保存しておく必要があります:
2020052709


目のアイコンをクリックするとマスクがはずれ、API キーの値を確認することができます。繰り返しますが、このダイアログを消すと API キーを再確認することはできません。忘れてしまった場合は再度 API キーを新規作成する必要がある点に注意してください。なんらかの方法で API キーの内容を再確認できるようこの内容を保存しておきます(後で使います):
2020052710


あらためて IKS サービスの作成状況を確認しておきましょう。「ファイナライズ中」と出ていればあと少しです。。。:
2020052711


しばらく待って全ての準備が完了すると、下図のように「通常」というステータスに変わります。この状態になっていれば IKS 上にアプリケーションをデプロイするための準備が整ったことになります:
2020052712


この画面を離れる前に Web 端末の準備もしておきます。この IKS で用意する Kubernetes 環境はローカルマシンの kubectl などから操作することも可能ですが、kubectl の環境を持っていない人でもブラウザ画面から利用できるターミナル機能が用意されており、こちらを使うことでローカルインストールや環境設定も不要で利用することができるようになって便利です。

Web 端末を利用するには IKS 画面右上の「Actions...」と書かれた箇所をクリックし、メニューから「Web 端末」を選択します:
2020052705


初めてこの操作をした場合はインストールができていないため以下のようなダイアログが表示されます。「インストール」をクリックして数分お待ち下さい:
2020052713


Web 端末のインストールが出来た後に改めて「Actions...」-「Web 端末」を選択すると、画面内にターミナル機能が現れ、ここから kubectl コマンドや IBM Cloud への命令を実行する ibmcloud コマンドを利用することができるます。画面が小さくて不便な場合は(別タブに)最大化して利用することもできます:
2020052714


この Web 端末を使って IBM Cloud CR(Container Registry) の名前空間をセットアップしておきます(後で使います)。まず "ibmcloud login" と入力します。IBM ID とパスワードの入力が促されるので入力し、Web 端末で IBM Cloud にログインします:
$ ibmcloud login

一度この時点で CR の名前空間一覧を確認しておきます。確認するためのコマンドは "ibmcloud cr namespaces" で、初めて実行した場合は1つも定義されていないという結果となるはずです:
$ ibmcloud cr namespaces

改めて名前空間を作成します。ユニークな名前空間名を指定して "ibmcloud cr namespace-add (名前空間)" を実行します:
$ ibmcloud cr namespace-add (名前空間名)

名前空間名は他の人が使っているものを指定することはできません(エラーとなります)。自分の場合は "ibmcloud cr namespace dotnsf-ns" と入力しました。実際に実行する場合はここで他の人が使っていないものを指定して実行してください(エラーとなる場合はエラーにならずに実行完了するまで繰り返して実行してください)。

最後に CR の名前一覧表示コマンドを再度実行し、直前のコマンドで作成した名前空間が一覧に含まれていることを確認してください:
$ ibmcloud cr namespaces

自分の上記例ではこんな感じになりました。この名前空間名も後で利用します:

2020052701


IKS の準備作業はこれで終わりです。


【アプリケーションおよび GitHub の準備】
次に IKS にデプロイするアプリケーションと GitHub 側の準備を行います。まずはデプロイするアプリケーションを準備して Docker 対応(Dockerfile の準備)します。ここは実際に IKS にデプロイして使ってみたいアプリがある場合は個別に用意していただいても構いません。

一応サンプルとしてシンプルな Web アプリケーションを用意しました。自分でアプリケーションを用意しない場合はこちらをお使いください:
https://github.com/dotnsf/hostname_githubactions_iks


このサンプルを使う場合は、まず GitHub にログインした上で上記 URL を開きます。そして画面右上の "fork" を選択し、自分自身のリポジトリとして複製してください:
2020052702


成功すると https://github.com/XXXXX/hostname_githubactions_iks というリポジトリができあがります(XXXXX 部分は各ユーザー個別の ID 名)。以降はこのリポジトリを使って GitHub Actions を利用します。まずこの URL を指定してリポジトリの内容をローカルに clone しておきます(XXXXX 部分は自分の ID に置き換えて実行してください):
$ git clone https://github.com/XXXXX/hostname_githubactions_iks

これでサンプルアプリケーションのソースコードがローカルファイルとしてクローンされ、ローカルファイルとして参照することができるようになりました。簡単にアプリケーションの内容を紹介しておくと、このサンプルアプリケーションは Node.js で実装されており、 GET / という HTTP リクエストに対して /etc/hostname ファイルの内容を text/plain でそのまま返すだけの機能を持っています。本体である app.js ファイルの全容は以下(これで全部)で、実質20行足らずの実装です。またポート番号は 8080 番で固定しています:
//.  app.js
var express = require( 'express' ),
    fs = require( 'fs' ),
    app = express();

app.get( '/', function( req, res ){
  res.contentType( 'text/plain; charset=utf-8' );
  fs.readFile( '/etc/hostname', "utf-8", function( err, text ){
    if( err ){
      res.write( JSON.stringify( err, 2, null ) );
      res.end();
    }else{
      res.write( text );
      res.end();
    }
  });
});

var port = 8080;
app.listen( port );
console.log( "server starting on " + port + " ..." );


この app.js と、依存ライブラリや起動コマンドが記述された package.json や、コンテナ対応のための Dockerfile などが含まれたアプリケーションとなっています。

繰り返しますが、実際に IKS にデプロイするアプリケーションは Docker 対応できていれば他のものを使っても構いません。ただしその場合はこのサンプルの .github/ フォルダ以下をまるごとそのアプリケーションプロジェクトにコピーしておいてください(実質的に .github/workflows/iks.yml ファイル1つだけのフォルダで、この iks.yml が Github Actions を IKS で使うためのワークフローを定義しています)。

iks.yml ファイルの中身はこの後で参照しますが、このファイルは Github のプロジェクトのシークレット情報を参照して動くよう定義されています。したがって必要なシークレット情報を Github プロジェクト内にあらかじめ定義しておく必要があります。

そのための設定を行います。 https://github.com/XXXXX/hostname_githubactions_iks を開き、"Settings" タブを選んで左メニューから "Secrets" を選択します。このプロジェクトに設定されたシークレット情報の一覧が表示されますが、最初は空のはずです。ここにシークレット情報を追加するため "New secret" ボタンをクリックします:
2020052703


シークレット情報は名前(Name)と値(Value)の組で定義します。まずは "IBM_CLOUD_API_KEY" という名前のシークレットを定義します。この値としては上述した IBM Cloud 利用時に作成してダウンロードするかクリップボードに保存した IBM Cloud API Key の値を入力します。入力後に "Add secret" ボタンをクリックして保存します:
2020052704


同様にしてもう1つ、"ICR_NAMESPACE" という名前で、 IBM Cloud CR の名前空間として作成した名称(上記例では dotnsf-ns ですが、個別に作成した時の値)を入力し、最後に "Add secret" をクリックします:
2020052705


つまりプロジェクトのシークレット情報として IBM_CLOUD_API_KEY と ICR_NAMESPACE の2つが定義されている状態にします。これで GitHub プロジェクト側の準備は完了です:
2020052706


最後に Github Actions のワークフロー定義を各自の内容に合わせて書き換えます。プロジェクト内の .github/workflows/iks.yml ファイルをテキストエディタで開きます。なおこのファイルの内容は以下のプロジェクトに含まれて提供されていたものをベースにしています:

https://github.com/IBM/actions-ibmcloud-iks


iks.yml を開き、20 行目以下(env: で始まる行以下)の値を編集します。といっても自分の独自アプリケーションではなく https://github.com/dotnsf/hostname_githubactions_iks からフォークしたプロジェクトのアプリケーションを使う場合はほぼそのままでも動くはずです:
2020052707


編集の必要な箇所があるとすれば以下です:
変数名設定内容既定値
IBM_CLOUD_REGIONIBM Cloud で利用する IKS のリージョン(地域)us-south
REGISTRY_HOSTNAME内部で利用する Docker Hub のホスト名us.icr.io
IMAGE_NAMEDocker イメージを保存する時の名称hostname
IKS_CLUSTERIKS 作成時に指定したクラスタ名mycluster
DEPLOYMENT_NAMEDocker イメージを IKS にデプロイする時の DEPLOYMENT の名称hostname
PORTアプリケーションが HTTP アクセス時に LISTEN するポートの番号
8080


ここまでの作業で hostname_githubactions_iks プロジェクト(Github にコミットするプロジェクト)のファイルに変更を加えている場合はこれで準備完了です。加えていない場合はコミットに変化を加えるというだけの目的でいずれかのファイルに挙動に支障のない変更を加えておいてください。例えば README.md ファイルの最後に空の1行を追加する、などでも構いません(苦笑):
2020052708


これで全ての事前準備が整いました。


【GitHub Actions の実行】
ではこのプロジェクトを Github にコミット&プッシュします:
$ cd hostname_githubactions_iks

$ git add .

$ git commit -m 'README.md updated.'

$ git push


Push の成功と同時に Github Actions が実行されます。リポジトリのページ(https://github.com/XXXXX/hostname_githubactions_iks )を開き、"Actions" タブを選択すると、コミットコメントの横にクルクル回るアイコンが表示され、Github Actions に定義された内容(iks.yml の内容)に従ってアプリケーションイメージが内部 Docker Hub に登録され、そこから IKS へデプロイされていきます:
2020052709


しばらくすると一連の作業が完了します。下図のように緑のチェックマークが表示されていればコマンドが成功しています(赤いバツは失敗):
2020052710


この箇所をクリックすることでワークフローで実行された内容の詳細を確認したり、(失敗している場合は)どこで失敗しているかを確認することもできます:
2020052700


この時点でアプリケーションは IKS 内にデプロイされ動いており、パブリックに公開されています。では実際に動いているアプリケーションにアクセスしてみたいのですが、そのためにはアクセスするための情報(IP アドレスおよびポート番号)を見つける必要があります。

まず公開されているパブリック IP アドレスは IBM Cloud ログイン後のダッシュボードから確認することができます。作成した IKS のワーカーノードを表示し、稼働しているサービスのパブリック IP を確認します。これが外部アクセス用の公開 IP アドレスとなっています:
2020052701


またポート番号は Web 端末から "kubectl get svc" を実行し、サービス名(iks.yml で指定したデプロイ名、上述の例だと hostname)の PORT(S) 列を参照します。 "80:*****/TCP" と表示されている ***** 部分(下図の場合は 32284)がサービスにアクセスするためのポート番号となります:
2020052702


これらを組み合わせてウェブブラウザまたは curl コマンドなどで http://(IP アドレス):(ポート番号) にアクセスします。下図の例では http://173.193.112.74:32284/ へアクセスしています。またその実行結果として(コンテナの /etc/hostname の中身である hostname-59cb7b958f-lwv52 という値が表示されています。この結果は実行環境によって異なりますが、実際に稼働しているコンテナから取得した値となっています)。実際の稼働環境にアクセスして挙動を確認することもできました:
2020052703


この時点で IKS 上で稼働しているので、インスタンスのスケールイン/スケールアウトといった操作も可能です。

またこの状態から更にアプリケーションのソースコードを改良するなどした上で、再度 git commit & git push すると同じワークフロープロセスが動き、自動的に IKS 内に最新コードのアプリケーションがデプロイされる、という CI/CD 環境が構築できました。


【デプロイしたポッド等を削除する場合】
最後に環境を削除する手順を紹介します。IKS そのものごと削除する場合は(IBM Cloud のメニューから IKS ごと削除すればよいので)ある意味で簡単ですが、IKS を残して IKS 内にデプロイしたアプリケーション環境を削除する場合の手順を紹介します。

まず Web 端末で "kubectl get all" を実行して、ポッドやサービス、デプロイメントの情報を確認します:
2020052704


この実行結果から hostname 関連のポッド、サービス、デプロイメントを削除します。Web 端末で続けて以下のコマンドを実行します(service/kubernetes のサービスは IKS そのものなので削除しないよう気をつけてください):
$ kubectl delete deployment hostname

$ kubectl delete service hostname

$ kubectl delete pod hostname-59cb7b958f-lwv52

最後にもう一度 "kubectl get all" を実行して、hostname 関連のものが残っていないことを確認します:
2020052705


上記のような結果になれば無事に削除できました。
 

最近のマイブームとなっている「あつまれ どうぶつの森」(以下「あつ森」)関連のブログエントリです。

マンホールマップに投稿されている約1万件(2020/05/25 時点)のマンホール画像が「あつ森」のマイデザインとして取り込むことができるようになりました。


以前にニューヨークのメトロポリタン美術館が約40万点の美術作品に対して「あつ森」のマイデザインとして取りこむことができるようになった、というニュースがありました。これのパクり・・インスパイアされた機能で、約1万点(プラス、後述のおまけで1点)のマンホール・デザインをマイデザイン化して登録できるようになりました。既にこの機能は有効です。


ではマンホールマップから「あつ森」マイデザインに登録するための手順を以下に紹介します。「あつ森」を既に所有している前提はもちろん必要ですが、手順の中で Nintendo Switch Online アプリを利用することになります。事前にお手持ちのスマホに Nintendo Switch Online アプリをダウンロードし、「あつ森」利用時に使っているニンテンドーアカウントでセットアップして利用できる状態にしておいてください:
2020051903


マンホールマップから「あつ森」マイデザインに取り込むには、まずマンホールマップにアクセスします。この手順は PC またはスマホのウェブブラウザを使って行いますが、後述の QR コード読み取りをスムーズに行うことを考えると PC での(というか、Nintendo Switch Online アプリをインストールしていないデバイスでの)利用を推奨します:
https://manholemap.juge.me/


マンホールマップから「あつ森」マイデザインとして取り込みたいマンホール画像を1つ選びます。マンホールマップから画像を選択する方法は何通りかありますが、例えばトップページの一覧から1つ選び、プレビュー画面のマンホール画像をタップすることで詳細ページにアクセスできます:
2020052501



マンホールの詳細ページではマンホール画像とそのマンホールが存在する位置を示す地図が表示されます。このページ下部に「QR コード」と書かれたボタンがあるのでタップします:
2020052502


すると画面に QR コードが表示されます:
2020052503


次にこの QR コードを Nintendo Switch Online アプリで読み取る作業になります。つまりこの QR コードが表示されている状態のままアプリを起動する必要がある点に注意してください。場合によっては一度 QR コードのスクリーンショットを撮った上で画像共有アプリと連携したり、PC や他のスマホを併用する必要があると思っています。

改めてこの表示されている QR コードを Nintendo Switch Online アプリの「あつまれ どうぶつの森」サービス内「タヌポータル」の「マイデザイン」を使って読み込みます。まずは Nintendo Switch Online アプリを起動し、「あつまれ どうぶつの森」を選択して、「タヌポータル」から「マイデザイン」を選択します。:
2020051904


マイデザイン内の機能を使って、マンホールマップで表示されている「QR コードを読み取り」ます:
2020051905


正しく読み取りが実行できると、マンホールマップで表示されていたマンホール画像がプレビューされ、保存するかどうか確認されます。マイデザインは 32x32 のサイズで最大 15 色に減色されるためかなり荒くなってしまう点にご注意ください。マイデザインに取り込む作業を続けるには「保存する」を選択します:
2020052504


正しく読み取って保存することができました:
2020052505


ここまでの状態になると「あつ森」ゲームからダウンロードしてマイデザインに取り込むことができるようになります。ここから先は実際に「あつ森」ゲームを使う作業になります。

Nintendo Switch で「あつ森」を起動し、(ゲーム内の)スマホからマイデザインアプリを選択します:
2020051908


マイデザインを開き、画面右下の「ダウンロード」を選択します:
EY2Mr6pU8AAfCHL


すると先程 Nintendo Switch Online アプリで QR コードを読み込んだデザインの情報が表示されます。正しければ「オッケー」を選び、上書きしてもよい保存先を選びます:
EY2Mr6dU4AAmDSw


保存先を選択すると、QR コードを読み取ったマンホール画像が縮小・減色されてマイデザインとして保存されます:
EY2NePfUEAAs4Tl


取り込んだマイデザインは他のマイデザイン同様にゲーム内でトップスとして着たり、島の地面に敷いたりすることができます:
EY2NeOsUMAAWs6I


・・・といったことがマンホールマップ内に登録されている全てのマンホール画像に対して行うことができるようになりました。


【おまけ機能】
マンホールマップの「あつ森 マイデザイン」機能にはおまけがあります。マンホールマップ内に保存されている全マンホール画像に加えて、(マンホールマップにログインする際の)自分の Twitter アイコンも同様にマイデザイン化することができます。

上述のマンホール画像→マイデザインではログインは不要でしたが、このおまけ機能を試す場合はログインの必要があります。マンホールマップに画面右上のメニューからログインします:
2020052501

2020052502


マンホールマップのログインには Twitter の OAuth を使います。したがって Twitter の有効なアカウントが必要です。またこのログインする Twitter アカウントに設定されているプロフィールアイコン画像を対象に QR コードを生成するため、あらかじめ Twitter のプロフィールアイコン画像を設定しておきます:
20200525


改めてログイン後に画面右上のメニューから「アイコンの QR コード化」を選択します:
2020052506


すると上述した時と同じような QR コードが表示されます:
2020052507


ここから先の手順は上述した内容と同じです。Nintendo Switch Online アプリの「あつまれ どうぶつの森」サービスの「タヌポータル」から QR コードを読み取ることで Twitter アイコンをマイデザインとして保存できるようになります:
2020052508


保存すると「あつ森」アプリからダウンロードできるようになります:
2020052509


ここから先は上述した内容と一緒です。「あつ森」アプリのスマホ内「マイデザイン」からダウンロードを選択して、取り込んだ Twitter アイコンをマイデザインとして保存できます:
EY2NePPUEAEV4Sn


そして取り込んだマイデザインはゲーム内で利用できるようになります:
EY2NePLUwAAIkrq


おまけで紹介した Twitter アイコンのマイデザイン化はマンホールマップに投稿したことがなくても(Twitter のアカウントさえ持っていれば)できるので、興味ある方は使ってみてください。ついでに近所のマンホール画像をアップロードしていただけると嬉しいですw


さすがにメトロポリタン美術館の40万点には敵いませんが、約1万点のマンホール画像(と自分の Twitter アイコン)をマイデザインとして利用できるような機能を提供できました。ぜひマンホールマップを(できればログインして)使ってみてください。



【関連エントリ】
お絵描き共有サービスの「あつまれ どうぶつの森」マイデザイン対応


 

ほぼ備忘録目的のブログエントリです。

HTML で <canvas> を使うと画面に単純な画像だけでなく、グラフィックコンテキストを使って自由度の高い図形や関数曲線を描くことができるようになります。個人的にもよく使っています。

特筆すべきはピクセル単位での画素情報を取得することもできる点です。ここでの画素情報とは RGB 値や輝度の値といった情報です。例えば <canvas id="mycanvas"></canvas> 内に描かれている内容のピクセル単位での画素情報を動的に取得するには以下のような JavaScript コードを実装すれば可能です:
  var canvas = document.getElementById( 'mycanvas' );
  if( !canvas || !canvas.getContext ){
    return false;
  }
  var ctx = canvas.getContext( '2d' );

  var imagedata = ctx.getImageData( 0, 0, ctx.canvas.width, ctx.canvas.height );
  for( var i = 0; i < imagedata.height; i ++ ){
    for( var j = 0; j < imagedata.width; j ++ ){
      var idx = ( j + i * imagedata.width ) * 4;

      var r = imagedata.data[idx];    //. R(0-255)
      var g = imagedata.data[idx+1];  //. G(0-255)
      var b = imagedata.data[idx+2];  //. B(0-255)
      var a = imagedata.data[idx+3];  //. 輝度(0-255)

        :
    }
  }

この中で画素情報を取得する際に使っているのが getImageData() 関数です。これは canvas 内の開始点座標と幅、高さを指定し、その指定範囲内の画素情報を配列で取り出すことができます。また上述例のように1つのピクセルの情報は配列内の4つの値(R, G, B, 輝度)として格納されており、1つずつ取り出して参照することも可能です。画像を独自に減色したりする際等に必要な情報を取り出すことができて、個人的にも便利に使っています。


このように便利な canvas と getImageData() 関数ですが、この getImageData() 実行時に以下のようなエラーが発生して、画素情報を取得できないケースがありました:
'The canvas has been tainted by cross-origin data.'

ん? "Cross-Origin" ?? どういうこと???


これが発生した時の <canvas> 内は、事前に以下のような処理を行って画像が表示されていました:
  var img = new Image();
  img.src = 'https://www.xxx.com/images/abc.png';
  img.addEventListener( 'load', function(){
    var canvas = document.getElementById( 'mycanvas' );
    if( !canvas || !canvas.getContext ){
      return false;
    }
    var ctx = canvas.getContext( '2d' );
    ctx.drawImage( img, 0, 0, canvas.width, canvas.height );
  }, false );

要するに <canvas> 内には https://www.xxx.com/images/abc.png という(架空の) URL で表現される画像ファイルが表示されている状態でした。単に画像を表示するだけなら <img src="https://www.xxx.com/images/abc.png"/> みたいに記述すればいいのですが、後で前述のような画素情報を取り出す処理を実行したかったので、<img> ではなく <canvas> を使って表示していたのでした、という事情がありました。が、このケースだと getImageData() 実行時に上述のようなクロスオリジン関連のエラーが発生して情報を取得することができなくなっていました。これはいったい・・?


エラーメッセージからなんとなく想像はできたのですが、この getImageData() 関数はクロスオリジンの画像が表示されている場合は CORS の制約がかかるようです。つまりこの例であれば www.xxx.com というサーバー上にある https://www.xxx.com/images/abc.png という画像を表示しています(上のコード例では drawImage() 関数によって実際に表示されます)。この drawImage() 関数はクロスオリジンに関係なく実行することができるので、(自サーバーではない)www.xxx.com というサーバー上にある画像に対して実行してもエラーが発生することなく実行され、画像は <canvas> 上に表示されます。

しかし getImageData() 関数についてはクロスオリジン制約があるようです。したがって自サーバー上ではない URL を指定して表示された画像に対して実行すると、今回のようなエラーが発生してしまう、という制約があるようでした。


このエラーを回避しようとすると、www.xxx.com 側で CORS の制約を緩和するような設定を行うか、それが難しい場合は目的の画像をクロスオリジンにならない形の URL で指定できるようにする必要があります(そのため静的な HTML や JavaScript だけだと実現が難しいです)。具体的にはサーバーサイドの処理で、例えば GET /getimage のような REST API を用意し、この API が目的の画像バイナリと Content-Type を返すようにする、といった対応が必要になります。


現にこういう方法で回避できちゃう CORS 制約は、処理が面倒くさくなるだけであまり意味ないと思っちゃうんだけどな。。


 

まだコードに手を加えることもあり、開発中ゆえの不安定さもあるのですが、一応一通りの機能が動く状態になったのでサービスを公開します(2020/05/19)。


自作のお絵描き共有サービス MyDoodlesNintendo Switch の人気アプリ「あつまれ どうぶつの森」のマイデザイン化するための機能を実装しました。とりあえずは手持ちの Windows 10 PC および iPhone SE で動作確認しています。


【はじめに】
最初にお断りをしておくと、このサービスの編集機能そのものはそれほど強力ではありません。線の色や太さを選んで描画する以外には、背景色設定と、アンドゥ、リドゥ、リセット程度の機能しかありません。一般的なレタッチアプリのような細かな編集はできませんが、よく言えば「簡単」「気軽」です。小学校低学年程度の子供でも利用できることを想定して開発しています(その割には漢字とかも使ってるけど・・ (^^;)。

また「そもそもなんでこんなツールを作ったのか?」を説明します。「あつまれ どうぶつの森」にはマイデザインを編集する機能が標準で付属していて(ゲーム内でマイルを貯めて機能豊富な Pro エディタを使うことも可)自分の好きなデザインを作ることはできますが、これがちと使いづらいというか何というか・・・だったりします:
EYXVHfAUwAAz0tb


このような状況に対して僕と同じような考えを持っている人が少なからずいるようで、後述のようなより便利にデザインを編集できるサービスがいくつか公開されていたりします。自分も先人達から提供いただいた情報を頼りに、その流れに乗っかる形でサービスを開発してみました。ただ自分の場合はデザインは専門ではなく、自分向けという意味もあるのですが「より自由度高くデザインする」というよりは「より簡単に使える」ことを目指して作ってみました。

なお今回作成したツールでは「指でお絵描き」する作業がありますが、この部分の実現には自分が開発した doodlejs を改良して使っています。この doodlejs の応用で LINE で手書きスタンプを送ったり、大勢でお絵描きをした内容を同時に参照したりしています。応用範囲の大きなライブラリだと思っていて、今回のサービスも doodlejs の応用で実現しています:
2020051901


・・・以上、宣伝コーナーでした(笑)。

では以下で MyDoodles の使い方を説明し、続けてマイデザイン化するための手順を紹介します。


【MyDoodles の使い方】
MyDoodles 自体は PC、スマホ、タブレットのウェブブラウザを使って URL にアクセスすることで利用できます(ただし後述のマイデザイン化する場合は PC のマウスで描画するよりも、スマホを使って指で描画する方が簡単だと思っています。以下のスクリーンショットもスマホでのものを中心に紹介します):
https://mydoodles.mybluemix.net/



アクセスすると以下のような画面が表示されます:
2020051900



それぞれ以下のような役割を持っています:
2020051901


タイトル絵のタイトル
履歴同一端末で過去に保存した絵を呼び出す
線の色描画する線の色
線の太さ描画する線の太さ
背景色タップすると「線の色」で指定された色をキャンバスの背景色にする
キャンバスここにお絵描きを描画します
アンドゥ1ストローク戻る
リセットキャンバスを初期状態に戻す
保存キャンバスのお絵描きを保存する
リドゥ(アンドゥ後に)1ストローク進める



タイトル欄には絵のタイトルを入力します。後述のマイデザインにする場合、ここで指定した内容が絵のタイトルにもなります:
2020051902


キャンバス画面を使って指で絵を描いていきます(PC を使っている場合はマウスやペンタブレットが使えます。タッチスクリーン対応の PC であれば画面に直接指でスクリーンに描くこともできます)。なお後述のマイデザイン化を想定する場合はあまり細い線で描いても最終的に潰れてしまう可能性が高い(マイデザインは 32x32 サイズ)ので、太さ 10 以上の線で描くことをおすすめします。また PC ブラウザを使う場合は線の太さに加えて、なるべくキャンバス部分が正方形になるようウィンドウサイズを調整してから描くことを推奨します(マイデザインが正方形のため):
2020051903



最後に「保存」ボタンをクリックするとお絵描き内容が保存されます:
2020051907



保存されたお絵描き内容が表示されます:
2020051905


この画面から Twitter や facebook などの SNS にシェアすることができるようになり、シェアされた他の人も同じ画像を見ることができるようになります。なお同一端末(お絵描きを描いて保存した時に使っていた端末)からこの内容を表示している場合のみ、画面右上に「再編集」ボタンが表示され、このお絵描き内容を元に編集を続けることもできます。また「自分も試す!」ボタンはこのページをシェアされて見た人が自分でもお絵描きを試せるよう新規作成画面へ案内するボタンです:
2020051906


加えて、これはあまり使われない機能であると想定していますが、過去作品履歴情報の他機種への引っ越し機能も一応用意しています。手順はこのブログの一番下※に記載しておきます。


基本的なお絵描き共有サービスの機能は概ねこんな感じです。これはこれで簡単にお絵描きして、簡単に SNS でシェアできる、というものだと思っています。


【どうぶつの森 マイデザイン化】
MyDoodles サービスを使って作ったお絵描きの内容を「あつまれ どうぶつの森」のマイデザインとして取り込む手順を紹介します。なお、こちらの手順はお絵描きの作者本人だけでなく、シェアされたお絵描きページを見ている全ての人が実行可能です。またこの手順はスマホで行う必要はなく、(シェアされたお絵描きページの URL がわかっていれば)PC などから行うこともできますし、その方が楽だと思っています。

まず、この機能を使ってマイデザインを取り込むには Nintendo Switch Online アプリをスマホにインストールし、デザインを読み取る人のアカウントで初期設定しておく必要があります。あらかじめご用意ください:
2020051903



改めてお絵描き内容をマイデザイン化するまでの手順を紹介します。MyDoodles サービスのお絵描きページを表示して、そしてその中の「QR コード」ボタンをタップします:
2020051901


すると画面内にお絵描き内容の情報を含む QR コードが表示されます:
2020051902


この QR コードを Nintendo Switch Online アプリの「あつまれ どうぶつの森」サービス内「タヌポータル」の「マイデザイン」から読み込みます:
2020051904


この手順を実行するには上述の QR コードをスマホの Nintendo Switch Online アプリを起動して読み取ることになります。したがってNintendo Switch Online アプリをインストールしたスマホとは別のスマホや方法で上記 QR コードを表示する必要があります。別のスマホや PC を使って MyDoodles から表示するか、 QR コードの内容をスクリーンショットで撮影して別途写真共有サービスなどを使うなどして、Nintendo Switch Online アプリのタヌポータル「マイデザイン」から生成された QR コードを読み込んでください:
2020051905


正しく QR コードが読み取れると以下のような確認画面になります(32x32 に縮小された結果、どの程度潰れてしまうかを確認できると思います)。読み込む場合は「保存」します:
2020051906


これで MyDoodles で描いたお絵描き内容が「あつまれ どうぶつの森」から取り込めるようになりました:
2020051907


ここから先は「あつまれ どうぶつの森」を実際に起動して行う操作となります。


「あつまれ どうぶつの森」を起動後に、(ゲーム内の)スマホを取り出し、「マイデザイン」を選択します:
2020051908


マイデザインの一覧が表示されている画面で「ダウンロード(+ボタン)」を選択し、インターネットに接続して「ダウンロード」を選択します:
2020051900


上述の作業で QR コードから取り込んだデザインがダウンロードされます。ダウンロードする先のデザイン(白紙のデザインか、上書きしてよいデザイン)を選んで保存します:
2020051901


MyDoodles で作ったお絵描きがマイデザインとして保存されました:
2020051902



現在の仕様では保存したマイデザインは「あつまれ どうぶつの森」の中では再編集することはできませんが、トップスとして身につけたり、地面に敷いたりする、等といったことができるようになります:
2020051903


2020051909



と、以上が MyDoodles サービスの簡単な使い方、およびマイデザイン対応の手順となります。繰り返しますが凝ったデザインを描くためのツールというよりは、気軽にお絵描きしたものがゲーム内で使えることを主目的としている点をご了承ください。


なお、このツール(のマイデザイン対応)の開発をするにあたり、以下のサイトの情報を大変参考にさせていただきました。ありがとうございます。 特に「ドット絵ナニカ」は画像を指定してマイデザインを作る、というもので、凝ったデザインを作りたい人にとっては(デザインツールで凝った画像を作って変換すればよいので)こちらを使われた方が目的にあっていると思っています:
ドット絵ナニカ
「あつまれ どうぶつの森」のマイデザインのQRコードを写真・画像ファイルから生成する方法





過去作品履歴の引っ越し手順

この MyDoodles では作った作品をシェアして他の人に見せたりすることはできますが、原則として「同一機種で作った作品のみ」履歴一覧から参照して検索したり、再編集することができます。

ただ機種変更などの都合により、ずっと同じ機種を使うことができないことも想定されます。そんな場合にこの引っ越し手順により、他機種へ過去作品履歴を引き継ぐことができるようになります。ただし特に画面サイズの異なる他機種へ引っ越しした場合は、再編集時にうまく表示できなくなります。事実上、参照のみのための引っ越しと考えてください。

引っ越しするには引っ越し元と引っ越し先両方の 機種 ID が必要になります。機種 ID は履歴参照時に表示される赤枠の部分です:
2020051902


引っ越しは①引き継ぎ先指定、②取り込み元指定 の2段階からなります。まず引っ越し元となる機種で①を実行して引き継ぎ先機種の機種 ID を指定し、続けて引っ越し先となる機種で②を実行して引き継ぎ元機種の機種 ID を指定して取り込みます:
2020051903


②までが完了すると、引っ越し元機種からは履歴一覧を見ても過去作品は見えなくなります。



HTML の <textarea> に行番号を付与する jQuery プラグイン jQuery LinedTextArea を使ってみました。

<textarea> フィールドを(コーディング目的などの)テキストエディタとして使いたい場合など、行番号を付与して使いたいケースがあります。CSS と JavaScript でがんばって作る方法もありますが、jQuery のプラグインを使うことで比較的簡単に実現できそうだったので紹介します。

目的のプラグインは jQuery LinedTextArea です。ざっと探した限りで CDN が存在していなさそうだったので、リンク先から git clone するかダウンロードしておきます(最低限必要になるのは jquery-linedtextarea.cssjquery-linedtextarea.js の2つです)。


準備段階として、これらを jQuery 本体の後にロードしておきます:
<script type="text/javascript" src="//code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="./jquery-linedtextarea.js"></script>
<link href="./jquery-linedtextarea.css" rel="stylesheet"/>

  :

そして目的の <textarea> を指定して、以下のようなコードを実行します:
<textarea class="lined">
あいうえお
かきくけこ
さしすせそ
</textarea>

<script>
$(function(){
  $('.lined').linedtextarea({
    selectedLine: 1
  });
});
</script>

目的の <textarea> に "lined" というクラスを指定した上で、jQuery で $('.lined') に対して linedtextarea() を実行します。上記例では { selectedLine: 1 } というパラメータを付けて実行しています。これにより1行目が選択された状態で表示されます:
2020051200


こんな感じ。

このページのトップヘ