ふんばりフロントエンジニアのブログ

新米フロントエンジニアの備忘録です。ふんばり温泉タオル欲しい...

人気ライブラリ「TweenMax」と「ScrollMagic」で簡単にスクロールアニメーションを実装!

さて、今回はアニメーションライブラリを使ってみよう!というお話です。

そして今回ご紹介するのは「TweenMax」と「ScrollMagic」、TweenMaxは日本でそこまで知名度があるわけではないですがアメリカではかなり人気のライブラリのようですね。

ただアニメーションの実装をするだけなら「TweenMax」だけで済みますが、やはり最近流行っているのは「スクロールして要素とぶつかったらアニメーション」というパターンでしょう。

ということで、よしなにスクロール時のイベントを設定できるScrollMagicについてもお話していこうと思います。

人気ライブラリ「TweenMax」と「ScrollMagic」の基本を解説!

TweenMaxの基本

最近取り組んでいる案件がアニメーションを実装してほしいとのことだったのですが、実際簡単なものならcssのanimationで出来てしまいます。

でもスクロールして要素とぶつかったらアニメーションを追加したりクラスを追加したり…って割とめんどくさいなあと思いましてね。(何よりコーディング期間が短いんですよね汗)

ということで使ってみようと思ったのがまずTweenMaxです。

TweenMaxはcssプロパティやアニメーションの設定をすることで、簡単にアニメーションを作ることができるライブラリ。

とりあえずサンプルを見てみましょう!


See the Pen
TweenSample1
by nakajima masahiro (@nakajima333ta)
on CodePen.

これは要素を消したり出したり、という簡単なサンプルです。

TweenMaxを使えるようにするには、↓からダウンロードするかCDNで読み込むか、またnpmでinstallするか、という方法がありますがオススメはnpmですね。

さて、コードを見ていくと非常にシンプルになっています。

使い方を解説すると、

TweenMax.アニメーション方向("ターゲット",アニメーションにかける時間,{cssプロパティ});

という感じですね。

もともとjQueryプラグインなのでターゲットの書き方もjQueryのように書けるのがお手軽感マックスです。

まず、TweenMaxには大まかにわけて二つのアニメーション方向がある、と言っていいでしょう。

それが「to」と「from」の二つ。

toは指定したcssプロパティ「へ」向かっていくようなアニメーションになりますが、fromはtoの逆で指定したcssプロパティ「から」元の形や位置に戻っていきます。

そのため、上記の例で指定しているcssプロパティは同じですがアニメーションの動きは逆になるんですね。

これさえ分かれば、ちょっとしたアニメーションならささっとできるようになるでしょう。

TweenMaxについてもっと詳しくお話していきたいのですが、種類がありすぎて解説しきれないのでこの辺でTweenMaxについてはやめておこうかと...

追記:TweenMaxのcycleプロパティについて解説してみました!
hubarifront.hatenablog.com

公式はドキュメントやデモが充実しているのでご興味のある方はご覧になって見てください。
greensock.com
greensock.com

「ScrollMagic」の基本

ScrollMagicはスクロール中に指定した要素を監視してくれるライブラリです。

ライブラリを使わなくても書けるっちゃ書けるのですが、やはり楽...いや便利なんですよね。

ということでこちらもサンプルから見ていきたいと思います。


See the Pen
scrollMagicPinSample
by nakajima masahiro (@nakajima333ta)
on CodePen.


こちらは#targetが出てくるときに、#targetをピン止めするという処理です。

まず、ScrollMagicを使う上で押さえたいポイントはコントローラーとシーンですね。

コントローラーはシーンを管理する大元、シーンはどこをターゲットにするか、などというような細かい設定を書くものと押さえておきましょう。

コントローラーは一回インスタンスを作れば、どんどんシーンを追加していけるので基本的にはコントローラの宣言は一回だけで良さそう。

そして肝心のシーンですが、基本構文はこんな感じです。

var 変数名 = new ScrollMagic.Scene({ 
triggerElement: "監視対象",
duration: 数値,
 })
.処理
.addTo(コントローラー名);

triggerElementに指定するのは、監視対象です。
つまりこのtriggerElementに指定した要素までスクロールすると、下に書いた処理が実行されます。
処理は「.」で繋げて書くことができ、最終的に「.addTo(コントローラー名);」することがお決まり。
最後にコントローラに追加しないといけないので注意しておきましょう。
こちらも公式のドキュメントが豊富なので詳しいことは↓から...
scrollmagic.io

