俺と俺のカップルチャンネル

ブログのひとこと説明を入力します。

IPL脱毛器の中身を出してみたら (JIN BISON RK-V9)

激光脱毛, 記事サムネ

JIN BISON(金野牛) 3イン1 光脱毛器 RK-V9です。Alibabaで単価30ドルくらい。http://www.jindlson.com/products_content-2130122.html

パカリ。

光脱毛器 RK-V9

ほとんどカメラのフラッシュライトですね。コンデンサもカメラ用。遠心ファンはランプを冷却するためのものです。

光脱毛器 RK-V9光脱毛器 RK-V9

基盤おもてうら。トランスの左上でねじれている薄板はパワーMOSFETの放熱板。ファンのケースがへし折ってありエアーが漏れてくるようになっています。スイッチも入らないところは斜めに削ってあって手作り感があふれていました。

PCI Express x1ソケット

ランプカートリッジのソケットはなんか見たことあるぞと思ったらPCI Express x1が流用されていました。

ちなみにこの機種、人体に接触するヘッド側から排熱する設計ですのでおすすめできないです。

Tailwind 2.0のfont-familyがどうなっているか確認したので

触った感触を述べたいがよろしいか。

あらまし

お勉強しようと使ってみたところなぜか游ゴシックUIで表示される…。調べたらTailwindのfont-familyはUI系ゴリ押しでした。カスタマイズは規定のフォントクラスを上書きして行うようです。

  • postcss 8.2.4
    • tailwindcss 2.0.2
      • modern-normalize 1.0.0
      • purgecss 3.1.3

プリセットを見る

ドキュメント全体にかかっている設定から見たいと思います。最初にmodern-normalize.cssがインポートされるためその書体指定もあるのですがTailwindにほぼ上書きされるのとコンセプト的に大差ないので割愛いたしました。

html {
  font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
  "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
  "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}

body {
  font-family: inherit;
}

button, input, optgroup, select, textarea {
  font-family: inherit;
}

pre, code, kbd, samp {
  font-family: ui-monospace, SFMono-Regular, Menlo, Mona...
}

大掴みに言うとゴシック体を使うことと各プラットフォームの普及フォントを使うというポリシーがあるようです。一貫した体験性を提供しようという考えのもとユーザの選択肢を奪う指定になっておりまして好みの分かれるところだと思いますがフレームワークなのでそれはいいとして問題は日本語環境のwindowsでございますあね。

system-uiはアレがアレする

system-uiはOSのネイティブUIに使われているフォントを意味する総称フォント1でありまして現状OSの見た目に寄せたい部分に使うのが無難でしょう。たとえばPWAのメニューとか。

The purpose of system-ui is to allow web content to integrate with the look and feel of the native OS.

英語圏では可読性の高いSegoe UIが選択されるので構わないのでしょうけど、MS UI Gothicにつらなる日本語UIフォントというのはレタースペースが極小となっていてVariable fontでもなくUIパーツに全角文字を押し込むのに都合がよいですが文章となると読みづらい。実際主要ブラウザのデフォはUIじゃないほうのMeiryoですし、まあわざわざUI系フォントで閲覧している人がいないとは言い切れないですけど、そうであるにしてもノーマライズと言いつつ偏屈な特殊例を増やす残念なCSSであることには変わりありません。

このプロセスはpreflightに含まれており無効にするオプション2も紹介されていましたがこれをやると下処理がゴソっと抜けてしまうのでルート要素のフォント指定だけ変更する方法について後で触れたいと思います。

フォントファミリのクラス

上記はhtml全体のお話でしたが、要素ごとにフォントファミリを指定するためのクラスが用意されています。こちらはpreflightを止めても使用可能でした。

.font-sans {
  font-family: ui-sans-serif, system-ui, -apple-system, ...
}

.font-serif {
  font-family: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
}

.font-mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}

それぞれresponsive variantも生成されますので画面サイズに応じて表示フォントを変えることができます。デバイスごとにserifとsans-serifを切り替えたい需要がどこかにあるのやもしれません。

カスタマイズについて

Tailwindのfont-familyは日本語環境にマッチしない部分がありました。またフォントクラスのvariantは標準ではまず使わないであろうものでしたのでカスタマイズが前提となっているのかなと思います。

クラス定義

tailwaind.config.jsに新しいクラスを定義するならたとえば以下のように指定します。

