ウェブサイトでSVGを配置して、cssで色を変更する話

SVGをウェブページに追加する最も簡単な方法は、<svg>タグをインラインで直接記述するか、<img>要素を追加してsrc属性でSVG画像を参照することです。
SVGファイル直接に使用すると、SVGの色を変えたい時は少しややこしいです。(編集ソフトを使用して、書き直す必要があります。)
(<img> 要素を使用してインポートした場合、CSSだけで色を変更することはできません。)

単色を変えたい場合:
css実装例:

#svgID path{   
  fill: red; 
}

このようにすればcssでpath要素の色を簡単に変更できるだと思いますが、グラデーションをかけたい場合はSVGファイル自体を修正しなければなりません。そこでもう一つの方法を紹介します。

DIV要素をカスタムシェイプに:

SVGインラインで直接記述するより、DIV要素の形をSVGにすれば、色々カスタマイズができます。今回は外部SVGを参照して、cssで色をグラデーションにします。

divといえば、多くの人のイメージには長方形や正方形しかありません。しかしdivを他の形にすることができます。この時はmask-imageを使います。
(単純にdivの形を変えたい場合はclip-pathも出来ますが、今回の主旨と違いますので詳細は割愛させていただきます)

HTML実装例:
<div class=”svgShape”></div>
css実装例:
(widthとheightはsvgのサイズに合わせてください)

.svgShape {
  width: 500px; 
  height: 500px;
  background: linear-gradient(45deg, black, transparent);
  mask-image: url('/img/sample.svg');
}


このように実装すれば、divはsvgの形に変えられ、色はcssでカスタマイズできます。
実装例:

refrence:

https://developer.mozilla.org/ja/docs/Web/CSS/mask-image

Figmaでアイコン等をSlotで管理してみる

Figmaでデザイン制作する際に、
1つのアイコンを様々な大きさで使う場面があるとします。

これをVariantsでまとめておくとこんなかんじになります。

3サイズを8つの絵柄で作ると合計24個。ちょっと多い。

これをもっとスマートにまとめる
「FigmaのSlotでコンポーネントを管理する方法」があるらしく、
これを使うとコンポーネント置き場がすっきり綺麗になるそうです。

↑こんな感じ。8つの絵柄だけでOK

なので試しにやってみたぞ、というお話です。

Slotってなに?

そもそもSlotって? Figmaの機能かな?と思ってたのですが、どうやらそうではない様子。空のコンポーネントを作り、その中に入るインスタンス要素を入れ替えているようです。

参考にした動画とFigmaファイルです↓

https://www.figma.com/community/file/969234311094210750

(この動画ではカードレイアウトで解説されています)

やってみよう

1. Slotコンポーネントをつくる

まずインスタンスを入れる空のSlotコンポーネントをつくります。

長方形ツールで縦横16pxの図形を製作し、Slotという名前を付け
右クリック→「コンポーネントの作成」からコンポーネント化します。

コンポーネント化したら、もう一度選択して右クリック→「オートレイアウトの追加」を選択。右側のオートレイアウトプロパティより上下の間隔やパディングを全て0にします。

※わかりやすいようにピンクの点線で囲んでいます。

2. Slotの複数サイズ展開をつくる

デザイン内でアイコンを使用する場面を想定して、様々なサイズ展開を作ります。
今回はS(16px)M(32px)L(64px)の3種類にします。

先程製作したSlotをアセットから複製しサイズを変え、
「IconArea / S」「IconArea / M」「IconArea / L」とそれぞれ名前を付け、コンポーネント化。
コンポーネント化したら、製作した3つのIconAreaを選択して
右メニューよりVariantコンポーネントにします。

Valiantについては過去に記事を書いてますので合わせてお読みくださいhttps://blog.nasbi.jp/design/figma_variants/

3. アイコンを準備する

実際に表示したいSVGアイコンを用意し、
それぞれに「Icon / アイコン名」の名前を付けてから
コンポーネント化→まとめてVariantコンポーネントにします。

アイコンサイズは48pxにしています。

これで準備完了です。

インスタンスを置き換えてみよう

準備ができたら、あとはアセットからIconAreaを呼び出し、
IconArea / L を選択→「インスタンスの入れ替え」からアイコンを選ぶと…
アイコンがIconArea / L の大きさに可変し、インスタンスの入れ替えができました👏

ここで一つ上のIconAreaの方を選んで
「インスタンスの入れ替え」を選択しても、可変されないので注意です

普通の32pxの四角いコンポーネントを作り、インスタンスの入れ替えをしても
可変されず、元のアイコンの大きさ(48px)になってしまいます。