追記:ScrollMagicのonメソッドについて解説してみました!
hubarifront.hatenablog.com

TweenMaxとScrollMagicを組み合わせよう!

さて、それぞれを簡単に解説していきましたがこれらをどのように組み合わせれば良いのでしょうか?
まあScrollMagicの処理の所にTweenMaxの処理を書けば良さそうですよね笑
ということで、完成したのがこちらの処理です。


See the Pen
TweenMax&ScrollMagic_sample
by nakajima masahiro (@nakajima333ta)
on CodePen.

追記:関数化してみたやつ↓
hubarifront.hatenablog.com


ScrollMagicで監視対象を指定して、要素とぶつかったらsetTweenというメソッドを使って、変数に格納しておいたTweenアニメーションを作動させています。
ちなみにsetTweenは「animation.gsap.js」というファイルを読み込まないと使えないので注意してくださいね。
また、このように「addIndicators」を記述すると簡単にどこからアニメーションが始まるのかをデバッグすることができるので使った方がより作業が捗ると思います。
https://codepen.io/nakajima333ta/pen/mzVwWOcodepen.io
どのようなタイミングでアニメーションが動いているのかをこれまたお手軽に確認することができるので、開発時には以下を書いておくといいでしょう。

.addIndicators( {name:"インジケータの名前"} )

シーンごとに名前をつけて管理できるのもいいですよね。
こちらも利用するには別で「debug.addIndicators.js」を読み込む必要があるので注意してください。
では最後にnpmでこれらを利用する際の手順を書いて終わりにします!

npmでTweenMaxとScrollMagicを使おう!

①npmでgsapとscrollmagicをインストール

npm install gsap scrollmagic

②jsファイルでimport ※import-loaderを使わないと上手く行かないので注意!

import {TweenMax,TimelineMax} from "gsap";
import ScrollMagic from "scrollmagic";
import 'imports-loader?define=>false!scrollmagic/scrollmagic/uncompressed/plugins/animation.gsap';
import 'imports-loader?define=>false!scrollmagic/scrollmagic/uncompressed/plugins/debug.addIndicators';

③スタート!
結構簡単に使えますね!
ただimportでエラーが起きたりと最初につまづいてしまったので、時間が結構かかりました...
スクロールアニメーションを使ってみたい!という方の参考になると嬉しいです^^

タブレット・スマホのデザインに768pxが多い理由とは

久しぶりの投稿ですね…

わりと沖縄へ行ったり熱海へ行ったりと最近は忙しめでした(笑)

さて、今回はデザインファイルを触るときによく見かける「768px」という数値についてお話しようと思います。

正直「半端やな…770pxでもええやんけ…」とずっと思っていたのですが最近お話を聞いて納得したので備忘録的に残しておこうと思います。

なぜ768pxがデザインの幅として多いのか?

この理由は意外と単純明快なものでした。

結論から言うと「768px」がタブレット最小幅だからです。

「え、それより幅が狭いタブレットあるくない?」と思いますが、実は基準としているのは「iOS製品」なんです。

f:id:ma1129nm:20180927173001j:plain

こちらはSafariで「レスポンシブデザインモード」にしたときの画面ですが、たしかに一番タブレットで小さいのは「iPad mini」でその画面幅は「768px」となっています。

そして、逆に一番大きいサイズは「iPad Pro」で「1024px」ですね。

「なるほど」とここで合点がいったのですが、わりとCSSでブレイクポイントを指定する際に「1024px」までをタブレットデザインとする表記が多いのはこういうことかと…

つまり1024px以上のタブレットが現在提供されていないので、それ以上は「PCデザインでいいっしょ!」ということですね。

少し話がそれましたが、タブレットスマホデザインとして768pxが多いのはこのような単純な理由からのようです。

でもたまに「828px」のタブレットスマホデザインも見かけますよね。

これはどういうことなのでしょうか?

デザイン幅が828pxはの理由は?

デザイン幅が828pxである場合も、やはりiOS製品に関係があるよう。

そしてこちらの数値はタブレットデザインというより、スマホデザインに比較的見られる数値かもしれませんね。