module.exports = {
  theme: {
    extend: {
      fontFamily: {
        'sans': ['sans-serif'],
        'relics': ['Times New Roman', 'MS PGothic'],
        'ui': ['system-ui', '-apple-system']
      }
    }
  }
}

クラス名はキーの頭に.font-を足して作られます。この場合.font-sans, .font-relics, .font-uiとそれぞれのvariantが生成されます。配列の値はそのまま出力されますのでフォント名によっては3は引用符も含めて設定しておく必要があります。

全体指定の上書き

.font-sansの値はhtml要素のフォント指定としても利用されます。なのでsansを上書きすると結果的に全体設定になります。同様に.font-monoはpreなどの初期値と入れ替わります。この点についてマニュアルに該当箇所が見つけられなかったのですがCSSのコメントには一応記載がありました。

Use the user's configured `sans` font-family (with Tailwind's default sans-serif font stack as a fallback) as a sane default.

そういうわけでクラスとして使わないとしてもsansだけは設定しておくのがよいと思われます。

CSSでつくる透過吹き出し

CSSというより根性で作った。

bonjiri
BONJIRI: an example of CSS speech bubble with transparent background & rounded corners.

作成手順

クラスポン付けで<span class="comment"></span>吹き出しにすることを目指していきます。

背景をつくる

まずこれを作ります。

f:id:nosei:20210311193947p:plain

角が丸くなってるのが要素本体。その下についてる帯はlinear-gradientの透過ピクセルborder-imageにして付けました。角の丸め方は以下の要領です。

f:id:nosei:20210314200325p:plainf:id:nosei:20210311193956p:plain

パディングエリア(緑)の四つ角が同じになるようにボーダー(黒)を曲げているのが分かるでしょうか。コードとしては例えば

.comment {
  border-radius: .4em;
  border-bottom-width: .6em;
  border-bottom-left-radius: .4em calc(.4em + .6em);
  border-bottom-right-radius: .4em calc(.4em + .6em);
}

のように楕円の縦の半径にボーダーの幅を足すといい感じにニュッと曲がります。

ちなみに黒のボーダーはborder-imageに置き換わるので色はどうでもいいですが見えないだけで場所は取ります。

::beforeで枠をのせる

f:id:nosei:20210311194000p:plainf:id:nosei:20210311194004p:plain

::beforeのボーダーで枠を作ります。真ん中下のところはclip-pathで切っておきます。clip-pathはパスで囲ったところだけ表示させるプロパティで、ここでは全体をぐるりと囲いつつ消したいところだけ外へ出すような感じです。

::afterでつのを成型する

f:id:nosei:20210311194008p:plainf:id:nosei:20210311194014p:plain

海苔状の物体は::afterのボーダーです。これをV字に切り抜いて吹き出しのつのにします。

カットして完成

f:id:nosei:20210311195148p:plainf:id:nosei:20210311195154p:plain

.commentのclip-pathではみ出している部分を切ったら完成です。

CSSの実際

polygonのストロークをのけると正味30行くらいですからやってることはわりと単純ですがしかし簡単に見えて意外とこのやり方でないとという部分がありますのでいくらか自注をつけたいと思います。

デモ

要素境界を整える

.comment {
  ...
  background-clip: padding-box;
  border-bottom: solid 1em;
  border-image: linear-gradient(var(--bg-color) 0 1%) 1;
  -webkit-clip-path: polygon(...);
  clip-path: padding-box polygon(...);
}

background-clipは背景の範囲を決めるプロパティで初期値はborder-boxです。背景とボーダーはダブるとブレンドされて色が変わってしまうのでpadding-boxを指定して分離します。

困るのがスケーリングが掛かって要素サイズの計算値に1ピクセル未満の端数が出る場合で、そうなるとborder-imageとパディングエリアはぴったりくっつきません。これは仕様によるもの・バグによるものとUAの解釈によるものがあり、微妙に隙間が空いたり重なったりして本当に往生するわけですが「border-widthborder-image-widthが1:1でborder-image-outsetがゼロ」ならかなりフィットします。つまり何も指定しない時が一番まともです。

border-imageのwidthとoutsetを使う場合単位を付けずに比率で指定し、かつそれぞれ整数倍にしておけば目立つギャップは回避できるようです。

clip-pathの座標計算でも同種の問題にあたりまして単純にボックスの境界でクリップすると削げることがありました。今回の作例ではFFは参照ボックスをpadding-boxにすることでボーダーを食いにくくなりました。webkitは参照ボックスの指定に対応していないのですがもともとの作りとして隙間は空いても削ることはないようです。

