jackmiwamiwa devblog

フロントエンドをメインに行ったことをまとめていくサイトになります。

storybookでダークモードの対応を行う

storybook-dark-mode を追加することでstorybookでダークモードの対応を行うことができるので、その時に対応メモ。

実行結果

ライトモード

f:id:jackswim3411:20200309232034p:plain

ダークモード

f:id:jackswim3411:20200309232052p:plain

パッケージインストール¥

$ yarn add -D storybook-dark-mode

or

$ npm i -D storybook-dark-mode

github.com

.storybook/main.jsのaddons部分に記載

module.exports = {
  addons: [
    // 省略
    'storybook-dark-mode/register' // これを追記
  ],
}

.storybook/config.jsのaddParameters部分に記載

addParameters({
  darkMode: {
    // Override the default dark theme
    dark: { ...themes.dark, appBg: 'black' },
    // Override the default light theme
    light: { ...themes.normal, appBg: 'white' }
  }
})

エラー対応

現状だと以下のエラーが出たので、それの対応。

f:id:jackswim3411:20200309233915p:plain

themesがないと言われるので、@storybook/themingをインストールして対応。

$ yarn add -D @storybook/theming

or

$ npm i -D @storybook/theming

参考

https://storybook.js.org/docs/configurations/theming/

www.npmjs.com

.storybook/config.jsに以下を記載。

import { themes } from '@storybook/theming'

// いろいろな内容

補足

画像の青い部分でダークモード・ライトモードの切り替えが可能。

f:id:jackswim3411:20200309234605p:plain

pug-lintを触ってみる

pugのlintを導入したので、その時のメモ

pug-lintインストール

インストール

$ yarn add -D pug-lint

or

$ npm install -D pug-lint

www.npmjs.com

.pug-lintrcを作成

$ touch .pug-lintrc

.pug-lintrc設定

ルール記載

書き方例

{
  "validateIndentation": 2
}

詳しいルール一覧

github.com

pug + gulpの連携

gulp-pug-linterインストール

$ yarn add -D gulp-pug-linter

www.npmjs.com

gulpfile.jsに記載

// pugの処理
const htmlFunc = () => {
  return src(srcPath.html)
    // いろいろ省略
    .pipe(pugLinter({ reporter: 'default' }))
    // いろいろ省略
}

補足(webpack, vue)

webpack + pug-lint

www.npmjs.com

vue + pug-lint

www.npmjs.com

www.npmjs.com

参考一覧

github.com

tech.arc-one.jp

smart.ataglance.jp

npmアップデート手順・アップデートを行ってみて

個人のフロントエンドのテンプレートでnpmパッケージのアップデートをよく行うので、アップデートの方法などのメモ

コマンド上でのバージョンアップ手順

npm-check-updatesのインストール

グローバルにインストール

$ npm -g npm-check-updates

www.npmjs.com

npm-check-updates使い方

バージョンアップするものの確認を行う

$ ncu

バージョンアップするもの全てのバージョンをあげる

$ ncu -u

パッケージを指定して、バージョンをあげる

$ ncu -u パッケージ名

マイナーバージョンのみアップデート

$ ncu -a

devDependenciesのみアップデートを行う

$ ncu -d

dependenciesのみアップデートを行う

$ ncu -p

注意

ncuなどでバージョンを上げた時にはパッケージのインストールは完了していないので、npm installyarn installを行う必要あり。

参考

tech.glatchdesign.com

vscodeでのバージョンアップ手順

vscode上でnpmパッケージのバージョンを確認できる「Version Lens」

marketplace.visualstudio.com

コードがいつ変更されたのかを表示できる「GitLens」

marketplace.visualstudio.com

npmバージョンをアップデートしてみた所感

普段から自分の使っているバージョンに意識できるようになった

Version Lensを入れることで、気軽に確認を行うことができるようになったので、バージョンアップを行う前よりは意識できるようになった

使っているパッケージ・使っていないパッケージを普段より見つけやすくなった

npmのバージョン確認(ncuなどでバージョンアップされている) → 何のパッケージか調べる(何を行なっているパッケージか、どこで使われているパッケージかなど) → 使われている場所なし

などで使われていないパッケージを消しやすくなった。

パッケージの切り替えを行いやすくなった