Slotを使うと可変されるけど…
ただのコンポーネントだと可変されず元の大きさになってしまう


Slotを使った管理方法は、
アイコンの数が多くなってしまう場合に有効なやりかたのひとつだとおもいます。
皆様も良きFigmaライフをお送りください。

LINE公式アカウントの消せないリッチメニューを消す方法

LINE公式アカウントのチャンネルを運用するには、LINE Official Account Manager(以下 Account Manager)を使う方法とサードパーティーや独自開発をしたアプリケーションを介してLINE Messaging API(以下 Messaging API)を利用する方法があります。
リッチメニューの仕様として、Account Managerで作成したリッチメニューをMessaging APIで操作したり、Messaging APIで作成したリッチメニューをAccount Managerで操作したりすることはできません。

ここで問題になるのが、リッチメニューの表示優先順位です。

ドキュメントによると(1. が最優先)

  1. Messaging APIで設定するユーザー単位のリッチメニュー
  2. Messaging APIで設定するデフォルトのリッチメニュー
  3. Account Managerで設定するデフォルトのリッチメニュー

という順で表示されるのですが、1. や 2. が設定されていると、Account Managerでリッチメニューを作成してもユーザーに表示されませんが、前述の通りAcocunt ManagerからはMessaging APIで作成したリッチメニューを削除することができません。

この場合Messaging APIを利用してリッチメニューを削除する必要がありますが、意外と簡単に削除することができます。

流れとしては

  • チャンネルアクセストークンを用意する
  • リッチメニューIDを取得する
  • リッチメニューIDを指定して削除する

の3段階です。

チャンネルアクセストークンを用意する

Messaging APIを利用するにはチャンネルアクセストークンが必要です。

チャンネルアクセストークンは LINE Developers のコンソール の「チャンネル設定」から確認することができます。

チャンネルアクセストークンがない場合は、Account Managerの右端の「設定」→左メニューの「Messaging API」のページのチャンネルID(Channel ID)とチャンネルシークレット(Channel secret)を確認できます。

そして、短期のチャネルアクセストークンを発行するAPIからチャンネルアクセストークンを発行できます。

リッチメニューIDを取得する

リッチメニューの配列を取得するAPIでMessaging APIで作成したリッチメニューのIDを取得できます。

{
  "richmenus": [
    {
      "richMenuId": "{richMenuId}", // <- これがリッチメニューID
      "name": "Nice rich menu",
      "size": {
        "width": 2500,
        "height": 1686
      },
      "chatBarText": "Tap to open",
      "selected": false,
      "areas": [
        {
          "bounds": {
            "x": 0,
            "y": 0,
            "width": 2500,
            "height": 1686
          },
          "action": {
            "type": "postback",
            "data": "action=buy&itemid=123"
          }
        }
      ]
    }
  ]
}

リッチメニューを削除する

リッチメニューを削除するAPIに先程取得したリッチメニューIDを指定して削除します。

このAPIを叩くことで「Messaging APIで設定するユーザー単位のリッチメニュー」や「Messaging APIで設定するデフォルトのリッチメニュー」も削除することができるので、Account Managerで設定したリッチメニューをユーザーに表示させることができます。

まとめ

Messaging APIが使えると、LINE公式アカウントのチャンネルをより深くカスタマイズできるようになりますが、相応の専門知識が必要です。

もしMessaging APIでお困りごとがあれば、弊社お問い合わせフォームから気軽にご相談ください。

ColimaのDocker内で `composer install` に失敗する問題の解決

M1やM2などのArm Macで、かつ Colima でDockerを使っている場合、Docker環境内で composer install でするとコケる事がある。
厄介なのは、コケたりコケなかったりColimaごと固まったり非常に不安定なことがある。
その場合恐らく、デフォルトの qemu 環境で立ち上がっていると思われるので、一旦VM環境を削除した後に

colima start --vm-type vz --vz-rosetta --mount-type virtiofs

のようにVZ環境で作り直すとうまくいく。

Virtualization.framework(vz)はMac OS 13から利用できる仮想環境のAPIで、I/Oも早くなるらしい。

aspidaのRestClientで多重送信を抑制する

OpenAPIでAPIが定義されているプロジェクトにおいて @aspida/fetch を使ってRestClientを生成・利用しています。

とあるGETリクエストを複数のコンポーネントからほぼ同時に呼び出す必要があり、リクエストの回数を1回にまとめたい状況がありました。
これをaspidaでやろうと思ったときにちょっと思ったようにできなかったのでメモ。

