投稿日:2021年6月1日
LチカとはLEDをチカチカさせることです。
俗に、ラズパイ(Raspberry Pi) にLEDを装着しチカチカと発光させることを言います。
以前購入しようと思いましたが、その前にJavaScriptとブラウザを使って作ったことがありました。
ラズパイを期待した人、申し訳ございませんm(_ _)m
Qiitaの記事はこちら
▲今回、Reactで作ったものです。
▼全体のソースコードです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lチカ React</title>
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
</head>
<body style="margin:0; padding:0;">
<div id="root"></div>
<script type="text/babel">
class CircleObj extends React.Component {
constructor(props) {
super(props);
// ▼ このstateの設定でも動く。。。
let count = setInterval(() => {
this.setState((state) => ({
}));
}, 1000);
}
windowWidth = window.innerWidth; //ウィンドウの横の表示領域
windowHeight = window.innerHeight; //ウィンドウの横の表示領域
maxObjSize = this.windowWidth / 10; //オブジェクト最大サイズ 横の個数は10に固定
verticalQuantity = Math.floor(this.windowHeight / this.maxObjSize); //縦の個数
objQuantity = 10 * this.verticalQuantity; //ウィンドウ内のオブジェクトの総数
bgStyle = { //背景のスタイル
backgroundColor: "#000",
width: this.windowWidth + "px",
height: this.windowHeight + "px",
overflow: "hidden",
display: "flex",
flexWrap: "wrap",
alignContent: "space-between"
}
// ▼関数
zeroPad(zeroNum) { // ゼロパディング
var zeroNum = ('00' + zeroNum).slice(-2);
return zeroNum;
}
getRanNum(max, min) { // ランダムな数値を取得
var randomNum = Math.floor(Math.random() * (max - min + 1) + min);
return randomNum;
}
getRandomColor(rgbColor) { // ランダムなカラー値を取得
let colorArray = []; // RGB3色分の処理
for (let j = 0; j < 3; j++) {
colorArray.push(this.zeroPad(this.getRanNum(255, 0).toString(16).toUpperCase()));
}
for (let i = 0; i < this.objQuantity; i++) { // オブジェクトの個数分の処理
rgbColor = '#' + colorArray[0] + colorArray[1] + colorArray[2];
}
return rgbColor;
}
// ▼可変しないスタイル
objStyle = { //カラーとサイズ以外の円のスタイル
borderRadius: "50%",
filter: "blur(5px)",
transition: ".5s",
}
render() {
// ここにstateを配置すると全て同じ色になってしまう
return (
<div style={this.bgStyle}>
{(() => { // JSX内の繰り返しのための即時関数
const objs = []; // 配列を準備
for (let i = 0; i < this.objQuantity; i++) {
let objSize = this.getRanNum(this.maxObjSize, 2); //最大サイズ〜2pxの間でランダムな大きさを設定
let objColorStyle = { // オブジェクト分、異なる色、大きさにしたいのでここに配置
backgroundColor: this.getRandomColor(), //ランダムな色
width: objSize + "px",
height: objSize + "px",
margin: (this.maxObjSize - objSize) / 2 + 'px' //マージン、最大サイズ-オブジェサイズ/2で算出
}
objs.push(<div key={i} style={Object.assign({}, this.objStyle, objColorStyle)}></div>); //配列に追加
}
return objs;
})()}
</div >);
}
}
ReactDOM.render(<CircleObj />, document.getElementById('root'));
</script>
</body>
</html>
ではブロックごとに説明していきましょう。
class CircleObj extends React.Component {
constructor(props) {
super(props);
// ▼ このstateの設定でも動く。。。
let count = setInterval(() => {
this.setState((state) => ({
}));
}, 1000);
}
▲今回はclassコンポーネントで書きました。
state
の設定はこれだけでsetInterval
も動きます。
不思議ですね。。。
windowWidth = window.innerWidth; //ウィンドウの横の表示領域
windowHeight = window.innerHeight; //ウィンドウの横の表示領域
maxObjSize = this.windowWidth / 10; //オブジェクト最大サイズ 横の個数は10に固定
verticalQuantity = Math.floor(this.windowHeight / this.maxObjSize); //縦の個数
objQuantity = 10 * this.verticalQuantity; //ウィンドウ内のオブジェクトの総数
bgStyle = { //背景のスタイル
backgroundColor: "#000",
width: this.windowWidth + "px",
height: this.windowHeight + "px",
overflow: "hidden",
display: "flex",
flexWrap: "wrap",
alignContent: "space-beetween"
}
▲変数の設定。
コメントの表記通りです。
bgStyle
はLチカオブジェクトのラッパー(背景)のスタイルです。
zeroPad(zeroNum) { // ゼロパディング
let zeroNum = ('00' + zeroNum).slice(-2);
return zeroNum;
}
getRanNum(max, min) { // ランダムな数値を取得
let randomNum = Math.floor(Math.random() * (max - min + 1) + min);
return randomNum;
}
getRandomColor(rgbColor) { // ランダムなカラー値を取得
let colorArray = []; // RGB3色分の処理
for (let j = 0; j < 3; j++) {
colorArray.push(this.zeroPad(this.getRanNum(255, 0).toString(16).toUpperCase()));
}
for (let i = 0; i < this.objQuantity; i++) { // オブジェクトの個数分の処理
rgbColor = '#' + colorArray[0] + colorArray[1] + colorArray[2];
}
return rgbColor;
}
▲関数。
getRandomColor
関数内の1つ目のfor
文は、R、G、Bの各色を配列に格納しているので3回の繰り返し。
また、2つ目のfor
文はLチカオブジェの総数(objQuantity)分RGBを付与する処理をしています。
objStyle = { //カラー以外の円のスタイル
borderRadius: "50%",
filter: "blur(5px)",
transition: ".5s",
}
▲可変しないスタイルです。
カラー値とサイズは変動するので別途用意します。
render() {
// ここにstateを配置すると全て同じ色になってしまう
return (
<div style={this.bgStyle}>
{(() => { // JSX内の繰り返しのための即時関数
const objs = []; // 配列を準備
for (let i = 0; i < this.objQuantity; i++) {
let objSize = this.getRanNum(this.maxObjSize, 2); //最大サイズ〜2pxの間でランダムな大きさを設定
let objColorStyle = { // オブジェクト分、異なる色、大きさにしたいのでここに配置
backgroundColor: this.getRandomColor(), //ランダムな色
width: objSize + "px",
height: objSize + "px",
margin: (this.maxObjSize - objSize) / 2 + 'px' //マージン、最大サイズ-オブジェサイズ/2で算出
}
objs.push(<div key={i} style={Object.assign({}, this.objStyle, objColorStyle)}></div>); //配列に追加
}
return objs;
})()}
</div >);
}
}
ReactDOM.render(<CircleObj />, document.getElementById('root'));
▲最後にJSXです。
変数objSize
は、ランダム値を取得する関数getRanNum()
を使い、最大値maxObjSize
(ウィンドウサイズ/10)、最小値2pxで設定しています。
スタイルを格納するオブジェクトobjColorStyle
のbackgroundColor
は、関数this.getRandomColor()
で乱数を取得し、width
、height
は先ほどの変数objSize
から取得しています。
ここで大切なのがmargin
です。
margin
を設定しないと、▼このようにオブジェクトの大きさの変化で位置が動いてしまいます。
style={Object.assign({}, this.objStyle, objColorStyle)}
▲スタイルを2つ適用するのにObject.assign()
関数を使いました。
重複するオブジェクトは上書きされるので注意が必要です。
最後にReactDOM.render()
に渡しDOMに出力します。
Reactについて何となく分かってきたような気がしますが、まだまだ勉強不足です。
カラー値やサイズといった可変の値だけDOMが書き換わるようにしたつもりですが、検証ツールで確認したところ他のスタイルも同じ値で再度レンダリングしているように見えます。
▼YouTubeにアップしてみました。
さらに勉強したいと思います。
最後まで読んでくださりありがとうございました。