続いて::afterでつのの縁取りを作るところです。

.comment::after {
  box-sizing: content-box;
  height: calc(100% - var(--border-w));
  border-bottom: solid .7em var(--border-color);
  clip-path: polygon(...);
}

つのを枠の内側のラインに合わせるために、枠線一本分低いボックスを作って基準にしています。最初はpositionで位置を合わせようとしたんですが例によって精度が出なかったのでまだマシなheightを使っています。box-sizingはどちらでもよいですがborder-boxにしたい場合、箱の外にボーダーを生やすためにborder-image: linear-gradient(var(--border-color) 0 1%) 1 / 1 / 1;としてアウトセットする必要があるかと思います。

その他の検討事項

最初の思いつきとしてはSVGborder-imageで楽々と透過吹き出しが作れるのではと思ったんですがそんなことは全くなかった。そこでボーダーと疑似要素をclip-pathで加工する手法を試みましてある程度の成果があったのではないかと思います。実用上の課題としてはpolygonによる切り抜きが面倒なことだと思います。機械的にやれるとよいのですが。それからつのをカーリーにしたい場合ですね。できそうな気はしますが労力を天秤にかけるとそもそも背景画像として用意するかjavascript吹き出しSVGを生成するほうが沼が浅い予感がします。

今回調べてみてサブピクセル絡みのレンダリングギャップは一般化された対処法もなくかなり厄介だなと感じました。私はもう面倒になってしまったのでスケールを基準に考えればむしろ割り切れるピクセル値が異常であり表示位置はズレるほうが逆に自然なのではと思い始めている次第です。

clip-pathpath()が使えるのでドローソフトの定義がそのままコピペできる…ことになっているけれども現状では座標がボーダーエリアの左上を原点としたピクセル値で、引数に文字列しか受け付けないためcalc()も挟み込めないということで実際には適用できるケースのほうが稀ではないかなと思います。Inline SVG<clipPath>はややサポートが厚いですが、とは言えCSS側の計算値を反映させる工夫が必要になると簡単ではないと思います。clipやmask用途での使い勝手は数年来あまり変わっていないようでありまして先進的なサイトの素敵なサンプルに化かされて手を出すと肥溜めに肩まで浸かることになるので注意が必要だなと思いました。

やっちまったな!

Lifebookのbeepを鳴らすメモ

f:id:nosei:20210326152804p:plain

意外と鳴らないbeepを鳴らすメモです。以下にbeepを鳴らさない方法が色々書いてあるので反対のことをすればだいたいなんとかなる模様。 https://wiki.archlinux.org/index.php/PC_speaker

1. 環境

2. モジュールについて

とりあえずlsmodしてpcspkrがロードされていることを確認します。ubuntuでは/etc/modprobe.d/blacklist.confでロードされないようになっているらしいですがdebianではそういったことはなかった。pcspkrの代わりにsnd_pcspでもbeepできますがわざわざこれを使う意味はなかろう。

3. ミュート解除

デフォ消音につき、apt install alsa-utilsしてalsamixerを起動。メインボリュームとbeepmしてミュートを解除、Gainを0dbまで上げておきます。Loopbackもenabledにする必要があります。

4. パーミッションのチェック

非rootでbeep --verboseするとpermission deniedされている事象について。

4-1. udevのデフォルトルール

beepの出力先デバイスのpermissionはudevで設定されています。ルールは/lib/udev/rules.d/70-beep.rulesにあり、ACLでuaccessが設定されるのでローカルにloginしているユーザなら誰でも出力可能ですがsshやらジョブキューから実行していると弾かれることになります。

4-2. udevで権限付与

beepの出力先をaudioグループ所有に変更して書き込みできるようにします。audioグループがない場合まず

# addgroup audio
# usermod -aG audio わしじゃよ

などとして準備します。70-beep.rulesを/etc/udev/rules.dにコピーして編集。udevのルールは1行で、マッチ条件に続いてAssignmentを記述することになっているので

ACTION=="add", SUBSYSTEM=="input", ATTRS{name}=="PC Speaker", \
ENV{DEVNAME}!="", TAG+="uaccess", GROUP="audio", MODE="0660"

のように書きます。これでPC Speakerなるinputデバイスがaddされたときにグループとrwが割り当てられる。さっそく適用してみましょう。ルールをリロードしてaddトリガを発行。