最初にやろうとした実装は、aspidaに渡すfetchをラップする方法。

const promises = {};
function customFetch(url, option) {
if (option.method === 'GET') {
const key = `GET__${url}`;
if (!promises[key]) {
promises[key] = fetch(url, option);
}
return promises[key];
} else {
return fetch(url, option);
}
}

promiseを再利用したいわけですが、こうすると、ResponseのStreamが使用済みなのでエラーになります。そりゃそうだ。

Response.clone() で複製してから使えばよいわけですが、aspidaの生成するtsコードで Response.json() を実行してしまうので、外からcloneを挟むようなことは無理そう…

色々考えた結果、こうなりました

const promises = {};
function dedupe(api, option) {
const key = `GET__${api.$path(option)}`;
if (!promises[key]) {
promises[key] = api.$get(option);
}
return promises[key];
}

使う側では

const result = await client.path.to.hoge.$get({ query: { fuga: 'piyo' } });

これを、

const result = await dedupe(client.path.to.hoge, { query: { fuga: 'piyo' } });

こうする。

関数で囲わなければいけなくなったのがちょっとスマートじゃないですが、まあ重複排除したいところだけ使えてポータブルな関数になったので良いということにしよう。

Google Publisher Tag のよくあるエラー

googletag.openConsole() で表示される警告文の意味と主な対処方法の自分メモ

用語

GPT: Google Publisher Tag
GAM: Google Ad Manager

ドキュメント

⚠️ 広告ユニットが取得されませんでした

何が起きているか

defineSlotは行われたが、displayやrefreshを行っておらず、広告リクエストが走っていない状態

対処方法

displayやrefreshを実行する。

googletag.display('div-id');
googletag.pubads().refresh([slot]);

disableInitialLoad() が利用されている場合は、displayでは広告リクエストが走らなくなるのでrefreshを使う。

⚠️ 広告ユニットが埋められませんでした

何が起きているか

配信条件に一致する広告申込情報が見つからずに広告を埋められなかった

対処方法

GAMで該当の広告ユニットと広告申込情報の配信設定やターゲティングを見直す

CSSのfont-synthesisとtext-renderingが原因でAndroidで太字にならない

Viteで新規にプロジェクトを作るとapp.cssに font-synthesistext-rendering が指定されています。

:root {
  ...
  font-synthesis: none;
  text-rendering: optimizeLegibility;
  ...
}

これらのプロパティがあると、 Android Chrome で見たときにfont-weightで700以上を指定しても太字にならない場合があります。

font-synthesis は、フォントに太字やイタリックの字体が含まれていない場合にブラウザが合成してよいかどうかを制御するもの。

text-rendering は、合字やカーニングの処理を行うか否かを制御し、読みやすさと速度のどちらを優先するか決めることができます。

これら2つの両方もしくはどちらかと、おそらく font-family によるフォント指定の組み合わせによって太字書体が使える環境にも関わらず太字にならないことがあるようです。

基本的に欧文フォントのためのプロパティなので、日本語環境では、少なくとも現段階では使わないほうが無難なようです。

Web Designing 2022年12月号にインタビューが掲載されました

2022年10月18日にマイナビ出版さんより発売された「Web Designing 2022年12月号」に菅沼のインタビューを掲載していただきました。

12月号はJavaScriptフレームワーク特集ですが、その中の「モダンフロントエンド開発技術の使い分けと現場の実情」というコーナーで、「普段どういう目線でフレームワークを選定しているのか?」「VueやReactなどを使う際に気をつけるべきこと」など、鼎談形式で話をさせていただきました
技術の深い話ではなく、フレームワークを使うと何が変わるのか、といった内容が主なので、現役のエンジニアよりはディレクターに向けた内容になっています

出版社サイトはこちら:
https://book.mynavi.jp/ec/products/detail/id=132319

ご興味があればぜひご覧ください!

クリエイティブに最適なAG274UXP/11をレビュー

以前の記事で、制作現場で使える最強ディスプレイを探した結果 Eve Spectrum を購入したことをお伝えしたが、今回2台目としてAOCのAG274UXP/11を購入した。
Macbook のディスプレイや Eve Spectrum とも比較をしながらレビューしていく

今回購入したAG274UXP/11はAOCというメーカーのもので、日本ではあまり聞き馴染みがないが欧米ではわりとメジャーな、台湾の老舗ディスプレイメーカーらしい。
実際にドット抜けもなく非常にコスパに優れた良い製品でした。

スペック

制作現場で重要となる項目について、AG274UXP/11のスペックは下記の通り

