0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

円形スライダーをCSSの三角関数を使ってつくってみた

Posted at

画面収録-2023-01-16-5.51.22.gif

CSSで三角関数がサポートされたらしい

いつもお世話になっているColissさんより
2023年はCSSで三角関数「sin(), cos(), tan()」が主要ブラウザのすべてで使用できるようになるぞ!

という記事を見て円形スライダーができるんじゃないかなで試してみました。

前提

  • いまのところ三角関数はSafariとFirefoxのみサポート
  • 試しにSafariで動くようにする
  • input type="range"valueに応じて円回転するようにしてみる
  • ついでにvalueに応じて色を変えてみる

HTML(React)

React(tsx)使っていますがvalueを変更するのみです。

const [count, setCount] = useState(0);
return (
  <input 
    className="circular-slider"
    type="range"
    min={0}
    max={100}
    step={1}
    value={count}
    onChange={e => setCount(parseInt(e.target.value))}
  />
)

円形スライダーのベース

SASSです。

  • inputのベース部分
  • 数値表示
  • つまみとスライダー円形トラック部

の定義です。

すこし特殊なところとしては

  • カーソルを縦に動かすと変更

円形スライダーは縦動作の方が自然に思えたため、
カーソルや指を縦に動かすと変更されるようにしています。

  • Webkitにしか対応させていない

SafariなどWebkitの-webkit-slider-runnable-track-webkit-slider-thumb擬似要素を利用しています。
非標準です。

  • 数値表示を::after擬似要素にattr(value)使って表示
$circle-size: 96px; // スライダーサイズ
$circle-border-width: 8px; // スライダーボーダー幅
$thumb-size: 16px; // つまみのサイズ

.circular-slider,
.circular-slider[type="range"]::-webkit-slider-runnable-track,
.circular-slider[type="range"]::-webkit-slider-thumb {
  appearance: none; // 既存の表示をリセット
}

.circular-slider {
  position: relative;
  transform: rotate(-90deg); // 縦にする
  height: $circle-size;
  width: $circle-size;

  // 数値部分
  &::after {
    display: block;
    content: attr(value); // attrでvalue値を表示
    font-size: 1.5rem;
    font-weight: 900;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) rotate(90deg);
  }

  // スライダーの円形トラック部
  &::-webkit-slider-runnable-track {
    border: $circle-border-width solid;
    border-radius: 50%;
    height: $circle-size;
    width: $circle-size;
  }

  // ノブ部分
  &::-webkit-slider-thumb {
    background: white;
    border: 2px solid;
    border-radius: 50%;
    position: absolute;
    bottom: calc($circle-size / 2 - $thumb-size / 2); // 初期位置
    left: calc($circle-size / 2 - $thumb-size / 2); // 初期位置
    height: $thumb-size;
    width: $thumb-size;
  }
}

三角関数でノブの位置指定

今回やりたかったことです。

  • translate3dでノブ位置指定
  • SASSのforstepごとに指定

100個できてしまいますがcalcで動的な値は使えないっぽいのでやむをえない(解決策あれば知りたいです)

$pi: 3.14;
$c: 360; // 円周角
$r: calc(-1 * ($circle-size / 2 - $circle-border-width / 2)); // 半径
$min: 0;
$max: 100;

@for $value from $min through $max {
  $theta: calc($c / $max * $value);
  $x: calc($r * cos($theta * $pi / 180)); // x位置計算
  $y: calc($r * sin($theta * $pi / 180)); // y位置計算

  // ノブの位置と色
  .circular-slider::-webkit-slider-thumb {
    transform: translate3d($x, $y, 0); // 位置
    border-color: hsl(calc(0 + $value * 2),90,45); // 色
  }

  // 円形スライダーの色
  .circular-slider::-webkit-slider-runnable-track {
    border-color: hsl(calc(0 + $value * 2),90,45);
  }
}

全体

$circle-size: 96px;
$circle-border-width: 8px;
$thumb-size: 16px;

.circular-slider,
.circular-slider::-webkit-slider-runnable-track,
.circular-slider::-webkit-slider-thumb {
  appearance: none;
}

.circular-slider {
  position: relative;
  transform: rotate(-90deg);
  height: $circle-size;
  width: $circle-size;

  &::after {
    display: block;
    content: attr(value);
    font-size: 1.5rem;
    font-weight: 900;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) rotate(90deg);
  }

  &::-webkit-slider-runnable-track {
    border: $circle-border-width solid;
    border-radius: 50%;
    height: $circle-size;
    width: $circle-size;
  }

  &::-webkit-slider-thumb {
    background: white;
    border: 2px solid;
    border-radius: 50%;
    position: absolute;
    bottom: calc($circle-size / 2 - $thumb-size / 2);
    left: calc($circle-size / 2 - $thumb-size / 2);
    height: $thumb-size;
    width: $thumb-size;
  }
}

$pi: 3.14;
$c: 360;
$r: calc(-1 * ($circle-size / 2 - $circle-border-width / 2));
$min: 0;
$max: 100;

@for $value from $min through $max {
  $theta: calc($c / $max * $value);
  $x: calc($r * cos($theta * $pi / 180));
  $y: calc($r * sin($theta * $pi / 180));

  .circular-slider[value="#{$value}"]::-webkit-slider-thumb {
    transform: translate3d($x, $y, 0);
    border-color: hsl(calc(0 + $value * 2),90,45);
  }

  .circular-slider[value="#{$value}"]::-webkit-slider-runnable-track {
    border-color: hsl(calc(0 + $value * 2),90,45);
  }
}

// 0の場合はOFFっぽく見せる
.circular-slider[value="0"] {
  &::-webkit-slider-runnable-track {
    border-color: #ccc;
  }

  &::-webkit-slider-thumb {
    border-color: #ccc;
  }

  &::after {
    color: #ccc;
  }
}

正直なところ

円形スライダー目的なら
JavaScriptで同様のことをしたほうがいい

三角関数はアニメーションや特殊配置に役立ちそうで期待しています。

なにかのお役に立てば幸いです。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?