【備忘録】tan(atan2(値1,値2))活用した画面幅に合わせてzoomの値を変更するCSSについて

  • URLをコピーしました!

CSSの三角関数とzoomプロパティを組み合わせて、画面幅に合わせていろいろな物を画像のように拡縮できるというテクニックがXにあったので、その理屈を確認したメモです。

凄いテクニック: https://twitter.com/tak_dcxi/status/1890589347227087120

今回は凄いテクニックをベースに、若干値を変更した以下のデモをベースに説明を書きます

上記を参考にして作った実装デモ

目次

CSSの三角関数とzoomプロパティを組み合わせて、画面幅に合わせていろいろな物を画像のように拡縮できるコード

デモ

デモはデザインデータが1400px × 800px になっている状態でそこから取り出したパスの値を使って offset-path: path() で実装したものを、画面のサイズに合わせて拡大縮小したいデモです。

拡大縮小したい部分を以下の .zoom-wrapper で囲んでいます。

@property --zoom-factor {
    syntax: "<length>";
    inherits: false;
    initial-value: 0;
}

.zoom-wrapper{
    --min-viewport-width: 375px; /* viewportの最小値を下回ったら縮小をやめる */
    --max-viewport-width: 2560px; /* viewportの最大値を上回ったら拡大をやめる */
    --viewport-width: 1400px; /* デザイン上のサイズ */

    --zoom-factor: 100dvi;

    --zoom-value: clamp(
            tan(atan2(var(--min-viewport-width), var(--viewport-width))),
            tan(atan2(var(--zoom-factor), var(--viewport-width))),
            tan(atan2(var(--max-viewport-width), var(--viewport-width)))
    );

    zoom: var(--zoom-value);

    -webkit-text-size-adjust: initial; /* iOS Safariのバグ回避 */
}

tan(atan(値1, 値2))@propertyzoomの意味を確認

上記のコードのポイントは tan(atan(値1, 値2))@property を使って、画面幅に応じて zoom の値を変化させていること。

まずはそれらの関数やアットルールが何かを確認します。

atan2(y, x) : iOS15.4から

atan2() – CSS: Cascading Style Sheets | MDN

アークタンジェント2(ふたつの引数をとるアークタンジェント)の関数。

CSSのアークタンジェントについての、今回のポイント

  • atan2(100px, 5vw) のような異なる単位の数値を入れてもOK。
  • ふたつの値から角度を表すラジアン(rad)の数値が返る。

そもそものアークタンジェント2とは

アークタンジェント2の仕組みは「x,yの座標の値を入れると角度が出る」。

例えば、xが3、yが2のときは、atan2(2,3) となり33.69deg に相当する0.588rad が返ってくる

計算機:https://calculatorlib.com/ja/atan2-calculator?x=3&y=2

直角三角形の底辺=x、高さ=yで、底辺xに対して高さyの斜辺がなす角度の計算するatan() と基本は同じ。

atan2() の方が、xが負の値の時もうまく計算できるというような特徴がある。

参考:http://nomoreretake.net/2013/10/21/arctan2/
参考:https://ja.wikipedia.org/wiki/Atan2

tan() : iOS15.4から

https://developer.mozilla.org/en-US/docs/Web/CSS/tan

タンジェントの関数。

CSSのタンジェントについての、今回のポイント

  • tan(33.69deg) のように角度を渡すと、単位無しの数値が返る。

そもそもタンジェントとは

タンジェントは「角度を渡すと傾きが出る」。傾きは「変化の割合(比率)」。

例えば角度が33.69°のときtan(33.69deg) となり、2/3 にあたる 0.666665 が返ってくる。

計算機:https://calculatorlib.com/ja/tangent-calculator?angle=33.69&inputUnit=degrees

タンジェントは直角三角形の高さ/底辺で、それがそのまま斜辺の傾きの割合を示している。

@property : iOS16.4から

@property – CSS: カスケーディングスタイルシート | MDN

CSSカスタムプロパティについて、型の定義や継承するかどうかを設定をするアットルール。

@propertyについての、今回のポイント

Safariの場合にatan2() の計算を正しくさせるためにいったん @property で型定義したカスタムプロパティに100dviを格納して length であることを明示している。

※ Chromeの場合は前述のatan2()100dvi を直接渡しても計算できるらしい

zoom : iOSは昔から / Firefoxが2024年から

zoom – CSS: カスケーディングスタイルシート | MDN

要素の大きさを拡大縮小するプロパティ。

transform:scale()scale() と似ているが、見た目だけではなくてレイアウト計算に使う要素の大きさ自体が変わるのが特徴。

値としては 1 のような数値か 100% のようなパーセンテージが設定できる。

コード全体の確認

1. @property100dviatan2() に入れても壊れないようにする

@property --zoom-factor {
    syntax: "<length>";
    inherits: false;
    initial-value: 0;
}

2. 計算の基準に使う画面の幅を設定する

    --min-viewport-width: 375px; /* viewportの最小値を下回ったら縮小をやめる */
    --max-viewport-width: 2560px; /* viewportの最大値を上回ったら拡大をやめる */
    --viewport-width: 1400px; /* デザインのサイズ */

今回は以下の希望から設定値を決定しました。

  • 画面幅が375px未満の時、2560pxを超えるときは拡縮を止めたい
  • 画面幅が1400pxのときはzoomの値は1(100%の意味)にしたい

3. zoomに設定したい値の計算式を作る

    --zoom-factor: 100dvi;

    --zoom-value: clamp(
            tan(atan2(var(--min-viewport-width), var(--viewport-width))),
            tan(atan2(var(--zoom-factor), var(--viewport-width))),
            tan(atan2(var(--max-viewport-width), var(--viewport-width)))
    );

tan(atan2(値1, 値2)) とすると、結果としては 値1 / 値2(の単位無し)が得られるので、結果的に以下のような感じになります。

  • 最小値:375 / 1400 (およそ0.268)
  • 推奨値:画面の幅 / 1400(画面幅700のとき0.5 / 画面幅1400のとき1など)
  • 最大値:2560 / 1400(およそ1.829)

4. zoomプロパティに計算した値を渡す

    zoom: var(--zoom-value);

これで、画面の幅が700pxならzoom:0.5 、画面の幅が1400pxなら zoom:1 のように画面の幅に応じて値が変わる zoom プロパティの設定完了です。

※そのほか-webkit-text-size-adjust: initial; を入れることで別途iOS Safariのズーム関連のバグを回避しています。

【再確認】CSSの三角関数とzoomプロパティを組み合わせて、画面幅に合わせていろいろな物を画像のように拡縮できるコード

デモ

@property --zoom-factor {
    syntax: "<length>";
    inherits: false;
    initial-value: 0;
}

.zoom-wrapper{
    --min-viewport-width: 375px; /* viewportの最小値を下回ったら縮小をやめる */
    --max-viewport-width: 2560px; /* viewportの最大値を上回ったら拡大をやめる */
    --viewport-width: 1400px; /* デザイン上のサイズ */

    --zoom-factor: 100dvi;

    --zoom-value: clamp(
            tan(atan2(var(--min-viewport-width), var(--viewport-width))),
            tan(atan2(var(--zoom-factor), var(--viewport-width))),
            tan(atan2(var(--max-viewport-width), var(--viewport-width)))
    );

    zoom: var(--zoom-value);

    -webkit-text-size-adjust: initial; /* iOS Safariのバグ回避 */
}
よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

コメントは日本語で入力してください。(スパム対策)

CAPTCHA

目次