サイトのあちこちで歯車が回ってます
このサイト、よく見ると歯車の設計図みたいなイラストがあちこちにあります。トップに1枚、サービスと会社概要と地域ページに1枚ずつ。ブログのカバー画像も同じノリで描いてます。
社名の「カラクリオ」はからくり仕掛けから取っているので、歯車は出したかった。ただ、よくあるフラットな歯車アイコンだと面白くないので、寸法線と注記つきの「図面」にしました。しかもゆっくり回る。これは気に入ってます。
で、最初の版は歯が重なってました
白状すると、最初は大小の歯車を「だいたいこの辺」に置いてただけです。止まってれば分からないんですが、回すとバレる。歯と歯が重なってすり抜けていくし、よく見ると歯の大きさも微妙に違う。機械として成立してない。
「確かな仕組みで、事業を動かす」って書いてあるロゴのすぐ横で、噛み合ってない歯車が回ってる。これはちょっと……ということで直しました。
歯車が噛み合う条件、4つ
調べると、歯車が噛み合う条件はきっちり決まってます。SVG で描くだけでも同じ。
- モジュール(歯の大きさ)を揃える — ピッチ円の直径 ÷ 歯数。ここが違うとそもそも噛み合わない
- 中心距離 = ピッチ円半径の足し算 — 「だいたいこの辺」ではなく、この距離ぴったりに置く
- 初期位相を合わせる — 中心同士を結んだ線の上で、片方の歯ともう片方の谷が向き合うように回しておく
- 回転比を歯数どおりにする — 18枚と 10枚なら回転周期は 18 : 10。ここをサボると、最初は噛み合ってても数秒後に重なり始める
トップの図だと大歯車が 48 秒で一周なので、小歯車は 48 × 10 ÷ 18 = 26.67 秒。CSS アニメーションの duration にそのまま入れてます。
座標は手で置かない
4つ全部を手作業で守るのは無理なので、座標はコードで出すことにしました。歯車の輪郭を作ってる関数はこれ。
/** 外歯車の輪郭パス(台形歯) */
export function gearPath(cx, cy, rOuter, rInner, teeth) {
const step = (Math.PI * 2) / teeth;
const pts = [];
for (let i = 0; i < teeth; i++) {
const a = i * step;
for (const [r, t] of [
[rInner, a],
[rOuter, a + step * 0.18],
[rOuter, a + step * 0.42],
[rInner, a + step * 0.6],
]) {
pts.push([cx + r * Math.cos(t), cy + r * Math.sin(t)]);
}
}
return "M" + pts.map((p) => p.join(" ")).join(" L") + " Z";
}
歯は 1 ステップのうち 0.18〜0.42 の区間、谷は 0.6〜1.0 の区間。なので歯の中心は 0.3 ステップ、谷の中心は 0.8 ステップのところにある。初期位相は「中心線の角度 − 0.3 ステップ」と「中心線の角度 + 180° − 0.8 ステップ」で向き合わせる、という寸法です。小歯車の中心も、大歯車の中心から「ピッチ円半径の和」だけ離れた点として計算してます。
遊星歯車、めんどくさい
一番手こずったのがサービスページの遊星歯車。太陽歯車のまわりを 3 つの遊星が自転しながら公転して、外側の内歯車とも噛み合うやつです。
内歯車の歯数 = 太陽の歯数 + 2 × 遊星の歯数、という制約はまだいいとして、遊星を等間隔に 3 つ並べるには(太陽の歯数 + 内歯車の歯数)が 3 で割り切れないといけないという組立条件があります。知らなかった。太陽 12T・遊星 9T・内歯車 30T なら (12 + 30) ÷ 3 = 14 で OK。ここに落ち着くまで何回か歯数を変えてます。
ついでにロゴの歯車も、塗りつぶしから図面と同じ線画に描き直しました。ロゴと図面が同じペンで描かれてる方が気持ちいいので。
おわり
歯が少し重なってても気付く人はまずいないと思います。でも自分が気になっちゃったので。