先ほどのレスポンシブデザインモードをまた見てみてください。

スマホで一番大きい画面幅の機種はどれですか?

そう、「iPhone 8 Plus」ですよね。

そしてこの幅は「414px」となっています。

ここで忘れてはいけないのが「Retina ディスプレイ」でしょう。

 

Retinaディスプレイって?~

Retinaディスプレイは「高精細」なディスプレイです。

このRetinaディスプレイがなぜ高精細なのかと言うと、「ppipixel per inch)」というディスプレイの解像度を示す単位が大きいためです。

このppi1インチにどれだけピクセルが入るか、という単位。

つまりこの数値が大きいほど1インチ当たりのピクセル数が多くなるので高精細になる、というわけですね。

Retinaディスプレイが搭載されたのはiPhone4からですが、このiPhone4が発売されるより前のApple製品のppiは「100~200ppi」ほどでした。

しかし、Retinaディスプレイを搭載したiPhone4のppiは「326ppi」。

そして先ほどのiPhone8Plusでは「401ppi」となっています。

つまり従来の解像度の二倍の解像度になっているんですね。

これがRetinaディスプレイが高精細なディスプレイたる理由です。

 

さて、Retinaディスプレイに関する話をしてみましたが従来の製品より解像度が二倍になっていることが分かりました。

つまり?

そうなんです、デザインを作る際には「Retinaディスプレイに対応するために二倍のデザイン幅でデザインを作らないとRetinaディスプレイに対応する解像度にならない」んです。

そして、現在提供されているiPhoneで一番大きい画面幅なのが「iPhone8 Plus」の「414px」、そしてその二倍の数値が「828px」なのでスマホデザインにおいては「828px」のデザインが多くなっているのでしょう。

スマホタブレットデザインのデザイン幅に関してはこれくらいですかね…

PCのデザイン幅は基準とするものが結構難しいようですが、一般的には「1280px」が多いようです。

しかし、画面幅いっぱいのコンテンツがデザインにあった場合、どのあたりで画面幅いっぱいのコンテンツをやめるか、対処するかを決めておかないととんでもないことになってしまうので気を付ける必要がありますね。

最近デザインを作ったりもしているので、今回聞いたお話はかなり貴重でした…

もしかしたら知っている方が多い話だったかもしれませんが、私にとってはインパクトが強かったので書いてみました。

今度はデザインの話ができればいいな…頑張ります~~

【Atom】atom-beautifyでPHPが整形できない…設定を変更しよう!

今回は私が愛用しているエディター「Atom」についての備忘録です。

今回の問題はAtomのコード整形パッケージ「atom-beautify」でPHPの整形がうまく行かない、ということについて。

エラーが出るわけではないのですが、注意書きで次のようなポップアップが出てきます。
f:id:ma1129nm:20180907153911p:plain
何やら内容としては、「PHP_CS_Fixerのパス設定が非推奨になってるので、変えてください」ということのよう。
PHP_CS_FixerはPHPのコードを整形するためのツールで、こちらはatom-beautifyを利用する際に確かダウンロードしてきたような気が…
まあ何はともあれ、このツールを使ってatom-beatuifyは整形をかけるのでもちろん正しくパスが通っていないと整形してくれないわけです。
ということでatom-beautifyのsettingsを見てみると、確かにPHPのところの「PHP-CS-Fixer Path」にパスが記載されています。
ただ、この「PHP-CS-Fixer Path」でパスを指定する方法がもうダメみたいですね。
そのため、まずはここにパスを記載している方は消しちゃってください。
そして新しく推奨されているのがatom-beautifyのsettings配下にある「Executables」内の「PHP」と「PHP_Fixer」にパスを通す、というもの。
PHPには「PHPのバイナリファイルがあるところまでの絶対パス」、「PHP_Fixer」は「ダウンロードしたphp-cs-fixer.pharがあるところまでの絶対パス」を書いてあげます。
f:id:ma1129nm:20180907155049p:plain
これでもう一度atom-beautifyを「opt+Ctrl+B」で実行するとできるようになるはずです。
ちなみに、phpファイルの中に記載されているHTMLは整形してくれないみたいですね...残念...

Dockerコンテナ内でComposerコマンドを使えるようにするメモ

Dockerのコンテナ内でComposerを使おうとした時のメモです。