Version Lensの最新版かつGitLensの更新が一定期間内行われていない場合、大替案やパッケージ自体が変更になったなど調べるきっかけになった。

参考リンク記事一覧

tech.glatchdesign.com

tacamy.hatenablog.com

cssとjsを使ってテキストに1文字ずつアニメーションさせる

テキストを1文字ずつアニメーションさせるときに手動でspanを囲わないで行いたいときに

成果物

See the Pen テキストアニメーション by miwa_shuntaro (@miwashutaro0611) on CodePen.

行ったこと

1. HTMLの作成

.txt: テキスト全体
.line: 改行させるためのもの

<p class="txt">
  <span class="line">テキストを</span>
  <span class="line">1文字ずつ</span>
  <span class="line">アニメーションする</span>
</p>

2. jsでテキスト1文字ずつにspanを導入する

function txtSplit() {
  const txtElemAry = document.querySelectorAll('.line') // 要素の取得
  txtElemAry.forEach( item => {
    let txt = '' // HTMLの導入部分初期化
    const textContentAry = item.textContent.split('') // テキスト1文字ずつを配列に格納
    textContentAry.forEach( item2 => {
      txt += item2.replace(/(\S)/g, '<span class="txtInner">$&</span>') // 追加するHTMLなど記載
    })
    item.innerHTML = txt // HTMLの内容を変更
  })
}

実行後のHTML

<p class="txt">
        <span class="line"><span class="txtInner"></span><span class="txtInner"></span><span class="txtInner"></span><span class="txtInner"></span><span class="txtInner"></span></span>
        <span class="line"><span class="txtInner">1</span><span class="txtInner"></span><span class="txtInner"></span><span class="txtInner"></span><span class="txtInner"></span></span>
        <span class="line"><span class="txtInner"></span><span class="txtInner"></span><span class="txtInner"></span><span class="txtInner"></span><span class="txtInner"></span><span class="txtInner"></span><span class="txtInner"></span><span class="txtInner"></span><span class="txtInner"></span></span>
</p>

3. animation-delayの秒数を設定

1つずつ順番に出てきて欲しいため、js側で秒数を設定

function addCss() {
  const txtElemAry = document.querySelectorAll('.line') // 要素の取得
  let aryNumner = 0 // 配列の番号(初期値0)
  const defaultTime = 0 // 初期の秒数
  const animeTime = 0.03 // 要素ごとに変化させる秒数
  txtElemAry.forEach( item => {
    [...item.children].forEach( item2 => {
      aryNumner++
      item2.style.animationDelay = `${defaultTime + aryNumner * animeTime}s`
    }) // cssのアニメーションの実行時間の設定
  })
}

cssのアニメーションは以下のように記載する(実行すること・アニメーション時間については共通のため、cssの方に記載)

.txtInner {
  animation-name: show;
  animation-duration: 0.2s;
  animation-fill-mode: backwards;
}