# udevadm control --reload
# udevadm trigger -c add /dev/input/by-path/platform-pcspkr-event-spkr

パーミッションエラーが消えればヨシ。fmv-820mgはこれでよかったのですがp772ではエラーはでないが音が鳴らなかったため続きます。

5. PC Speakerが鳴らないケース

beepはまず/dev/input/by-path/platform-pcspkr-event-spkrへ出力を試みます。このファイルは/dev/input/eventNへのシンボリックリンクになっていますがそもそもこいつが鳴らないようです。

5-1. PC SpeakerとHDA Digital PCBeep

PC Speakerは伝統的なPITの出力を使ったBeepで、後者はIntel High Definition AudioのBeep機能です。p772には両方あります。

udevはPC Speakerをbeepバイスとしてセットアップしてくれるが鳴らない…。Digital~のほうを鳴らした直後だけうっすら鳴るのでどうも存在はするらしいが常時給電されているわけではないのか詰んだのでDigital PCBeepを使うことにしました。

まずデバイスを探すわけですが方法は至って簡単で手当り次第に# beep -e /dev/input/eventNして鳴ったやつがそれ。一応デバイスのリストからも確認してみます。udevadm info -eすると

P: /devices/pci0000:00/0000:00:1b.0/sound/card0/input14
L: 0
E: DEVPATH=/devices/pci0000:00/0000:00:1b.0/sound/card0/input14
E: SUBSYSTEM=input
E: PRODUCT=1/10ec/269/1
E: NAME="HDA Digital PCBeep" 
E: PHYS="card0/codec#0/beep0"
E: PROP=0
E: EV=40001
E: SND=6
E: MODALIAS=input:b0001v10ECp0269e0001-e0,12,kramls1,2,fw
E: USEC_INITIALIZED=3517421
E: ID_INPUT=1
E: ID_PATH=pci-0000:00:1b.0
E: ID_PATH_TAG=pci-0000_00_1b_0
E: ID_FOR_SEAT=input-pci-0000_00_1b_0
E: TAGS=:seat:

のようなブロックが見つかりました。このデバイスにリンクするようudevのルールを更新します。マッチ条件に使える属性はudevadm info -a -n input/eventNなどで得られます。

5-2 Digital PCBeep用のudevルール

ルールを上書きしたいので/etc/udev/rules.d/70-pcspkr-beep.rulesを作って

ACTION=="add", SUBSYSTEM=="input", ATTRS{name}=="HDA Digital PCBeep", \
KERNEL=="event?*", SYMLINK="input/by-path/platform-pcspkr-event-spkr", \
TAG+="uaccess", GROUP="audio", MODE="0660"

としました。これでHDA Digital PCBeepというデバイスが追加されるとリンクが貼られてパーミッションも設定されます。リンクを触りたくなければalias beep='beep -e /dev/input/event8'などでよいでしょう。

6. HDA Digital PCBeepの制約

AC'97・HDAの仕様でBeepジェネレータのトーンレジスタは8bitしかなく、生成可能な周波数は 48000 / (1 .. 255 * 4) Hzに限られます。PC Speakerの 1193182 / (20 ... 32767) Hzと比べるとやや大雑把な音律で、メロディとして聴くなら5歳児のアカペラくらいの印象になるかと思います。

7. ハードウェア事情など

BeepバイスがPC Speakerという名前であるのはIBM PCに遡るらしいですね。Intel C8253というタイマーICで矩形波を出すことができたのが専らBeepとして利用されるようになったそうです。時代の流れでタイマーで音を鳴らさなくてもよくなりましたが、データシートを見るかぎり82C54互換のPITがチップセット(ich-mやpch)に統合されて生き残っていまして、オーディオコーデックにもPCBeep入力ピンが残っているところ、繋げばLineに出せる作りになっているようです。しかし今回調べていて分かったことはBeepを鳴らしたい人より止めたい人のほうがずっと多いこと。コストや電力の問題が解決したとて需要がなければBeepの消滅は必定かもしれんすね。個人的にはサウンドBeepの用途は別だと思いますし実機のブザーはいい音なので存続してほしい気持ちは多少ありますが。

beep -f 523 -l 300 -D 100 \
-n -f 698 -l 800 \
-n -f 880 -l 300 -D 100 \
-n -f 784 -l 800 \
-n -f 523 -l 300 -D 100 \
-n -f 698 -l 800 \
-n -f 880 -l 400 \
-n -f 784 -l 400 \
-n -f 880 -l 400 \
-n -f 932 -l 400 \
-n -f 1047 -l 400 \
-n -f 880 -l 400 \
-n -f 698 -l 400 \
-n -f 784 -l 700 -D 100 \
-n -f 523 -l 400 \
-n -f 698 -l 1200