まず、何も考えずに「curl -sS https://getcomposer.org/installer | php」でComposerをインストールするとカレントディレクトリにcomposer.pharが置かれます。

もちろんこのままではcomposerコマンドが利用できません。

Composerコマンドを使えるようにするには「/usr/local/bin」配下にcomposer.pharを配置しなければならないのですが、ただ置いただけではComoserコマンドを利用することはできません。

そこで行うのが「/usr/local/bin」配下に置いた「composer.phar」のリネームです。

「mv composer.phar composer」として「composer」にリネームすることで、Composerコマンドが利用できるようになりました!

他にも「/usr/local/bin」配下にcomposerディレクトリを作る、という方法もあるらしいですが私はそれで対処できませんでした...

とりあえず、一番手っ取り早いのは

  1. 「/usr/local/bin」に移動
  2. curl -sS https://getcomposer.org/installer | php」を打つ
  3. 「mv composer.phar composer」でリネーム

という感じでしょうか。

上手くいかなかったら教えてください〜

JavaScriptでアプリを作る!React Nativeの環境を作ってみよう

「ちょっとReactでアプリ作れるっぽいんだけど触ってみてくんない?」というお言葉から、本日はReact Nativeをかるーく触ってみました!
以前Reactを触ってみたお話しをしましたが、React Nativeはアプリケーションを作るためのものという認識なので触れてなかったんですね...
hubarifront.hatenablog.com
ただ、やはり触ってみた所感としては「ReactはReactだ!」、そして「SwiftやJavaなどを使って本格的にアプリを作るのはちょっと億劫だなあ」というフロントエンジニアの方にはもってこいのフレームワークだなあと改めて実感したところであります。
ということで、今回はReact Nativeをかるーく触ったお話をしていきたいと思います!

React Nativeの環境を作る!

React Nativeの環境はどうやらReactとは少し違うよう。
なんせアプリ開発ですからね...
公式ドキュメントを見る限り大雑把に分けると二つの方法にわかれます。

1. 「npm install -g create-react-native-app」で一発
2. nodeとwatchmanをbrew install、react-native-cliをnpm installしてprojectをinitする方法

まあReactの環境構築と似たような感じですね。
前回Reactでプロジェクトを作成したときは2の方法をとって、一から作っていたので今回は1の提供されているデフォルトのプロジェクトをインストールする方法をとりました。
本来ならつまづくところではないのですが、わたくしここでつまづきました....
というのも最近Macの様子がおかしく、時々Homebrewの挙動がやばいんですよね(笑)
まず、「npm install -g create-react-native-app」は問題なく入りました。
次に、「create-react-native-app プロジェクト名」でプロジェクトを作るのですが、ここも問題なかったです。
この二点を実行することでReact Nativeを動かす要素は揃ったはずだったのですが、「npm start」をすると「watchmanを入れるように」というエラーが。
ここで「brew install watchman」を打ったのですが、20分待っても終わらない...
結局何回やってもダメだったので、「OSを更新したからHomebrewの調子が悪いんかな?」ということでHomebrewのアンインストールをすることに。
そして再インストールをすることになったのですが、今度はHomebrewのインストールで止まる...

もう弾けそうでしたね、逆に。

何度か「usr/local」配下に作られているhomebrewやCellarなどを除去してはインストール、ということを繰り返していましたが結局解決はできず。
そこで試したのが「セーフブート」です。
セーフブートはmacの起動時のオプションでキャッシュクリアなどをして最低限の状態で起動してくれるモード。
セーフブートで起動してからさらに再起動するとキャッシュクリアして綺麗な状態で起動することができるんですね。
早速これを行いまたインストールしたところ、Homebrewもwatchmanも問題なくインストールされました...
おそらくキャッシュに残っているところをインストール時に見に行ってたんですかね??
細かいことはわかりませんが、とりあえずセーフブートからの再起動で正常にHomebrewが正常に戻り、Watchmanもインストールができました。
あとはもうこっちのもんです。
先ほどの「create-react-native-app プロジェクト名」で作ったプロジェクトにcdして「npm start」を打つだけ!
そうすると、「starting packager...」という文言が出て、最終的にはそこにQRコードが表示されます。
このQRコードを読むことで、シミュレーターを表示できるのですがここで必要になってくるのが「expo」というアプリ。
これはiOSでもAndroidでもダウンロードできるアプリなので、個人的にはexpoを使って実機で確認するのが一番いいのかなーとか思ったりしますね。
もちろん「npm run ios」をするとXcodeのシミュレーターが立ち上がったりしますが、結局はexpoに行くので...
ということで、開発環境はexpoを使った方法がおすすめです!

