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の
for
でstep
ごとに指定
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で同様のことをしたほうがいい
三角関数はアニメーションや特殊配置に役立ちそうで期待しています。
なにかのお役に立てば幸いです。