Daisy Bell (A Bicycle Built for Two)

参考

サンプルエントリー

カスタムテーマ制作用のサンプルエントリーです。下記をコピーして記事を作成してください。 ※ Markdownで書かれています。 必ずブログの「設定」-> 「編集モード」を「Markdown」に変更してから記事を作成してください。

段落

あのイーハトヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモーリオ市、郊外のぎらぎら光る草の波。

あのイーハトヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモーリオ市、郊外のぎらぎら光る草の波。

画像(はてなフォトライフ

f:id:nosei:20210306204716j:plain
pepper

あのイーハトヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモーリオ市、郊外のぎらぎら光る草の波。

f:id:nosei:20210306204720j:plain
Gold Hill

脚注

あのイーハトヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモーリオ市、郊外のぎらぎら光る草の波。*1

罫線


(Rounded Mplus 1c Bold)

h1見出し

あのイーハトヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモーリオ市、郊外のぎらぎら光る草の波。
ABCDEFGHIJKLMabcdefghijklm1234567890

h2見出し

h3見出し

asin

あのイーハトヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモーリオ市、郊外のぎらぎら光る草の波。

「へんな会社」のつくり方 (NT2X)

「へんな会社」のつくり方 (NT2X)

あのイーハトヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモーリオ市、郊外のぎらぎら光る草の波。

引用

本日(11月12日)から11月27日まで、はてなダイアリー公開デザインコンテスト「公開デザイン祭2007秋」を開催します。

「公開デザイン祭2007秋」を開始しました - はてなダイアリー日記

リスト(ul,ol,dl)

あのイーハトヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモーリオ市、郊外のぎらぎら光る草の波。

あのイーハトヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモーリオ市、郊外のぎらぎら光る草の波。

  1. 大賞1名:Amazonギフト券5万円分
  2. 入選9名:Amazonギフト券1万円分
    1. 大賞1名:Amazonギフト券5万円分
    2. 入選9名:Amazonギフト券1万円分

あのイーハトヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモーリオ市、郊外のぎらぎら光る草の波。

大賞1名
Amazonギフト券5万円分
入選9名
Amazonギフト券1万円分

テーブル

あのイーハトヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモーリオ市、郊外のぎらぎら光る草の波。

名前 個数
りんご 1
みかん だいだい 2

あのイーハトヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモーリオ市、郊外のぎらぎら光る草の波。

コードブロック

css

.xxx {
  width: 999px;
  height: 999px;
}

.propA, .propB, .propC {
  width: 999px;
  height: 999px;
}

#yyy {
  width: 9px;
  height: 999px;
}

typescript

const stepOpr = (actualOperation: Function) => { // something to say
  return (x: number) => {
    return (y: number) => {
      return actualOperation(x, y)
    }
  }
}

const add = (x: number, y: number): number => {
  return x + y
}

let left = stepOpr(add),
    right = left(1),
    ret = right(2)

console.log(ret) // => 3

aa

                     _
                 /::::::::::::::::\
                    ,     ヽ:::::::::::::、
              /         、:::::::::::::、
             / , --_ 、     、::::::::::::、
                レ/'`´` ヽミ_ヽ   、:::r=、:::、
                ゝ'_,、,、,、, 、_、 ゝム  、:|l c:}}:::、
             ゞ'゙  ̄ ̄` ゙‐-ヽ、マ 、:ゝ=''::::::,
               |          `゙  、::::::::::::::::,
          /i                 、ニニ',::::::,
         /:::::|               、ニニ',::::::i
         /:::::::::::|                、ー、:::::::::|
        /::::::::::::::|                /:::::::::ヽ:::::::ト..、
     ,.:':::::::::::::::_:|             /:::::; :::::::::゙、:::i::::::::"'''-...、
     '_::::::::: -‐'´ |           ./::::::::::::::::::::::::i:::i ::::::::::::::::::シ
       ̄    |          ,..':::::::::::::::::::::::::::::,-::::i:::::::::::::, -'
           |       /:::::::::::::::::::::::_:, -':::::::├‐ ' ´
                  ゝ-----‐ '゙´

*1:ここに脚注を書きます