ふう...
本当はコードについてもお話しようと思ったのですが、ちょっと酔いが回ってしまったのでまた今度の機会にさせてもらおうと思います...
今回の内容でとりあえずReactNativeを動かすことはできるのでぜひお試しあれ!

Seleniumでブラウザテストを自動化!Javaでブラウザを動かそう!

今回はブラウザテストについてお話ししようと思います。

以前記事で書いた「診断コンテンツ」がありましたが、結局これはReactを使ってもっとボリュームのあるものを現在開発しています。

hubarifront.hatenablog.com

ただ、診断コンテンツのように選択肢によって結果が変わるものには「テスト」が必要。

しかし、今回開発しているのは「2つの選択肢がある設問が9個」で選んだ選択肢によって結果が分かれる、というもの。

つまり単純に考えると「2の9乗=512通り」のパターンがあることになります。

「こりゃあえらいこっちゃ…」

512通りを全て確認するのはかなり大変ですよね。

現在完璧に全部をテストできる状態にはなっていないのですが、Seleniumを使ってブラウザテストを初めてやってみたので備忘録として残しておきたいと思います。

Seleniumとはなんぞ???

Seleniumとは、UIテストツール、というかブラウザで表示されている要素を直接触れることなくスクリプトで操作できるツールです。

RubyPythonなど様々な言語で利用できるものですが今回は昔少しだけ触ったことのあるJavaを使ってみました。

