自分のイメージキャラクターのイラストを描いていただいたのでホームページ作りました
ひそなさんに書いていただきました・・・・!!!!最高・・・・・!!!!!
僕がほんとに好きな絵師さんで,どれくらい好きかっていうと毎年カレンダー買ってて今は5年目になります(4年目かもしれない)
マジで目が!!!!!!!!!!!!!!!!!!最高!!!!!!!!!!!!!!!!!!!!!!!
サブスク系の買い物いつの間にかめっちゃ増えてる現象
サブスク系の買い物いつの間にかめっちゃ増えてる現象
クレカの引き落としが毎月きたり,突然年間契約4000円 x 2みたいな出費が起きてびっくりするのでまとめることにしました.
YouTube Premium
¥1180 / month
満足してる.Apple Musicと用途が似てるのでどうにかしたい
YouTubeメンバーシップ
¥490 * 2 / month
必要経費.推しには貢ごう
Apple Music
¥480 / month
学生プランが剥がれないのでまだこの値段で使ってる.次通知がきたら変更する.
YouTube Premiumと用途がかぶってるんだけどCD買った時にクラウド同期できるのが良くて手放せない
Zaim
¥360 / month
ジャパンネット銀行が紐付けられるので自動で家計簿がつけられていい
Bear
¥1500 / year
解約するかも,そんなに画期的なmdエディタじゃなかった
Pixivファンボックス
¥1000 + ¥600 + ¥100 / month
ここは必要経費.必要があればもっと増やす.
vectary
¥1100くらい/month
ARがさくっと作れるジェネレーター.とりあえず課金してる
amazon prime
¥4900 / year
必需品
mac book proの分割払い
¥20000 / month
めっちゃきついけどいい買い物だった
全部(mac book proの分割を除外してる) ¥9640
多分まだあるので見つけ次第追加したり,飽きたら除外する 生活に困ったらいろいろやめる.
開発しているサービスを初めてやってみました
自社サービスをはじめて使ってみた
はじめに
上のリンクに貼った会社でフロントエンドエンジニアとして仕事をしています.
SOELUというサービスを作っているものの,オンラインフィットネスというタイトルのサービスなので,生粋の陰キャオタクである僕にはサービスを体験してみるハードルがものすごく高く今までサービスを体験せずにいました.いわゆるエアプですね.
ただ,体験しないとサービスをよりよくできないと言うのもあり,社員エンジニアはみんな一度は体験しましょう!みたいなことを言われたので怖いなぁって思いながらも体験してみることにしました.
なぜ怖く感じるのかっていうと,ヨガのインストラクターから自分が見える,しゃべりかけられるって言うのが,陰キャの僕にはすごい怖い.そもそも高専 -> 電通大とかいうオタクしかいない(女性の少ない)環境で育ってきたのでそれはそうなんですが・・・・
ただ,最近ライブビューイング機能*1が実装されたので喋りかけられることはないという安心感があり,今回ばかりは重い腰を上げてレッスンを受けてみることにしました
実際にやってみる
iPhone持ってる人は多分iOSアプリ入れたほうがいいです,Androidアプリに関してはないのでwebでやるしかないですね.
上のリンクからみるといいです.
今無料でできるので.......
ポーズチェックなしのものを選ぶといいと思います,顔も声も見せたくないでしょ?
赤く囲ってあるやつ.下の画像のタグがついてるやつを選ぶといいです
予約に関してはPCでやって*2実際に時間が来てレッスンを受ける時はPCかiOSアプリでやるのがいい*3と思う.スマホwebはどうなのかよくわからん.エアプなので・・・・
あとは時間きたら
- webなら マイページ -> レッスン一覧
- iOSなら マイページ -> 予約リスト
から入ればいい
あとは画面の前の人の言うことを聞いて体動かすだけ・・・・・見られてないから安心して落ち着いてやればいい,先生が喋りかけてくるけど俺たちに喋りかけてるわけじゃない.安心して運動するだけだ〜!!!
終えた感想
引きこもりのエンジニアには結構良さそうだな〜って思いました.
何と言うかいい気分転換になるし体動かすので結構コード書く元気が出たりする.
あと15分だけでもじんわり汗かいた....どんだけ運動してないんだよって話なんですがそれくらいの運動量です.
ただ,エコーっぽいのはある,安いマイク使ってる人とライン電話してるみたいになるけど,いつもVCとかしてエコー慣れしてるオタクなら許容できると思う!!!(許容してね...!)
終わりに
結構良かったので,疲れたな〜って思ったら無料のやつやってみようかなと言う気分になっている.ただ,顔見られるのは怖いし喋りかけられたくないので,ポーズチェックなしっていうタグついただけにするかな〜
是非やってみて,無料なので.
気に入ったら有料会員になってくれてもいいんだよ!!
あとバグ見つけたら教えて〜〜〜〜〜
学生ではなくなりました
SOELU株式会社に就職しました
やってること
Reactでこんな画面作ったりしてます.以下の2つは全て僕が実装したものです.
おわりに
コロナの外出自粛ムードが終わったらご飯でも行きましょう
欲しいものリストです.よければなにか・・・・!! Amazon 欲しいものリスト
aspidaとNestJSでHTTPClientにも型定義しながら開発するぞ!!!!!!!
aspidaとNestJSを使って気持ちがいい開発がしたい!したくない?
今回もお試しリポジトリが存在します.NestJS x aspida x Reactの環境で作っています.是非お試しください
なにするの?
NestJSはにはSwaggerModuleがありOpenAPIでしゃべることが可能になります.また, aspidaにはopenapi2aspidaというサブライブラリが存在します.この2つの組み合わせによりNestJS -> OpenAPI -> aspidaができるようになりNestJSでControllerを書くと自動的にHTTPClientの型定義が生成されるという感じになります.バックエンドを書くとフロントエンドに必要なコードが生成されるのは気持ちがいいですね.
OpenAPI経由でaspidaの設定ファイルが吐かれるのでNestJSに限らずいろいろは場面で使えるかと思います.今回はその一例としてNestJSを利用しています.
aspidaとは
HTTPClientに型をつけてくれるライブラリです.GETクエリ, Postパラメータはもちろん, Formデータにも型がつくらしい. しかもURIも保管してくれたりします.
使用感はこんな感じです
今回は /api/user/
に問い合わせるとUser
オブジェクトが返ってくるようなapiを作りました.
導入方法
yarn add @aspida/axios axios
初期設定だと<root>/apis/
以下にエンドポイントと同じ名前のディレクトリを切って設定ファイルを置いていくことになります.この設定ファイルを読んで<root>/apis/$api.ts
が作成されます.
aspidaのビルド設定ファイルは公式を見てください aspida/packages/aspida at master · aspidajs/aspida · GitHub
例えば/api/user
というエンドポイントが生えていたとすると,次のようにファイルを作って設定を書けばおkです
export interface Methods { get: { resBody: Types.User } }
作成後に
yarn aspida --build
で<root>/apis/$api.ts
が作られ型定義されたHTTPClientを使用することができます.
aspidaの設定ファイルは必ずHTTPクライアントをラップする必要があるので,実際使用するときはこのようなutil関数を作っておくと楽だと思います.
import client from "apis/$api"; import aspida from "@aspida/axios"; export const api = client(aspida());
openapi2aspida
OpenAPI形式のjsonをHTTP通信形式で受け取り,aspidaの設定ファイルを自動で作ってくれます.めちゃくちゃ便利.
ルートにaspida.config.json
を作っておき
module.exports = { input: "apis", // outputディレクトリ, openapi: { inputFile: "http://localhost:3000/swagger-json" } }
でおkです.サーバを起動した状態で, openapi2aspida --build
でaspidaの設定ファイルが全て自動生成されます.便利すぎる・・・・
2回目移行ビルドするときはoutputディレクトリ丸ごと消しておく必要があります.
fatal: destination path 'apis' already exists and is not an empty directory.
NestJSについて
Node.jsにおいてバックエンドサーバといえば, Express一強みたいなところがありましたが,最近伸びているバックエンドフレームワークです.Angulerに近い書き心地で様々な機能を後からバシバシ入れることができるプログレッシブフレームワークになっています.Star数も22.5kとかなり多くなってきていて今注目のフレームワークって感じがしてきますね
今回はNestJSには深く触れず, SwaggerModuleを入れるところから始めていきたいと思います.
2019NestJSのアドベントカレンダーに少し参加したので興味のある人はこちらへ
SwaggerModuleを入れてOpenAPIを喋れるようにする
公式ドキュメントにSwaggerModuleの導入の仕方が書いてあるのでそちらを参考に進めていきます.
必要なモジュールを入れる
yarn add @nestjs/swagger swagger-ui-express
main.tsを次のように書き換える
import { NestFactory } from "@nestjs/core"; import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger"; import { AppModule } from "./app.module"; async function bootstrap() { const app = await NestFactory.create(AppModule); app.setGlobalPrefix("api"); // frontendのrenderを/においているのでNestJSで定義される全てのControllerをapi/xxxにしておく // 公式とほとんど同じ const options = new DocumentBuilder() .setTitle("API description") .setVersion("1.0") .addServer("http://localhost:3000/") .build(); const document = SwaggerModule.createDocument(app, options); SwaggerModule.setup("swagger", app, document); await app.listen(3000); } bootstrap();
ここで現在これは修正されていますaddServer
をやっておかないとopenapi2aspida
が実行できないので気をつけましょう.
この行で落ちます
const options = new DocumentBuilder() .setTitle("API description") .setVersion("1.0") .addServer("http://localhost:3000/") .build();
これだけでNestJSがOpenAPIを喋れるようになりました.
yarn start:dev
をやってから
特に何もしていなければhttp://localhost:3000/swaggerでこのような画面を見れると思います.
また,http://localhost:3000/swagger-jsonでOpenAPIを喋っているのがJSON形式でわかります
なんの型が返ってくるかを明示するためにapp.controller.ts
を次のように書き換えます
import { Controller, Get, Post, Body } from "@nestjs/common"; import { AppService } from "./app.service"; import { ApiTags, ApiCreatedResponse } from "@nestjs/swagger"; @ApiTags("AppController") @Controller() export class AppController { constructor(private readonly appService: AppService) {} @Get() @ApiCreatedResponse({ type: String }) // ここでstringが返ってくることを書いておく getHello(): string { return this.appService.getHello(); } }
これでopenapi2aspidaで型を自動生成する準備は万端です.実際にビルドして使用感を確かめてみましょう
NestJSから吐かれるOpenAPIからaspidaの設定ファイルを生成してみる
NestJSを次のコマンドで起動します
yarn start:dev
http://localhost:3000/swagger-jsonが生きてることを確認し,aspida.config.js
に以下の設定が書いてあれば準備はおkです
module.exports = { input: "apis", openapi: { inputFile: "http://localhost:3000/swagger-json" } }
このコマンドを実行すれば自動生成されます
rm -rf apis yarn openapi2aspida --build
たったこれだけで<root>/apis/$api.ts
が生成されました.
すごいですよね!!! あとはこれをフロントエンドのコードで使うだけ!OpenAPIをメンテしていく意味も出てくるし一石二鳥のライブラリだと思います.
まとめ
去年の12月ごろにも一度使用していたのですが,かなりのアップデートがかかっていてびっくりしました. naporitan.hatenablog.com
NestJSとaspidaを使えばすべてTSの世界でwebの世界を渡り歩けるようになりました.今実戦投入するプロジェクトにこの構成をとっていますが,いい感じです.
副作用として,バックエンドでAPIを書き換えるとき影響範囲がTSの型チェックで落ちたところを修正すればよくなるのでAPI変更の際の精神負荷も少し軽減される気もします.
バックエンドでAPIを作成するとすぐ型安全な状態でそのAPIにアクセスできると言うのは圧巻だと思います. aspida流行れ・・・・!!!
DIVでBlurっぽいことをやる(React)
DIVでもInput要素のblur的なことがしたい!
InputElementは別のところを触るとBlurイベントを発火してフォーカスが外れます.
MDNのサイトで動作は確認できるかと思います.
これをDIV Elementでもやりたいなぁと言うのが今回の議題です.
今回はBlur的なことをしたくなったSelectorUIを用意しました.https://naporin0624.github.io/napoblog-assets/#/div-blur
ようなUIを考えます.
方針
セレクターUIはdivの中に存在するようになっていて,次のようなDOM構成になっています.
- ContainerDIV
- ButtonDIV
- MenuDIV
- OptionGroupDIV
- OptionDIV
- OptionDIV
- ...
- OptionGroupDIV
ButtonDIVもOptionGroupDIVもOptionDIV触っても親の要素は常にContainerDIVになるので
こちらのclosest
メソッドを使ってクリックされた要素の親にContainerがあるかどうかでフォーカスがはずれたかどうかを検知するようにしていきます!関係ないところをクリックしてもその親にはContainerはいないのでフォーカスは外れる仕組みです!
実装
こんな感じでできるかと思います!InputElementが自分でblurイベントを発火してくれるところを自分でclosestメソッドを使ってblurイベント相当のものを生成しています.
function Selector() { // closestにSelectorをわたすためにContainerのrefをとります const ref = useRef<HTMLDivElement>(null); useEffect(() => { const handler = (e: Event) => { // Blurを制御したい親Elementのselector(クラス)refからを作る const selector = ref.current?.className .split(" ") .map(s => `.${s}`) .join(); // eはクリックしたところから発火されるイベント // eをclosestで比較し,eの親にrefが含まれるか確認する const blur = !(e.target as HTMLElement).closest(selector || ""); // 親にrefが含まれていなければフォーカスを外す if (blur) setIsFocus(false); }; document.addEventListener("click", handler); return () => document.addEventListener("click", handler); }, []); return ( <Container ref={ref}> <Button></Button> <Menu> <OptionGroup> <Option>hoge</Option> <Option>huga</Option> <Option>nyan</Option> </OptionGroup> </Menu> </Container> ) }
ここなんですが
const selector = ref.current?.className .split(" ") .map(s => `.${s}`) .join();
const selector = [...ref.current.classList].map(s => `.${s}`).join()
みたいなことができたんですけど,TSだと怒られましたw
最後に
今回使ったプログラムはここに置いてあります!必要であれば使ってください. github.com
自作のUI(DIVで作ったやつ)でフォーカス制御してみたいなことがあって困っていろいろ模索した結果こんな感じの解にたどり着きました.MDNじろじろ見る癖が少しづつついてきたかなぁって感想と,CSS筋が前よりついてきた気がします.
もっとこうしたらいいよとかあれば@naporin24690に教えてください〜!
LottieWebでチェックボックスの状態を管理する
Lottieで消えちゃうCheckBox作るぞ!
こういうのを作りたい
https://naporin0624.github.io/napoblog-assets/#/
今回はこちらのチェックボックスアニメーションを使わせていただきました.
コードの全体像
Lottieのマウントにはreact-lottieを使っています.animを直で触りたいのでそこの部分だけ型定義を拡張して使っている感じですね.
index.tsx
import React, { useRef, useEffect } from "react"; import Lottie from "react-lottie"; import checkbox from "./checkbox.json"; import { AnimationItem } from "lottie-web"; interface LottieType extends Lottie { anim: AnimationItem; } interface Props { checked: boolean; } const options = { loop: false, autoplay: false, animationData: checkbox, rendererSettings: { preserveAspectRatio: "xMidYMid slice", }, }; export const CheckBox = (props: Props) => { const { checked } = props; const ref = useRef<LottieType>(null); const prev = useRef<boolean>(); useEffect(() => { // 初回マウントときはレンダリングしない // falseでは行ってきたときにgoToAndPlayされるのを防ぐため if (prev.current === undefined) { prev.current = checked; // 初回マウント かつ チェックボックスが選択されているならフレームの最後からアニメーションを実行する checked && ref.current?.anim.goToAndPlay(ref.current?.anim.getDuration(true), true); return; } if (checked) { ref.current?.anim.goToAndPlay(0, true); } else { ref.current?.anim.setDirection(-1); ref.current?.anim.goToAndPlay(15, true); } }, [checked]); return <Lottie ref={ref} options={options} width={300} />; };
最後に
lottie-webにはここでフレームを止めるみたいなことができないぽいのでこのような措置を取りました.もっといい方法があれば教えてください🙇♂️
初めはこの子
で実装していてチェックされてから消えるまでセットのアニメーションだったために以下のようにしていたのですが
useEffect(() => { ref.current?.anim.playSegments([30, 75], true); ref.current?.anim.stop(); }, []);
なぜかこうなる・・・・・・
消すとうまくいくので明らかにplaySegmentが悪いのはわかっているんですけど,どう直したらいいのかわからなかったので上で紹介したアニメーションを使いました
有識者教えてください!!!!
わかっていること
- destroyの前に動き始めている
- useEffectのreturnにconsole.logをしこませて検証
- playSegmentの上にconsole.logをおいても初期レンダリング以外では反応なし
ぐらいです・・・・・・