@keyframes show {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

実行後のHTML

<p class="txt">
        <span class="line"><span class="txtInner" style="animation-delay: 0.03s;"></span><span class="txtInner" style="animation-delay: 0.06s;"></span><span class="txtInner" style="animation-delay: 0.09s;"></span><span class="txtInner" style="animation-delay: 0.12s;"></span><span class="txtInner" style="animation-delay: 0.15s;"></span></span>
        <span class="line"><span class="txtInner" style="animation-delay: 0.18s;">1</span><span class="txtInner" style="animation-delay: 0.21s;"></span><span class="txtInner" style="animation-delay: 0.24s;"></span><span class="txtInner" style="animation-delay: 0.27s;"></span><span class="txtInner" style="animation-delay: 0.3s;"></span></span>
        <span class="line"><span class="txtInner" style="animation-delay: 0.33s;"></span><span class="txtInner" style="animation-delay: 0.36s;"></span><span class="txtInner" style="animation-delay: 0.39s;"></span><span class="txtInner" style="animation-delay: 0.42s;"></span><span class="txtInner" style="animation-delay: 0.45s;"></span><span class="txtInner" style="animation-delay: 0.48s;"></span><span class="txtInner" style="animation-delay: 0.51s;"></span><span class="txtInner" style="animation-delay: 0.54s;"></span><span class="txtInner" style="animation-delay: 0.57s;"></span></span>
</p>

参考リンク

補足(animation-delayの秒数を設定をscssで行う)

成果物

See the Pen テキストアニメーション by miwa_shuntaro (@miwashutaro0611) on CodePen.

コード

.line {
  $defaultTime: 0;
  $aryNumber: 0;
  $animeTime: 0.03;
  @for $i from 1 through 10 {
    &:nth-of-type(#{$i}) {
      @for $j from 1 through 10 {
        .txtInner:nth-of-type(#{$j}) {
          $aryNumber: $aryNumber + 1;
          animation-delay: #{$defaultTime + $aryNumber * $animeTime}s;
        }
      }
    }
  }
}

gulpfile.jsからgulpfile.tsに変更する

gulpfile.jsからgulpfile.tsに変更した時のメモ

version

  • gulp: ^4.0.2
  • ts-node: ^8.6.1
  • typescript-require: ^0.2.10

gulpfile.js

基本的に変更はしていませんが、念のため

gulpfile.jsの内容

const { src, dest, watch, parallel } = require('gulp')
const pug = require('gulp-pug')
const data = require('gulp-data')
const stylus = require('gulp-stylus')
const postcss = require('gulp-postcss')
const postcssPresetEnv = require('postcss-preset-env')
const autoprefixer = require('autoprefixer')
const plumber = require('gulp-plumber')
const notify = require('gulp-notify')
const sourcemaps = require('gulp-sourcemaps')
const cleanCSS = require('gulp-clean-css')
const browserSync = require('browser-sync')
const webpackStream = require('webpack-stream')
const webpack = require('webpack')
const htmlmin = require('gulp-htmlmin')
const mode = require('gulp-mode')({
  modes: ['production', 'development'],
  default: 'development',
  verbose: false,
})
const isProduction = mode.production()

const webpackConfigDev = require('./webpack.dev')
const webpackConfigProd = require('./webpack.prod')
const webpackConfig = isProduction ? webpackConfigProd : webpackConfigDev

const srcPath = {
  html: ['src/pug/**/*.pug', '!' + 'src/pug/**/_*.pug'],
  stylus: 'src/**/*.styl',
  js: 'src/**/*.ts',
  image: 'src/assets/img/**/*',
  fonts: 'src/assets/fonts/**/*',
  static: 'src/static/**/*',
}

const destPath = {
  root: 'dist/',
  assets: 'dist/assets/',
}

const jsFunc = () => {
  return webpackStream(webpackConfig, webpack)
    .on('error', function(e) {
      this.emit('end')
    })
    .pipe(dest(`${destPath.assets}js/`))
    .pipe(browserSync.reload({ stream: true }))
}

const htmlFunc = () => {
  return src(srcPath.html)
    .pipe(plumber({ errorHandler: notify.onError('Error: <%= error.message %>') }))
    .pipe(
      data(file => {
        return {
          relativePath: file.history[0].replace(file.base, ''), // ページ情報仮置き
        }
      })
    )
    .pipe(
      pug({
        basedir: 'src/pug',
        pretty: true,
      })
    )
    .pipe(
      mode.production(
        htmlmin({
          collapseWhitespace: true,
          minifyJS: true,
          removeComments: true,
        })
      )
    )
    .pipe(dest(destPath.root))
    .pipe(browserSync.reload({ stream: true }))
}

const stylusFunc = () => {
  return src('src/assets/stylus/*.styl')
    .pipe(mode.development(sourcemaps.init()))
    .pipe(plumber({ errorHandler: notify.onError('Error: <%= error.message %>') }))
    .pipe(stylus())
    .pipe(postcss([postcssPresetEnv(autoprefixer)]))
    .pipe(cleanCSS())
    .pipe(mode.development(sourcemaps.write()))
    .pipe(dest(`${destPath.assets}css/`))
    .pipe(browserSync.reload({ stream: true }))
}

const imageFunc = () => {
  return src(srcPath.image).pipe(dest(`${destPath.assets}img/`))
}

const fontsFunc = () => {
  return src(srcPath.fonts).pipe(dest(`${destPath.assets}fonts/`))
}

const staticFunc = () => {
  return src(srcPath.static).pipe(dest(destPath.root))
}

const browserSyncFunc = () => {
  browserSync({
    server: {
      baseDir: 'dist/',
      index: 'index.html',
    },
  })
}

const watchFiles = () => {
  watch(srcPath.html[0], htmlFunc)
  watch(srcPath.stylus, stylusFunc)
  watch(srcPath.js, jsFunc)
  watch(srcPath.image, imageFunc)
  watch(srcPath.static, staticFunc)
  watch(srcPath.fonts, fontsFunc)
}

exports.default = parallel(
  watchFiles,
  [htmlFunc, stylusFunc, jsFunc, imageFunc, staticFunc, fontsFunc],
  browserSyncFunc
)

exports.build = parallel(htmlFunc, stylusFunc, jsFunc, imageFunc, staticFunc, fontsFunc)

変更した内容

1. gulpfile.jsからgulpfile.tsにファイル名を変更する

2. 必要なパッケージインストール

ts-node

ts-node

typescriptのコードをnodeで直接実行するためのもの

typescript-require

typescript-require - npm

typeescriptのコードでrequireを使うためのもの

終わり

以上で、gulpfile.tsでもエラーなくbuildなどを行うことができます。

tslintから@typescript-eslintに変更する

tslintから@typescript-eslintに変更したので、その時のメモ 。
あくまでも自分の環境の話になります。

変更した内容

1. tslintアンインストール

$ yarn remove tslint tslint-loader tslint-config-airbnb tslint-config-prettier tslint-plugin-prettier tsutils

パッケージ一覧

  • tslint
  • tslint-loader
  • tslint-config-airbnb
  • tslint-config-prettier
  • tslint-plugin-prettier
  • tsutils

2. @typescript-eslintインストール

$ yarn add @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-config-prettier eslint-plugin-prettier eslint-loader

パッケージ一覧

  • @typescript-eslint/eslint-plugin
  • @typescript-eslint/parser
  • eslint
  • eslint-config-prettier
  • eslint-plugin-prettier
  • eslint-loader

3. tslint.jsonを削除し、.eslintrcを追加

tslint.json

{
    "extends": [
        "tslint-config-airbnb",
        "tslint-config-prettier"
    ],
    "rulesDirectory": [ "tslint-plugin-prettier" ],
    "rules": {
        "prettier": [
            true, {
                "singleQuote": true,
                "trailingComma": "es5",
                "semi": false
            }
        ]
    }
}

.eslintrc

{
  "root": true,
  "env": {
    "es6": true,
    "browser": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:prettier/recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier/@typescript-eslint"
  ],
  "plugins": [
    "@typescript-eslint"
  ],
  "globals": {
    "window": true,
    "document": true,
    "location": true,
    "ga": true
  },
  "rules": {
    "prettier/prettier": [
      "error",
      {
        "printWidth": 120,
        "singleQuote": true,
        "trailingComma": "es5",
        "semi": false
      }
    ]
  },
  "parserOptions": {
    "sourceType": "module",
    "project": "./tsconfig.json"
  }
}

4. webpack.config.jsのloaderをeslint-loaderに変更

webpack.config.js

module.exports = {
  module: {
    rules: [
      enforce: 'pre',
      test: /\.ts$/,
      exclude: /node_modules/,
      use: [
        'ts-loader',
        {
-         loader: 'tslint-loader',
+         loader: 'eslint-loader',
          options: {
            typeCheck: true,
          },
        }
      ],
    ]
  },
}

backdrop-filterについて

backdrop-filterとは

要素の背後に対してぼかしなどの処理を入れることができるプロパティ。

APPLEのTOPページのheader部分で使われているものになります。

サポート状況

2019年12月10日の状況

f:id:jackswim3411:20191210105807p:plain

参考: https://caniuse.com/#search=backdrop-filter

実装

  • 基本的な書き方
.className {
  background-color: rdba(0,0,0,0.8);
  backdrop-filter: grayscale(1);
}

表示参考

See the Pen backdrop-filter demo by Robin Rendle (@robinrendle) on CodePen.

対応していないブラウザの対応方法

方法① @supportsを使う

backdrop-filterの対応しているブラウザが少ないので、

.className {
  background-color: #fff;
  @supports (backdrop-filter: saturate(180%) blur(20px)) {
    background-color: rdba(0,0,0,0.8);
    backdrop-filter: grayscale(1);
  }
}

のように記載して対応しているブラウザのみに適応させる。

@supportsについての参考リンク

方法② polyfill対応

backdropjsをインストールして適応させる。

実行結果

Example Domain

参考リンク一覧