では早速ですが、Seleniumで操作することのできる簡単な例をご紹介したいと思います。

        String url = "";
        String type = "";
        try {
            url = "https://www.yahoo.co.jp/";
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        WebDriver driver = new ChromeDriver();
        driver.get(url);

こちらを動かすと、自動的にGoogleChromeで「yahoo」のHPが表示されます。 こちらのコードは簡単ですが、基本となるものなのでしっかり抑えておきましょう。 まず重要になるのは「WebDriver」です。 WebDriverはなんとなくのイメージとしてブラウザに繋げるためのオブジェクトと捉えていただければ大丈夫かと思います。 そしてこのWebDriverという型でブラウザのdrverをnewしてインスタンスを作るわけなのですが、このインスタンス化によってどのブラウザを使うか、ということを選ぶことができます。 今回使用したのは「GoogleChrome」なので「ChromeDriver」をnewしてdriverインスタンスを作っています。 このインスタンス化をすることによってWebDriverがもつメソッドを利用することができるんですね。 上の例で使っているメソッドは「get(URL)」というメソッドで、これは引数のURLを開くメソッドです。 そのため、上の例ではyahooのURLが入っているのでこれを実行するとyahooのHPが表示される、というわけです。 このようなメソッドは他にもあり、WebDriverインスタンスを作ることで表示されている要素を検索して取ってきたり、要素をクリックできるようになったりします 。 さて、今回やりたいことは「512通り」ある選択肢を漏れなくテストしたい、というもの。 テスト内容としては、結果ページで出た「タイプ名」と、条件とした選択肢通りにクリックしてそのタイプになるかを確認したい。 となると、まずは2の9乗のパターンを全部吐き出すような処理を書かなければいけません。 ここで、今回行うテストの想定は - 1か0で判断してどちらの選択肢をクリックするかを決める - 2の9乗なので、「512」になるまで2進数で9桁の文字列を配列で作る というようなことを考えました。 開発している診断コンテンツは「右」か「左」のどっちを押すか、というようなものですので0か1で判断することはもちろん可能です。 では512通りの選択肢を試すためには何が必要か、と考えた時に2進数で512になるまで一つ一つの数字を2進数で表す、という考えに至りました。 先に512 までの2進数を表示するためのメソッドを載せておきます。

 public  String arrayCreate(int index) {
        List<String> decimal_array = new ArrayList<>();
//            二進数の配列を作成
        for (int i = 0; i < 30; i++) {
            String decimal = Integer.toString(i, 2);
            String decimal_fill = String.format("%09d", Integer.parseInt(decimal));
            decimal_array.add(decimal_fill);
        }
        return decimal_array.get(index);
    }

こちらはStringで引数に指定されたインデックス番号の文字列(2進数)を返すメソッドとなっています。 やっていることは非常にシンプルで、for文の「i」を1から30まで一つづつ「toString」で2進数化し、その進数を9桁の数字になるようにString.formatで整形して返す、というもの。 そしてテストするメソッドはこちらです。

public static String ClickHandler2(String args) {
        String url = "";
        String type = "";
//           IP取得
        try {
            InetAddress address = InetAddress.getLocalHost();
            url = "http://" + address.getHostAddress() + ":8888";
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        WebDriver driver = new ChromeDriver();
        WebDriverWait wait = new WebDriverWait(driver, 20);
        driver.get(url);
        WebElement start = driver.findElement(By.className("start-btn"));
        start.findElement(By.tagName("a")).click();
        if (driver.findElements(By.tagName("button")).size() != 0) {
            System.out.println(args);
            for (int z = 0; z < 10; z++) {
                if (driver.findElements(By.tagName("button")).size() != 0) {
                    List<WebElement> el = driver.findElements(By.tagName("button"));
                    WebElement el0 = el.get(0);
                    WebElement el1 = el.get(1);

                    switch (args.charAt(z)) {
                        case '0':
                            el0.click();
                            break;
                        case '1':
                            el1.click();
                            break;
                    }
                } else {
                    System.out.println("結果ページです");
                    WebElement h1 = driver.findElement(By.tagName("h1"));
                    String src = h1.findElement(By.tagName("img")).getAttribute("src");
                    type = src.substring(src.length() - 5, src.length() - 4);
                    System.out.println(type);
                }
            }
        }
        return type.toUpperCase();
    }

このメソッドは先ほどのarrayCreateで返された二進数の文字列を引数にして、その文字列が「0か1か」で9問目まで判別し、その判別結果によってボタンをクリックさせる、という内容になっています。 最終的に返されるのはtypeというString型の変数で、こちらが結果ページの「タイプ」です。 そしてテストケースはこちら。

    @Test public void test0() { Assert.assertEquals("R", ClickTest2.ClickHandler2(arrayCreate(0))); }

予想されるタイプを第一引数、そして先ほどのメソッドで返されるタイプを第二引数にしています。 現在テストケースはこれしか作成していませんが、なんとなく512まで作れそうな気だけはするような… それぞれのメソッドに関してはまた後日お話しします。 今回は初めてSeleniumを使ってみたら意外といろんなことができるんだなあ...というお話しでした!

イラレの個人的注意点をまとめてみた

 

さて、しばらくコードの話をしていたので今回はイラレについてお話しようと思います!

私は業務でデザイナーさんから送っていただくデザインを元にコーディングすることが多いのですが、その場合フォトショかイラレかのどちらかをいただきます。

その中でもイラレの方がなんとなーく迷うことがありそうなので備忘録がてら書いていこうとおもいます。

 

ダイレクト選択ツールで選択しようとしたら背景が持ってかれる...

直感的に使うとなると陥りやすいやつですね。

こちらはかなりシンプルで背景レイヤーにロックをかけるだけで解決できます。

また背景レイヤーだけでなく、選択したくないレイヤーや動かしたくないレイヤーにはあらかじめロックをかけておくといいかもですね。

クリッピングパスがかけられているレイヤーを余白なしで書き出したい!

普通にクリッピングパスがかけられているレイヤーを選択して書き出そうとすると、そのクリッピングがかけられている元のレイヤーのコンテンツは含まれませんが、元のレイヤー分の幅・高さで書き出されてしまうので余白が生まれてしまいます。

その際には、アートボードツールを使うと綺麗に書き出すことができます。

まずダイレクト選択ツールでクリッピングマスクがかけられているレイヤーを選択します。

そしてアートボードツール(mac:shift+O)に切り替え、そのレイヤーをもう一度クリックするとその選択したレイヤーでアートボードが作られます。

アートボードができたらあとは「書き出し」から「スクリーン用に書き出し」で書き出したいアートボードを選択して書き出せばOKです。

 

簡単な内容でしたが備忘録として残しておきます...