2021年1月8日金曜日
2021年オフィス狛の年賀状の制作秘話。
1月 08, 2021
新年あけましておめでとうございます。オフィス狛 デザイン部のSatoです。
今年もどうぞよろしくお願いいたします。
2020年はレジャーや里帰りになかなか行けなかったり、慣れないリモートワークなどで大変な一年でしたね……。
一日でも早く安心して過ごせるようになることを願うばかりです。
デザイン部の年明け初めての記事ですので去年同様、今年の年賀状のおはなしをしようと思います。
↓去年の年賀状の記事です。
2021年の年賀状はこちら!
前年同様、弊社サイトやSNSなどのアイコンなどで登場している狛犬ちゃん(社内ではよく「こまちゃん」と呼ばれています)がホルスタインのコスプレをして牛乳にしがみついているポップなイラストです。
2020年に姿を描くことでご利益があるという言い伝えがあると話題になったアマビエを描いてみました。
こまちゃんの牛のコスプレも、災害が起こる前に突然現れ予言するという言い伝えがあり、絵図は厄除のお守りになると言われている体は牛で顔は人間の妖怪「件」に偶然にも似ているので、ご利益があるかもしれませんね。件と違って体が牛で顔が犬ですがご利益があると信じたいです。
……こまちゃん自体、コスプレしなくても厄除モチーフなのをうっかり忘れていました。
今年は実際に年賀状にした案がでるまでは無難なラフを描いていました。
左のラフの牛は結構好きなんですが無難すぎたかもしれません。
好きなイラストレーターの方が販売している今年用の年賀状に牛乳瓶を持ち上げる牛…という絵のパターンがあり「確かに牛乳も牛モチーフだ!」と気付き、その年賀状を参考にし右の牛きぐるみこまちゃんを牛乳に抱きつかせた絵を試しに描いた所、いい感じになったのでその絵を清書することに決めました。
完成したものには使いませんでしたが、最初上部分の波打つ牛乳のような部分は最初はこちらの液体が垂れるアピアランスのチュートリアルを参考にして牛乳上からダバーっと流れている風にしてみたのですが、私の使い方が悪かったのか少しホラーに見える…と他の社員に指摘され波打つような線に変更しました。
いつか液体が垂れるアピアランスを使いこなしてお洒落に見えるものが作りたいです…!
今年も前進できるよう頑張ります。
2020年12月30日水曜日
Angular・Componentのタグにclassを付与したい【HostBinding】
12月 30, 2020
こんにちは、オフィス狛 技術部のpinoです。
早速ですが、皆さんはAngularをやっていて「コンポーネントのタグに直接classを付与したいんだけどなぁ....。」と思った経験はないでしょうか。
今回は、そんな時に使える @HostBinding についてご紹介したいと思います!
準備
まずは、コンポーネントを用意します。app.component.html(親コンポーネント)
<header class="header"> <section class="header__about"> <h1 class="header__title">@HostBinding Sample</h1> <p class="header__lead">動作確認用のサンプルです</p> </section> <nav class="header-nav"> <ul class="header-nav__list"> <app-list-item *ngFor="let name of names" [name]="name"></app-list-item> </ul> </nav> </header>
list-item.component.html
<li class="header-nav__item"> <input type="checkbox" />{{ name }} </li>
list-item.component.css
.header-nav__item { width: 120px; height: 64px; padding-left: 32px; line-height: 64px; }
list-item.component.ts
import { Component, Input, OnInit } from '@angular/core'; @Component({ selector: 'app-list-item', templateUrl: './list-item.component.html', styleUrls: ['./list-item.component.scss'] }) export class ListItemComponent implements OnInit { @Input() name: string; constructor() { } ngOnInit(): void { } }
ビルド後のイメージ
色味がなく、シンプルで寂しい印象です。
ここから、実際にHostBindingを使ってclassを付与してみたいと思います。
HostBindingの使い方
使い方は1. コンポーネントのタグにclassを付与する
2. 上記1に加えて、動的にclassの付け外しをする
と、主に2つあります。
まずは、1. コンポーネントのタグにclassを付与するについてです。
こちらは、大きく2通りの書き方ができます。
list-item.component.css
import { Component, HostBinding, Input, OnInit } from '@angular/core'; // HostBinding を追加 @Component({ selector: 'app-list-item', templateUrl: './list-item.component.html', styleUrls: ['./list-item.component.scss'] }) export class ListItemComponent implements OnInit { @HostBinding('class') listItem = 'list-item'; // ① @HostBinding('class.first') first = true; // ② @Input() name: string; constructor() { } ngOnInit(): void { } }
ポイントは、@HostBinding()の、()の中です。
①は、「'class'」のみ指定して、なんのclassを付与するかは変数の値が使用されるパターンです。
値部分に定数を使えば、ロジック側にテンプレートの情報をベタ書きすることも避けられますね。
固定のclassであればこれで十分そうです。
②は、「'class.first'」と付与するclass名まで指定するパターンです。
この場合は、後に続いている値がtrueであれば付与、falseであれば付与しない、ということになります。
(※真偽値を固定で設定したい場合は、「@HostBinding('class.first') readonly first = true;」 といった具合に、readonlyをつけるなどの対策が考えられます。)
また、HostBindingの話とはすこし逸れますが、コンポーネントのタグに使用するclassは
グローバルである(style.cssに記述されている等)か、:hostメタデータを使用する必要があります。
今回は、自コンポーネントのCSSに背景色をつけるclassを用意したいと思います。
list-item.component.css
// 以下を追加 :host.list-item.first { background-color: #7ae5ec; } :host.list-item.second { background-color: #7aecc0; } :host.list-item.third { background-color: #7ab9ec; }
ここまでのビルド後イメージ
すべてのコンポーネントにclassが付与されて、背景色がつきました。
次は、2. 上記1に加えて、動的にclassの付け外しをするについてです。
list-item.component.css
export class ListItemComponent implements OnInit { @HostBinding('class') @Input() name: string; // ① // 今回formは用意していないので、例としてだけ挙げます @HostBinding('class.valid') get valid() { return this.form.valid; } // ② @HostBinding('class.list-item') isClick = false; // ③-A ... onClick(): void { this.isClick = !this.isClick; } // ③-B
他にもいろいろな方法があると思うのですが、簡単に思いつくものを挙げてみました。
①は、Input()で受け取った値を使用します。
組み合わせて使うだけで、特別なことをしてる感じがします...!
②について、今回Formは用意していないので記述の例になるのですが、状態など値そのものを監視したい時に使える方法です。
getterってあまり使う機会がなかったのですが、今回試してみたところ使い勝手がいいですね!
また③は、②のようにイベント発生時ではなく、識別子に設定した変数の値を書き換えることによってclassの付け外しをしています。
ここまでで、上記の①と③をプログラムに落とし込んだビルド後のイメージが以下のようになります。
それぞれで別々のclassの付与と、classの付け替えができました!
補足
ここまでclassを付与する使い方を紹介してきましたが、なんとHostBindingはclass以外のバインディングにも使えます。例えば、「@HostBinding('style.display') flex = 'flex';」としてあげればstyle="display: flex;"がバインドされます。
便利!
今回は公式以外に以下サイトも参考にしたのですが、「HostBinding('value') myValue;は[value]="myValue"と全く同じです。」という一文が特にわかりやすかったです。
@HostBindingと@HostListener:彼らは何をし、何のためにいますか?
以上、HostBindingデコレータについて紹介しました。
参考になればうれしいです。
Spring Fest 2020に参加しました。
12月 30, 2020
オフィス狛 技術部のJoeです。
Spring Fest 2020が開催されましたので、昨年に引き続き参加しました。
公式ページ
今年はオンライン開催ということで、昨年のような雰囲気ではありませんでしたが、
質問をチャットで受け付けてセッション後に回答いただけるなど、良かった点もありました。
また、今回は「Advanced Track」と「Beginner track」の2トラックで分かれて配信されていましたので、初めて参加される方も、セッションを選択し易かったかと思います。
(私はどれも聞いてみたく、結構直前まで迷ってしまいました)
今回も、特に気になったセッションの感想を、ブログに残したいと思います。
今こそ知りたいSpringエコシステム
槙 俊明さん(VMWare)セッション資料
Springの歴史から始まり、主なSpring Projectを下記の3つの分類に分けて紹介されていました。
・できることを増やす
・バリエーションを増やす
・使いやすくするプロジェクト
改めて、様々なプロジェクトがあることを認識させられたことと、
最新情報は、書籍ではなく、公式ドキュメントと
プロジェクト開発者のGihub、Twitterで集めることが勉強になりました。
今こそ知りたいSpring DI × AOP
多田 真敏さん(株式会社カサレアル)セッション資料
Springの基礎である、コンテナ、DI、スコープ、プロキシ、AOPについて丁寧に解説されていました。
初心者向けとありましたが、私の勉強不足もあり、なかなか説明に追いつけないところがありましたので、是非、もう一度復習したい内容でした。
CloudNativeな決済サービスの開発と2年間の歩み
鈴木 順也さん(SBペイメントサービス)セッション資料
大規模な決済サービスのシステムを、2年間運用された実績をもとに、
アプリケーション構成とアプリの役割から、
ライブラリの移行と発生した問題、開発体制、CI / CD、テスト、Observabilityといった内容を
実績で紹介されていました。
1つのサービスの歩みという内容がとても面白く、勉強になりました。
また、2年経過してシステム数やアプリ数が増加しているのでに、
プラットフォーム運用者はほぼ変わらないという点にはとても驚きました。
Spring 5.3 & Spring Boot 2.4
槙 俊明さん(VMWare)セッション資料
こちらはSpring 5.3 と Spring Boot 2.4 の新機能の紹介でした。
常に新しいもの、いいものを取り込んで進化しているという印象を受けました。
特に気になったのは、「プロパティ読み込み方法の改善」で、YAMLの定義方法が紹介されていました。
過去にSpring Boot のバージョンアップを行った際に、YAMLの定義方法の変更で、
結構ハマってしまうことがあったので、早めのバージョンアップが必要だなと思いました。
またこちらのセッション後にあった、Springについて色々な観点からの質問コーナー(?)は個人的に面白かったです。
今回はオンラインでの開催で、目的のセッションをゆっくり視聴できました。
今回のセッション動画は、今は非公開になっていますが、
来年に公開される予定とのことですので、今回視聴出来なかったセッションも確認してみたいと思います。
node.jsでS3上の画像ファイルをPDFファイルに変換する方法。
12月 30, 2020
オフィス狛 技術部のJoeです。
担当したプロジェクトで、S3上の画像ファイルをPDFファイルに変換する要件がありましたので、
変換方法を備忘も兼ねてご紹介しようと思います。
今回使用したライブライは2つです。 ※()は使用したバージョンです
・pdf-lib(1.11.1):PDFファイルを編集するためのnpmパッケージ
・sharp(0.26.3):画像ファイルを編集するためのnpmパッケージ
1.S3上の画像ファイル読み込む
S3から画像ファイルを読み込んで、bufferデータを取得します。ここで問題になったのは、読み込んだ画像ファイルが意図せずに回転してしまったことです。
読み込んだ画像ファイルの回転情報を保持するために、sharpのライブラリを使用しました。
const aws = require('aws-sdk'); const sharp = require('sharp'); // S3にアクセスするための情報 const s3Client = new aws.S3({ accessKeyId: [S3アクセスキー], secretAccessKey: [S3シークレットアクセスキー], region: [S3のリージョン], }); const params = { Bucket: [S3バケット名], Key: [S3ファイルパス/ファイル名], }; // S3の画像ファイルを取得 dataInS3 = await s3Client.getObject(params).promise(); // 画像ファイルのbufferデータを取得(rotateの引数なしで、読み込んだ画像の回転情報を保持する) bufferData = await sharp(dataInS3.Body).rotate().toBuffer();
2.pdf-libで画像をPDFファイルに埋め込む
読み込んだ画像ファイルをPDFファイルに埋め込みます。この処理では、読み込んだ画像ファイル容量が大きい場合、メモリ使用率にご注意ください。
const { PDFDocument } = require('pdf-lib'); // 空のPDFを作成 const pdfDoc = await PDFDocument.create(); // 画像のbufferデータをPDFに埋め込む image = await pdfDoc.embedJpg(bufferData); // jpgファイルの場合はこちら image = await pdfDoc.embedPng(bufferData); // pngファイルの場合はこちら // 画像の倍率を元サイズのままとして幅と高さの情報を取得 const dims = image.scale(1); // 画像ファイルと同じサイズのPDFページを追加して、画像を設定する const page = pdfDoc.addPage([dims.width, dims.height]); page.drawImage(image, { width: dims.width, height: dims.height, }); const pdfBytes = await pdfDoc.save();
3.PDFファイルをS3に保存
最後に変換したPDFファイルをS3に保存にします。// PDFファイルのbufferデータを取得 const pdfBuffer = Buffer.from(pdfBytes); // S3に保存するためのパラメータを設定 const putParams = { Bucket: [S3バケット名], Key: [S3ファイルパス/PDFファイル名], Body: pdfBuffer, ContentType: 'application/pdf', }; // S3に保存 await s3Client.putObject(putParams).promise();
以上で、変換したPDFファイルがS3に保存されました。
もし、画像からPDFへの変換が必要になった際に、参考になれば幸いです。
Catalinaにアップデートした後、pod installできないときの対処法。
12月 30, 2020
オフィス狛 技術部のmmm(むー)です。
既にBig Surがリリースされているので、少し今更感はありますがMac OSをCatalinaにアップデートした後、pod installが実行できなくなったのでその対処方法を記載します。
※ちなみにCatalinaのデフォルトシェルはzshですが、急いでいたのでひとまずbashで各作業は行っています。
実行環境
Xcodeのバージョンは諸事情で11系です...
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.7
BuildVersion: 19H15
$ xcodebuild -version
Xcode 11.1
Build version 11A1027
1. エラーの内容確認
1-1. pod installのエラーメッセージの確認
エラー内容から、CocoaPodsはrubyの2.3を使用しようとしているようですが、フォルダがないようです。
$ pod install
-bash: /usr/local/bin/pod: /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby: bad interpreter: No such file or directory
1-2. rubyのバージョン確認
Catalinaではデフォルトでrubyの2.6が入っているようです。
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [universal.x86_64-darwin19]
2. 対処方法
調査した結果、CocoaPodsを入れ直すと書かれていたので入れ直してみます。gemを使用する方法と、brewを使用する方法があるようですが、今回はgemを使用します。
2-1. Xcodeのコマンドラインツール
その前にXcodeのコマンドラインツールが必要になるのでインストールします。すでに入っている方は、下記のように表示されます。
$ xcode-select --install
xcode-select: error: command line tools are already installed, use "Software Update" to install updates
うまくインストールできない方は、公式から直接ダウンロードできるようです。
参考:https://developer.apple.com/download/more/
2-2. Xcodeとの紐付け
Xcodeにて、使用するコマンドラインツールの紐付けを行います。既にこの作業が完了している方は、読み飛ばしてください。
(私はここが完了していなかったのですが、調べた数々のサイトにはこの手順の記載がなかったので時間が溶けました...)
Xcode > Preferences > Locations > Command Line Tools > XCode X.X.X(X.X.Xはバージョン)
2-3. CocoaPodsのインストール
$ sudo gem install cocoapods -n /usr/local/bin
pod insatll を行えたら、確認完了です。
以上となります、参考になりましたら幸いです。
参考にしたページ
・This terminal won't let me run or install cocoa pods because I am on MacOS Catalina Beta? (stack overflow)
・Brew based CocoaPods CLI fails in MacOS 10.15 Catalina due incorrect fallback to Ruby 2.3 #8955 (GitHubのCocoaPodsレポジトリのissue)
Angularでgetパラメータに配列を設定する方法。
12月 30, 2020
オフィス狛 技術部のHammarです。
前回6月くらいにAngularについて投稿したのですが、そこからお久しぶりのAngularについての投稿になります。
またご存知の方には基本的なお話しかもしれませんが、「angularでgetパラメータに配列をつかってリクエストする方法」についてご紹介しようと思います。
実はすこし前にKoma(Twitterアカウントの中の人&CEO)より「HttpParams を動的に追加したい。」という投稿で、配列形式でクエリパラメータを追加するという投稿があったのですが、これに少し似ている内容で、今回は1つのパラメータに配列を設定する方法になります。
まずは最初こんな感じでいけるのかなーと思って下記作ってみました。
※HogeInfoRequestModelにitemArrayという配列項目があるとします。
上記で上手くいきそうな感じはするんですが、もちろん上手くいきません。。。
ここで「HttpParams を動的に追加したい。」の方法で、改めて配列追加という流れでやってももちろん大丈夫ですが、すでに配列になっている項目をリクエストしたい場合、下記のような記述方法でもいけました。
JSON.stringifyを使ってここでJSON文字列に変換しちゃおうという方法です。
【注意!】結果的に、「配列を送っている」というのは正しくなく、ただの文字列を送っているにすぎないので、当然受け手側(WebAPI側)が、その文字列を配列に変換する必要があります。
配列項目をリクエストするという時には、用途に合わせて良き書き方で書いていただければと思います。
前回6月くらいにAngularについて投稿したのですが、そこからお久しぶりのAngularについての投稿になります。
またご存知の方には基本的なお話しかもしれませんが、「angularでgetパラメータに配列をつかってリクエストする方法」についてご紹介しようと思います。
実はすこし前にKoma(Twitterアカウントの中の人&CEO)より「HttpParams を動的に追加したい。」という投稿で、配列形式でクエリパラメータを追加するという投稿があったのですが、これに少し似ている内容で、今回は1つのパラメータに配列を設定する方法になります。
まずは最初こんな感じでいけるのかなーと思って下記作ってみました。
※HogeInfoRequestModelにitemArrayという配列項目があるとします。
getHogeInfo(req: HogeInfoRequestModel): Observable<HogeInfoModel> { const options = { params: new HttpParams() .set('items[]', req.itemArray) }; return this.http.get('xxxxx/yyyyy/hoge/info', options).pipe(tap(console.log)); }
上記で上手くいきそうな感じはするんですが、もちろん上手くいきません。。。
ここで「HttpParams を動的に追加したい。」の方法で、改めて配列追加という流れでやってももちろん大丈夫ですが、すでに配列になっている項目をリクエストしたい場合、下記のような記述方法でもいけました。
getHogeInfo(req: HogeInfoRequestModel): Observable<HogeInfoModel> { const options = { params: new HttpParams() .set('items', JSON.stringify(req.itemArray)) }; return this.http.get('xxxxx/yyyyy/hoge/info', options).pipe(tap(console.log)); }
JSON.stringifyを使ってここでJSON文字列に変換しちゃおうという方法です。
【注意!】結果的に、「配列を送っている」というのは正しくなく、ただの文字列を送っているにすぎないので、当然受け手側(WebAPI側)が、その文字列を配列に変換する必要があります。
配列項目をリクエストするという時には、用途に合わせて良き書き方で書いていただければと思います。
2020年11月27日金曜日
NgRx 8にて発生した「@ngrx/store: runtime checks are currently opt-in but ...」の警告の解決方法。
11月 27, 2020
オフィス狛 技術部のmmm(むー)です。
Angular8 + ngrx8を使用している担当プロジェクトで、ngrx/storeの警告がでているのが気になったので対処しました。
1. エラーメッセージの確認
@ngrx/store: runtime checks are currently opt-in but will be the default in the next major version with the possibility to opt-out, see https://ngrx.io/guide/migration/v8 for more information.直訳:runtime checksは現在オプトイン形式がデフォルトですが、次のメジャーバージョンでオプトアウト形式になる可能性があります。詳細はサイトで確認してください。
これだけではさっぱりわからなかったので、メッセージに従いサイトを確認します。
2. ngrx バージョン8のアップデートガイド確認
色々書かれていますが、今回関連があるのは下記のようです。A migration is provided to remove the usage ngrx-store-freeze, remove it from the package.json, and to enable the built-in runtime checks strictStateImmutability and strictActionImmutability.直訳:ngrx-store-freezeの使用を取り除くマイグレーションが提供されます。package.jsonから削除して、ビルトインのruntime checks(strictStateImmutability とstrictActionImmutability)を有効にしてください。
要するに、ngrx7まではngrx-store-freezeを使用してStoreをimmutable(不変)にする必要があります。
しかし、ngrx8以上ではライブラリ不要になるので、runtime checksの値を設定してくださいとのことです。
弊社ではngrx-store-freezeを使用していませんが、同様にエラーが出ていました... とにかく設定しないといけないみたいです。
3. RuntimeChecksのページ確認
ページ内の記述方法を参考にstrictStateImmutabilityとstrictActionImmutabilityの値を設定します。※ngrx-store-freezeを使用している場合は、設定している2つの項目はtrueにしてください。
// app.module.ts
StoreModule.forRoot(reducers),
// ↓
StoreModule.forRoot(reducers, {
runtimeChecks: {
strictStateImmutability: false,
strictActionImmutability: false
}
}),
以上となります。
サイトに書いてあることをそのまま実行しただけですが、ngrxについて日本語で書かれているページがあまりないので、よければ参考にしてみてください。🍭
登録:
投稿 (Atom)