解像度:4K
ビット深度:True10bit
リフレッシュレート:160Hz
色域:P3 102%

2021年の M1 Pro/Max を搭載した MacbookPro が ProMotion を採用したので、外部ディスプレイで必ずしも120Hzが必要かと言われるとそうでも無くなってきているのだが、特筆すべきはP3の100%を超える色域だろう。
MacbookのP3カバー率は明記されていないが、実測で96%程度らしいので、おそらく公称値98%のディスプレイと同程度と考えると良さそう。
少なくとも AG274UXP/11 は、 Spectrum や MacbookPro より広い色域を表現できるということだ。

色域以外でもビット深度が8bit+FRCではなく True 10bit であることやリフレッシュレートが最大160Hzである点など、完全な上位互換となっている

あと、おまけでモニターフードもついてきます
マルチディスプレイとは相性が悪いが、つけてるとデキるデザイナーっぽい演出ができるのでオススメ

実際に繋いでみた

Spectrum では、おそらくディスプレイのファームウェアの問題で type-c to type-c で繋ぐと60Hzまでしか出力できず、 type-c to DP で繋いで4K144Hzを出力していたが、AG274UXP/11では type-c to type-c で繋いでも4K120Hzを選ぶことができた。
144Hzや160Hzが出力できない理由は現状わかっていないが、120Hzあれば制作用途であれば必要十分なので問題ない。

もちろんThunderboltなので、1本繋ぐだけでディスプレイをUSBハブとしても利用可能。
電源供給は60Wなので M1 Pro/Max のマシンでは少し心許ないが、高負荷な作業を連続して行わない限りバッテリーが目減りすることはないので個人的には不満には感じていない。

ロゴプロジェクターと背景のライティングは不要

やはりゲーマー向けモデルなだけあって背景は虹色に光る。
それだけならよくあるゲーミングディスプレイなのだが、AG274UXP/11に至ってはなんとロゴプロジェクターまでついている。

AOCの、このフラッグシップモデルに対する熱い思いはひしひしと伝わってくるが、まったくもって不要である。

ちなみに、背面のライティングとロゴプロジェクターはRGBそれぞれ100段階で色の変更も可能なので、最初の10分くらいは楽しく遊べます。

設定からすべてオフにできるので不要な方もご心配なく。

現状最強ディスプレイ

制作現場で使うディスプレイとしては完璧と言っていいくらいのスペックで、それに対する価格では最強と言っても過言ではないと思う

もし120Hz環境が必要ないのであれば、 HUAWEI の MateView もMacbookレベルの色域と広い作業領域が7万円程度で手に入るので非常におすすめ。
ちょっとクセは強めですが。

  • 解像度が4Kよりも縦に広い(デザインツールなどでは使いやすいと思う)
  • VESAマウントに非対応

AG274UXP/11はVESAにも対応してるけど、アームでロゴプロジェクターって相性悪くないのかなあ。

MacでThunderboltブリッジ接続のネットの上りが遅いのを解決する

tl;dr

下記コマンドでTCP Segmentation Offload を無効にする。

sudo sysctl -w net.inet.tcp.tso=0

説明

(以下すべてmacOS Catalinaで検証しています。)
Mac同士をThunderbolt3ケーブルなどを繋いでThunberboltブリッジ接続しネットワーク共有をした場合に、アップロードの速度が1MB/s以下と異常に遅いのですが、それを解決する方法を見つけました。

Thunderbolt Ethernet Bridge very slow - Apple Community に答えが載っていました。
確かに下記2種類のコマンドのどちらかで解決しました。

sudo sysctl -w net.inet.tcp.tso=0
sudo sysctl -w net.link.generic.system.hwcksum_tx=0

後者の場合はファイルの書き込み速度が50%ほど遅くなる副作用がありましたので、前者をオススメします。

これらは実際のところ何の設定を変えるコマンドなのでしょうか?

我々はその謎を探るべくアマゾンの奥地へと向かった…

net.inet.tcp.tso=0 はTCP Segmentation Offload を無効にしています。
一方 net.link.generic.system.hwcksum_tx=0 は TCP Checksum Offload を無効にしています。

ではなぜ、TCP Segmentation Offloadを無効にしたりTCP Checksum Offloadを無効にしないと異常にネットの上りが遅いのか?
TCP Checksum Offloadを無効にすると書き込み速度が落ちるのか?

答えはわかりませんでした。

でも自分が何をしたか全く分からないよりはマシなので「TCP Segmentation Offloadを無効にした」とだけ覚えておくことにします。