2018年10月4日木曜日
CSSでテキストの1文字目を大きく表示する。
10月 04, 2018
こんにちは、オフィス狛 デザイン部のSatoです。
先日、ドロップキャップをウェブサイトで表現する必要があったのですが調べるまで正しいやり方がわからなかったのでメモしたいと思います。
(テキストの1文字目のみを大きく表示する表現のことをドロップキャップって言うんですね。実は知らなかったです。)
最初大きくしたい1文字目の部分を<span>で囲んでclassで…と思ったのですが、実は「:first-letter」という擬似要素で簡単に実現できます。
いちいち<span>で囲まなくてもいいんです。
この擬似要素はブロックレベル要素の最初の文字にのみスタイルが適用されるので、ドロップキャップを実現できるのですね。
「p:first-letter」にfloat設定しp要素でfloat解除するといい感じになりました。
2018年10月1日月曜日
ESLint のエラー「Use object destructuring prefer-destructuring」に対応する。
10月 01, 2018
オフィス狛 技術部のKoma(Twitterアカウントの中の人&CEO)です。
Node.js + ESLint で開発を行っていると、良く出てくるエラーが、
「Use object destructuring prefer-destructuring」です。
直訳すると、「オブジェクトの非構造化の使用」なのですが、初見だと、何をどう修正すれば良いのか分からないんですよね・・・
例えば、以下のようなプログラムがあったとします。(あくまで例なので、意味の無いプログラムになっています)
const response = await hogeService.getUser();
if (response.id) {
const userId = response.id;
} else if (response.name) {
const userName = response.name;
}
「hogeService.getUser()」は、DBやAPIからデータを取得するイメージです。
「hogeService.getUser()」の戻り値の中には、「{id: 1234, name: "test"}」のような構造化されたデータが入っている事が前提で、そのデータと構成を「response」に設定している、という感じです。
これでESLintのチェックに掛けると、見事に
error Use object destructuring prefer-destructuring
が出ます。
「オブジェクトの非構造化の使用」を促されているので、問題なのは構造化されている「response」だと分かります。
(正確に言うと、構造化された後の使い方ですが)
と言う事で、
const { id, name } = await hogeService.getUser();
if (id) {
} else if (name) {
}
と直す事で、ESLintのエラーが出なくなります。
「const { id, name }」とする事で、構造化から解放されていますね。
初見だと分かり難いですが、
お決まりのパターンの修正なので、慣れるのが一番ですね。
2018年9月26日水曜日
Moment.jsでDeprecation warning(value provided is not in a recognized RFC2822 or ISO format)が発生した場合の対応方法(Angular,Pipe)
9月 26, 2018
オフィス狛 技術部のKoma(Twitterアカウントの中の人&CEO)です。
前回、AngularのPipeを使ってhtml(View)の表示を共通化する。と言う記事を書きましたが、実は実装をしている時に一つハマったことがあります。
最終的な実装の前に記載していたプログラムは以下の通りです。
import { Pipe, PipeTransform } from '@angular/core';
import * as moment from 'moment';
@Pipe({
name: 'changeDateFormat'
})
export class ChangeDateFormatPipe implements PipeTransform {
transform(value: string, args?: any): any {
const postDate = moment(value).format('YYYYMMDD');
const today = moment().format('YYYYMMDD');
const yesterday = moment().subtract(1, 'days').format('YYYYMMDD');
let displayDate: string = value;
if (postDate === today) {
displayDate = '今日';
} else if (postDate === yesterday) {
displayDate = '昨日';
}
return displayDate;
}
}
上記で実行すると・・・・
Deprecation warning: value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info. Arguments: [0] _isAMomentObject: true, _isUTC: false, _useUTC: false, _l: undefined, _i: 2018/09/01, _f: undefined, _strict: undefined, _locale: [object Object] Error
とエラーになってしまいます。
momentに引き渡す日付は、ISO形式ではなくていけないようです。 ただ、そもそもの値が文字列なので、文字列操作でISO形式にフォーマットするのが面倒・・・ と言う事で、前回の実装では、
const postDate = new Date(value);
const postDateISO = moment(postDate.toISOString()).format('YYYYMMDD');
上記のように一度日付に戻してから、「toISOString()」を使うようにしました。元々、トラブルの多い「new Date()」を使いたく無いので、momentにしたのですが・・・
と言う訳で、最終的な実装は、前回も記載した通り、
import { Pipe, PipeTransform } from '@angular/core';
import * as moment from 'moment';
@Pipe({
name: 'changeDateFormat'
})
export class ChangeDateFormatPipe implements PipeTransform {
transform(value: string, args?: any): any {
const postDate = new Date(value);
const postDateISO = moment(postDate.toISOString()).format('YYYYMMDD');
const today = moment().format('YYYYMMDD');
const yesterday = moment().subtract(1, 'days').format('YYYYMMDD');
let displayDate: string = value;
if (postDateISO === today) {
displayDate = '今日';
} else if (postDateISO === yesterday) {
displayDate = '昨日';
}
return displayDate;
}
}
となります。
上記実装を参考にされる方は、タイムゾーンに注意して下さいね。
2018年9月25日火曜日
AngularのPipeを使ってhtml(View)の表示を共通化する。
9月 25, 2018
オフィス狛 技術部のKoma(Twitterアカウントの中の人&CEO)です。
Angularのhtml(View)で変数を展開する場合、中括弧を二つ(double curly braces)で変数を囲みます。
<div>{{ targetDate }}</div>
さて、例えば、この「targetDate」変数に「2018/09/01」のような日付が設定されていて、
その日付が本日であれば『今日』、昨日だったら『昨日』と表示し、それ以外の時だけ、日付をそのまま表示するとします。
そんな時、どんな実現方法があるでしょうか?
「*ngIf」を使う?そもそもTypeScript側で判定しておく?色々とありますが、「*ngIf」を使うと煩雑になって、他に同じような表示箇所があったら、その度に記載する必要がありますし、APIから取得した値などは、html(View)側でリストのまま繰り返し処理を行う、
<ng-container *ngFor="let item of list">
<div class="hoge">{{item.targetDate}}</div>
</ng-container>
という方法を使う事が多いので、TypeScript側で編集はしないんですよね。まあ、『そんなのAPI側の責務でしょ』と言われたらそれまでですが、
表示内容に特化しているなら、フロントエンドでやるのも悪手では無いと思います。
さて、話が逸れてしまいましたが、こんな時に役に立つのが、AngularのPipe機能です。
簡単に言うと、htmlに表示する時に同時に変換処理も行い、表示内容を変えてしまう、と言う機能です。
早速使ってみましょう。
angular-cliを利用しているならば、
ng g pipe [path/name]と言うコマンドでテンプレートを作成出来ます。
今回は、[path/name]の部分を pipe/change-date-format に変えます。
すると、以下のようなファイルが生成されます。
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'changeDateFormat'
})
export class ChangeDateFormatPipe implements PipeTransform {
transform(value: string, args?: any): any {
return null;
}
}
この状態で、実装を行なっていきます。
今回、日付の編集・判定には、「moment」を使用します。
momentのインストールと使用方法は省きますが、実装結果は以下のようになります。
import { Pipe, PipeTransform } from '@angular/core';
import * as moment from 'moment';
@Pipe({
name: 'changeDateFormat'
})
export class ChangeDateFormatPipe implements PipeTransform {
transform(value: string, args?: any): any {
const postDate = new Date(value);
const postDateISO = moment(postDate.toISOString()).format('YYYYMMDD');
const today = moment().format('YYYYMMDD');
const yesterday = moment().subtract(1, 'days').format('YYYYMMDD');
let displayDate: string = value;
if (postDateISO === today) {
displayDate = '今日';
} else if (postDateISO === yesterday) {
displayDate = '昨日';
}
return displayDate;
}
}
処理は単純で、引数に送られてきた値を日付に変換、形式の統一、そして判定を行い、その日付が本日であれば『今日』、昨日だったら『昨日』、それ以外は日付をそのまま return しています。
Pipeの使い方は、
<div>{{ targetDate | changeDateFormat }}</div>
となります。@Pipe の name をvertical lineで変数に繋げて(Pipe)記載するだけです。簡単ですね。大規模なプロジェクトになればなるほどPipeを上手く使うと、開発効率が上がります。
それでは、より良いAngularライフを!
2018年9月21日金曜日
Amazon Linux 2 にnginxをインストールする。(Amazon Linux Extrasを使う)
9月 21, 2018
オフィス狛 技術部のKoma(Twitterアカウントの中の人&CEO)です。
今回は完全に自分用の備忘録です。
(毎回同じ問題にぶちあたり、同じ情報を調べるので・・・・)
さて、早速ですが、AWS EC2 のAmazon Linux 2 に、nginxをyumでインストールしようとすると・・・
$ sudo yum install -y nginx 読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd パッケージ nginx は利用できません。 エラー: 何もしません nginx is available in Amazon Linux Extra topic "nginx1.12" To use, run # sudo amazon-linux-extras install nginx1.12
と、エラーになってしまいます。
・・・まあ、メッセージに解決策があるのですが、
念の為、説明しておくと、Amazon Linux 2には、
Amazon Linux Extras という仕組みがあって、良く使われるソフトウェアの最新バージョンについて、関連パッケージを含めて簡単にインストールすることが出来ます。
AWS自体が提供している仕組みだけあって、OSの安定性を保ったインストール・利用が可能になります。
実際にどんなものを提供しているのか見てみましょう。「amazon-linux-extras」というコマンドを実行してみます。
$ amazon-linux-extras
0 ansible2 available [ =2.4.2 ]
1 emacs available [ =25.3 ]
2 memcached1.5 available [ =1.5.1 ]
3 nginx1.12 available [ =1.12.2 ]
4 postgresql9.6 available [ =9.6.6 =9.6.8 ]
5 postgresql10 available [ =10 ]
6 python3 available [ =3.6.2 ]
7 redis4.0 available [ =4.0.5 =4.0.10 ]
8 R3.4 available [ =3.4.3 ]
9 rust1 available \
[ =1.22.1 =1.26.0 =1.26.1 =1.27.2 ]
10 vim available [ =8.0 ]
11 golang1.9 available [ =1.9.2 ]
12 ruby2.4 available [ =2.4.2 =2.4.4 ]
13 nano available [ =2.9.1 ]
14 php7.2 available [ =7.2.0 =7.2.4 =7.2.5 ]
15 lamp-mariadb10.2-php7.2 available \
[ =10.2.10_7.2.0 =10.2.10_7.2.4 =10.2.10_7.2.5 ]
16 libreoffice available [ =5.0.6.2_15 ]
17 gimp available [ =2.8.22 ]
18 docker=latest enabled [ =17.12.1 =18.03.1 ]
19 mate-desktop1.x available [ =1.19.0 =1.20.0 ]
20 GraphicsMagick1.3 available [ =1.3.29 ]
21 tomcat8.5 available [ =8.5.31 ]
DBやWebコンテナ、言語、フレームワークなど、色々ありますね。さて、nginx1.12 が利用可能(available)になっているので、インストールしてみます。
sudo amazon-linux-extras install nginx1.12
これでインストール完了です。もう一度「amazon-linux-extras」というコマンドを実行してみます。
$ amazon-linux-extras
0 ansible2 available [ =2.4.2 ]
1 emacs available [ =25.3 ]
2 memcached1.5 available [ =1.5.1 ]
3 nginx1.12=latest enabled [ =1.12.2 ]
4 postgresql9.6 available [ =9.6.6 =9.6.8 ]
5 postgresql10 available [ =10 ]
6 python3 available [ =3.6.2 ]
7 redis4.0 available [ =4.0.5 =4.0.10 ]
8 R3.4 available [ =3.4.3 ]
9 rust1 available \
[ =1.22.1 =1.26.0 =1.26.1 =1.27.2 ]
10 vim available [ =8.0 ]
11 golang1.9 available [ =1.9.2 ]
12 ruby2.4 available [ =2.4.2 =2.4.4 ]
13 nano available [ =2.9.1 ]
14 php7.2 available [ =7.2.0 =7.2.4 =7.2.5 ]
15 lamp-mariadb10.2-php7.2 available \
[ =10.2.10_7.2.0 =10.2.10_7.2.4 =10.2.10_7.2.5 ]
16 libreoffice available [ =5.0.6.2_15 ]
17 gimp available [ =2.8.22 ]
18 docker=latest enabled [ =17.12.1 =18.03.1 ]
19 mate-desktop1.x available [ =1.19.0 =1.20.0 ]
20 GraphicsMagick1.3 available [ =1.3.29 ]
21 tomcat8.5 available [ =8.5.31 ]
nginx1.12 が使用出来る状態(enabled)になっています。
念の為、コマンドを実行してみます。
$ nginx -v nginx version: nginx/1.12.2
無事にインストール出来ているようです。
以上、本当に備忘録でした。
2018年9月19日水曜日
knex.js の transaction でなぜか delete されないときに注目すること。
9月 19, 2018
オフィス狛 技術部 CTOの Taka-yamです。
knex.jsは、Node.jsでActiveRecordを用いてSQLを発行するライブラリです。
fluentにSQLを構築でき、大変便利だなと感じる一方で、
トランザクション中にSELECT分を使用する際にちょっとした落とし穴があり注意が必要です。
例えば、booksというidとnameを保存するシンプルなテーブルがあるとして考えます。
id | name | ---+-------------+ 1 | 我輩は猫である| 2 | こころ | 3 | 三四郎 |
例えば、このテーブルのid1のデータを 削除->存在チェック->登録と実行します。
// knexの定義
const knex = require('../db/knex');
knex.transaction(trx => {
// 全て削除
knex.from('books').del();
// 消えているか確認(存在チェック)
const user = knex.from('books') . where('id', 1).first();
if (typeof user !== 'undefined') {
throw new Error(' データがあるよ')
}
// 登録
const books = {id: 1, name: '銀河鉄道の夜'}
knex.insert(books).into('books');
}
上記の メソッドは存在チェック後のifでエラーを投げます。
なぜか?
これは selectがクロージャ内に渡されているKnex.Transactionインスタンスを使用していない ため、
トランザクションとは別に処理を走らせてしまっているためです。
クロージャ内にいるので一見すると同じトランザクション として扱われるのかなと思ってしまいますが、実際には下記のようにしないといけません。
knex.transaction(trx => {
// 全て削除
trx.from('books').del();
// 消えているか確認(存在チェック)
const user = trx.from('books').where('id', 1).first();
if (typeof user !== 'undefined') {
throw new Error(' データがあるよ')
}
// 登録
const books = {id: 1, name: '銀河鉄道の夜'}
trx.insert(books).into('books');
}
selectに関しては下記のようにも 書けます。
const user = knex.transactioning(trx).from('books') . where('id', 1).first();
例えば処理を共通化して別メソッドとして切り出したりしていると、
思わぬところでトランザクションが途切れてしまっていることがあり、
「???」になることがあります。
また、個人的にですが、Realmなどのライブラリですと、
クロージャ内がトランザクション領域として扱われるので
勘違い して同じように使用してはまってしまったという経緯もありました。
もし同じような現象で困っている方がいらっしゃいましたら、
上記のような可能性も考えてみてください。
2018年9月3日月曜日
Illustratorでカラーバリエーションのあるようなアイコンやイラストをできるだけ楽に作る。
9月 03, 2018
この記事は2018年9月時点のオブジェクトを再配色機能の説明です。
2020月11月に新しい機能などの説明を加えた記事を投稿しています↓
こんにちは、オフィス狛デザイン部のSatoです。
今回はカラーバリエーションのあるようなアイコンをできるだけ楽に作る方法をご紹介したいと思います。
アプリ内の画像などを作っている時に背景色によってアイコンの色が変わったり、状態によってアイコンカラーが変わったりするときの画像がすこーし簡単に作れるようになります。
Illustratorで描いたイラストです。
パーツが少し多いのでもうちょっと一部の色を明るくしたいなと思ったり、カラーバリエーションのある画像が欲しいと思うとちょっと大変ですよね。
こういう時に使える機能が「オブジェクトを再配色」機能です。
まず色を変えたいオブジェクト全体を選択し、Illustratorメニューバーの「編集」の「カラーの編集」から「オブジェクトを再配色」を選ぶかツールバーのオブジェクトを再配色アイコン」クリックします。
下のようなオブジェクトを再配色パレットが出てきます。
編集ボタンを押すと色相環のような画面になるので右下の「ハーモニーカラーをリンク」ボタンをクリックしておきます。(これをクリックするとまとめて色相や彩度が変わります)
色相環のような図の中の丸い色つきの丸を移動させると色相が変わるのでこれで一気に全体的な色が変えられます!
一部だけ色が変えたい場合は「ハーモニーカラーをリンク」ボタンを押さずに変えたい部分の色のみの位置を動かしたり、指定画面(編集ボタンの横にある「指定」ボタンで画面が戻ります)から色を変えたりできます。
一部色を変えてみました。
グラデーションで使われている色などもこの機能で変えられるので、カラーバリエーションのある画像がササッと数枚作れます。
使う機会が多そう&時短になる機能なので、ぜひ使ってみてください。
登録:
投稿 (Atom)








