- 投稿日:2021-06-20T23:03:52+09:00
Vue.jsでカスタムページネーションを作る
Vue.jsにはVue Pagination 2というpagination用のライブラリがありますが、仕組みを理解したいと思い自作しました。今回はそのカスタムページネーションについて記事にします。ソースコードはGitHubにて公開しています。 手っ取り早く実装したい方は上記ライブラリを使うことをお勧めします。時間があり、仕組みから理解したい人は読んでくれたら嬉しいです。 完成図 手の込んだことはしておらず、ページボタンを押すと表示するアイテム一覧が変わるだけの簡単な実装にしています。 対象読者 普段pagination実装はライブラリで済ませているけど、今こそ中身を理解したいと言う人 既存ライブラリのpaginationに満足しておらず、自作paginationを作りたいと思っている人 内容 方針 やっていることは決して難しいことではなく、表示したい部分のインデックスを取得して、それに対応する配列の一部分を取ってくるだけです。ページの変更は、表示したいインデックスを変更するだけで大丈夫です。 それでは実装に移りましょう。 実装 紙面の都合上、重要な部分のみ取り上げます。詳細に関してはGitHubより確認して頂ければと思います。 Vue.jsの基本はすでに理解している前提で話を進めますが、難しいことはしていないので基本を押さえている方であれば大丈夫だと思います。 ページネーションコンポーネントには次の2つを渡します。 1. アイテムを格納した配列 (items) 2. 1ページに表示したいアイテム数 (itemNumPerPage) App.vue <template> <div class="home"> <pagination :items="items" :itemNumPerPage="10" /> </div> </template> 今回はデモなので渡すアイテム配列は要素に文字列を持つ配列にしています。 続いて、ページネーションコンポーネントについて見ていきます。 Paginaiton.vue <template> <div class="pagination"> <div class="item-list"> <item v-for="(item, idx) in displayItems" :key="idx" :title="item" /> </div> <div class="page-btns"> <page-button @changePage="changePage" v-for="n in pageNum" :key="n" :pageNumber="n" :curPage="curPage" /> </div> </div> </template> <script> import Item from '@/components/Item.vue'; import PageButton from '@/components/PageButton.vue'; export default { components: { Item, PageButton }, props: { items: Array, itemNumPerPage: Number, }, data() { return { curPage: 1, // curPage starts from 1 pageNum: 0, // number os pages } }, created() { this.calcPageNum(); }, computed: { displayItems() { const startIdx = (this.curPage - 1) * this.itemNumPerPage; const endIdx = startIdx + this.itemNumPerPage; return this.items.slice(startIdx, endIdx); }, }, methods: { changePage(value) { this.curPage = value; }, calcPageNum() { this.pageNum = Math.ceil(this.items.length / this.itemNumPerPage); } } } </script> itemコンポーネントは単に渡した数字を表示しているだけなので省きます。 実際に画面に表示したいアイテム部分列を選んでいるのは算出プロパティdisplayItemsです。 displayItems() { const startIdx = (this.curPage - 1) * this.itemNumPerPage; const endIdx = startIdx + this.itemNumPerPage; return this.items.slice(startIdx, endIdx); } 表示したい配列部分の開始、終了インデックスを計算して、スライス関数を使って部分配列を作成して返しています(現在のページ番号を保存する変数curPageは画面に表示されているページ番号と揃えるために1スタートにしている点に注意)。 ページ数の計算はcalcPageNum関数で行っています。この関数はcreatedで呼び出しています。 calcPageNum() { this.pageNum = Math.ceil(this.items.length / this.itemNumPerPage); } Math.ceil()にしているのは、最終ページの表示アイテム数がitemNumPerPageより小さい場合でも表示できるようにするためです。 続いてPageButtonコンポーネントについて見ます。 PageButton.vue <template> <div class="page-btn"> <button @click="btnPressed" :class="{active: isCurrentPage}" >{{ pageNumber }} </button> </div> </template> <script> export default { props: { pageNumber: Number, curPage: Number }, computed: { isCurrentPage() { return this.pageNumber === this.curPage; } }, methods: { btnPressed() { this.$emit('changePage', this.pageNumber); } } } </script> propsでcurPageを受け取り、同じページ番号のボタンの背景色は変えています。 ボタンが押されたときに親コンポーネントに対してcurPageを変更するように知らせています。親コンポーネントであるpagination.vueではその知らせを受け取ったら、changePage関数を呼び出して新しいページ番号にcurPageを変更しています。 pagination.vue changePage(value) { this.curPage = value; } 以上で実装に関しては終わりです。 まとめ 本記事ではVue.jsを使ったカスタムページネーションの作成について解説しました。 時間ができたときに、一つ前、先のページに進むボタンなどを付け加えたいと思っています。 「もっとこうした方が良いよ」「こういうやり方もあるよ」というアドバイスがあれば、ぜひコメントを書いてくださると助かります。 参考資料 Pagination in Vanilla Javascript
- 投稿日:2021-06-20T22:36:00+09:00
JavaScriptでカウントダウンタイマーを作る
HTML + CSS + JavaScript でカウントダウンタイマーを作りました。ソースコードに直接記述した日時までカウントダウンします。 URL https://cordelia-sixth.github.io/countdown_timer_js/ ソースコード https://github.com/cordelia-sixth/countdown_timer_js ディレクトリ構成 app ├── index.html ├── script.js ├── style.css └── background.jpeg index.html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Countdown Timer</title> <link rel="stylesheet" href="style.css"> <script src="script.js" defer></script> </head> <body> <h1>Time left in 2021</h1> <div class="countdown-container"> <div class="countdown-elm"> <p class="time-text" id="days">0</p> <span>days</span> </div> <div class="countdown-elm"> <p class="time-text" id="hours">0</p> <span>hours</span> </div> <div class="countdown-elm"> <p class="time-text" id="mins">0</p> <span>mins</span> </div> <div class="countdown-elm"> <p class="time-text" id="seconds">0</p> <span>seconds</span> </div> </div> </body> </html> script.js const daysElm = document.getElementById('days'); const hoursElm = document.getElementById('hours'); const minsElm = document.getElementById('mins'); const secondsElm = document.getElementById('seconds'); // ここに好きな日時を記述する // 西暦 月 日 const target = '2022 1 1'; function countDown() { const targetDate = new Date(target); const currentDate = new Date(); const totalSeconds = (targetDate - currentDate) / 1000; const days = Math.floor(totalSeconds / 3600 / 24); const hours = Math.floor(totalSeconds / 3600) % 24; const mins = Math.floor(totalSeconds / 60) % 60; const seconds = Math.floor(totalSeconds % 60); daysElm.innerHTML = days; hoursElm.innerHTML = formatTime(hours); minsElm.innerHTML = formatTime(mins); secondsElm.innerHTML = formatTime(seconds); } function formatTime(time) { return time < 10 ? `0${time}` : time; } setInterval(countDown, 1000); countDown()がタイマー処理です。setInterval()により1秒ごとに呼び出されて時間が更新されます。 formatTime()で表示される時間を整形しています。時間、分、秒が10以下の場合は常にゼロを表示させてレイアウトが崩れるのを防いでいます。 style.css @import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro&display=swap'); * { box-sizing: border-box; } body { background-image: url(./background.jpeg); background-size: cover; background-position: center center; display: flex; flex-direction: column; align-items: center; min-height: 100vh; font-family: 'Source Sans Pro', sans-serif; margin: 0; } h1 { font-weight: normal; font-size: 4rem; margin-top: 5rem; } .countdown-container { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; } .time-text { font-weight: bold; font-size: 6rem; line-height: 1; margin: 1rem 2rem; } .countdown-elm { text-align: center; } .countdown-elm span { font-size: 1.2rem; } 終わりに 時間の計算方法がとても勉強になりました。こういった単位換算が苦手なので...。次は日時を入力できるフォームを追加したり、複数のタイマーを表示できるようにしてみたいですね! 読んでいただきありがとうございました!フィードバックしていただけたら嬉しいです! URL https://cordelia-sixth.github.io/countdown_timer_js/ ソースコード https://github.com/cordelia-sixth/countdown_timer_js 参考 リンク Github https://github.com/cordelia-sixth Products https://raindrop.io/cordelia/my-products-18715918 Qiita https://qiita.com/cordelia Twitter https://twitter.com/cordelia_sixth
- 投稿日:2021-06-20T18:48:01+09:00
[JavaScript] HTMLを取得するメソッド三種
はじめに HTMLを取得する三種のJavaScriptメソッドを紹介します。 HTMLの要素を取得する方法としてはid名を指定して取得する方法と、class名を指定して取得する方法と、セレクタ名を取得する方法が存在します。 それでは一つずつ紹介していきます!よろしくお願いします。 document.getElementById("id名") これは引数に渡したidを持つ要素を取得することができます。 //id名がhogeの要素を指定する場合 document.getElementById("hoge") この場合はhogeというid名のHTMLの要素を取得することができます。 document.getElementsByClassName("class名") 使い方はidを使って取得する方法と同じですが、このメソッドの名前のなかのElementsが複数形になっていることに気をつけましょう。 idとの使い分けとしては、HTMLの中で同じ名前のidは存在できないので取得する要素は一つだけになります。 しかし、classはHTMLで複数同じ名前が存在する可能性があるので、それら全ての要素を取得することができます。Elementsが複数形になっている理由も納得ですね! //class名がfugaの要素を指定する場合 document.getElementsByClassName("fuga") document.querySelectorAll("セレクタ名") セレクタ名はCSSでスタイルを適用するために指定している要素です。CSSでスタイル適応する時はid名や、class名、はたまたタグ名を指定しますよね。つまり、先ほど紹介したメソッドを使わなくても、これで完結するのです。 id名を指定する時は、id名の直前に . をつけます。class名は # をつけます。タグ名はそのままです。 //class名がfugaの要素を指定する場合 document.querySelectorAll(".fuga") //id名がhogeの要素を指定する場合 document.querySelectorAll("#hoge") //h1タグの要素を指定する場合 document.querySelectorAll("h1") おまけ ちなみに、document.querySelectorAll("セレクタ名")は合致する要素を全て取得してきますが、 document.querySelectorだと、合致する要素のうち一番はじめに見つかった要素を一つだけ取得します。 //id名,class名,タグ名の指定方法は、querySelectorAllメソッドと同じ document.querySelector("セレクタ名") 最後に これからオリジナルアプリにこの方法でフロントを実装したいところがありまして、おさらいしてみました。 JavaScriptこれから深めていきたいと思います!!!
- 投稿日:2021-06-20T12:20:08+09:00
フロントエンドで気をつけることをまとめる
あらすじ バックエンドがメイン開発な私がフロントエンドに苦闘した2週間を振り返る。HTML,CSS,JSの知識が多少なりともあってフレームワークだったらBootstrapが一番使ったことがあるって感じのエンジニアが、既存のデザインをいじったがレスポンシブ対応を完全にできなかった。そんな出来事から良くなかったことを反省して次に生かそうと思う。 VueのライブラリVuetifyを導入する策を講じた RailsオンリーのSSRでコツコツerbを使ってフロントエンドをつくってきたプロジェクトですが、レスポンシブ対応ができないんだったらVuetifyを入れてサーバーサイドとクライアントサイドで完全に分けちゃおうって思って、この策を講じることにした。vueをなぜ使おうかと思ったのは今後デザインの管理がしやすいのと、ライブラリが多様にあるのでレスポンシブやらSPAやらうまい具合に使ってUIめっちゃ向上するんじゃないのかと思ったからです。結論は、erbを使ったSSRでは、長時間かけないと切り替えられないなという結果でした。erb前提のroutingになっているのでAPI化にするのは作業工程が多すぎるなと感じて撤退しました。 そのまま突っ走って既存CSSで対応していこう メディアクエリが一応設けられているcssなのでこのまま細分化していって対応することもできると考えましたが、リソースがないのを考えるとbootstrapやらbulmaやらのフレームワークつかっちゃった方が得策だなと感じフレームワークを使うことになりました。 Bootstrapを使いましょうか 私自身がBootstrapを使ったことが一番多いので、他のフレームワークを使わずにBootstrapを使いますかと脳筋スタイルで進めようと思っていましたが、アメリカ人エンジニアさんがBootstrapは重いから軽量のレスポンシブ対応のみできるフレームワークを使おうよとなりBulmaへ。 Bulmaで決まりだ 結果的にBulmaになりました。実際に実装してもらったのはアメリカ人エンジニアさんなのですが、ボタンもBootstrapから卒業してレスポンシブ対応の方法も簡潔で違ったフレームワークを使うとデフォルト感がなくなるので良いですね。どうしてもBootstrap使うと見慣れた感を感じるユーザーがいると思うのでデザインに手を抜いているなとか思われる可能性考えたら良い到着点だったのかなと思います。本当、試行錯誤は長い時間かけたらまずいですが、早いスパンで繰り返すのは大切だなと改めて感じました。 まとめ フロントエンドに時間をかけるリソースがない開発は、用途にあったフレームワークを決めるのは大切。 vueやらreactを使った方が間違いなくUIは改善できると思う。 話し合いは大切。 技術選定はなるべく早く。切り替えるのは時間がもったいない。
- 投稿日:2021-06-20T12:20:08+09:00
フロントエンドの技術選定に時間がかかった話
あらすじ バックエンドがメイン開発な私がフロントエンドに苦闘した2週間を振り返る。HTML,CSS,JSの知識が多少なりともあってフレームワークだったらBootstrapが一番使ったことがあるって感じのエンジニアが、既存のデザインをいじったがレスポンシブ対応を完全にできなかった。そんな出来事から良くなかったことを反省して次に生かそうと思う。 VueのライブラリVuetifyを導入する策を講じた RailsオンリーのSSRでコツコツerbを使ってフロントエンドをつくってきたプロジェクトですが、レスポンシブ対応ができないんだったらVuetifyを入れてサーバーサイドとクライアントサイドで完全に分けちゃおうって思って、この策を講じることにした。vueをなぜ使おうかと思ったのは今後デザインの管理がしやすいのと、ライブラリが多様にあるのでレスポンシブやらSPAやらうまい具合に使ってUIめっちゃ向上するんじゃないのかと思ったからです。結論は、erbを使ったSSRでは、長時間かけないと切り替えられないなという結果でした。erb前提のroutingになっているのでAPI化にするのは作業工程が多すぎるなと感じて撤退しました。 そのまま突っ走って既存CSSで対応していこう メディアクエリが一応設けられているcssなのでこのまま細分化していって対応することもできると考えましたが、リソースがないのを考えるとbootstrapやらbulmaやらのフレームワークつかっちゃった方が得策だなと感じフレームワークを使うことになりました。 Bootstrapを使いましょうか 私自身がBootstrapを使ったことが一番多いので、他のフレームワークを使わずにBootstrapを使いますかと脳筋スタイルで進めようと思っていましたが、アメリカ人エンジニアさんがBootstrapは重いから軽量のレスポンシブ対応のみできるフレームワークを使おうよとなりBulmaへ。 Bulmaで決まりだ 結果的にBulmaになりました。実際に実装してもらったのはアメリカ人エンジニアさんなのですが、ボタンもBootstrapから卒業してレスポンシブ対応の方法も簡潔で違ったフレームワークを使うとデフォルト感がなくなるので良いですね。どうしてもBootstrap使うと見慣れた感を感じるユーザーがいると思うのでデザインに手を抜いているなとか思われる可能性考えたら良い到着点だったのかなと思います。本当、試行錯誤は長い時間かけたらまずいですが、早いスパンで繰り返すのは大切だなと改めて感じました。 まとめ フロントエンドに時間をかけるリソースがない開発は、用途にあったフレームワークを決めるのは大切。 vueやらreactを使った方が間違いなくUIは改善できると思う。 話し合いは大切。 技術選定はなるべく早く。切り替えるのは時間がもったいない。
- 投稿日:2021-06-20T11:14:53+09:00
関数コンポーネントで学ぶReact公式チュートリアル
関数コンポーネント版React公式チュートリアル Reactの公式チュートリアルではクラスコンポーネントが使われていますが、最近は関数コンポーネントを利用することがほとんどだと思います。折角初心者の方に教えるのであれば、使えるものを教えたいと思ったので、公式チュートリアルを一通り関数コンポーネントを使った形に書き換えてみました。 以下にはコードと関数コンポーネントで書く際の注意点のみ記述します。 コードの詳しい解説については、公式の方を確認してください。 スターターコード サンプルコードに関してはCodeSandboxに用意しました。以降で操作するファイルは、src/index.jsになります。 CodeSandbox 描画したいJSXを、クラスコンポーネントではrenderメソッドに記述しましたが、関数コンポーネントでは返り値とするのでreturn文のなかに記述します。 また、以下のコードでは関数の定義は、基本的にアロー関数を変数に代入する形でおこないます。 const コンポーネント名=(props)=>{ /* 処理 */ return <Component value={props.value}/> } この場合、定義順などに気をつける必要がありますが、同名コンポーネントの定義を防止できるなど利点もあるので、この形を利用していきます。 JavaScriptの関数定義に興味のある方は、@raccy様の記事を参考にしてみてください。 ゲームを完成させる データをProps経由で渡す BoardのrenderSqueareを以下のように書きえましょう。 const renderSquare = (i) => <Square value={i} />; こうすることでSquareの中で、引数iの値をprops.valueとして扱うことができます。実際にSquareを書き換えてprops.valueの値を反映させてみましょう。 const Square = (props) => { return <button className="square">{props.value}</button>; }; 各マスに数字が表示されるようになったと思います。 インタラクティブなコンポーネントを作る クラスコンポーネントではコンストラクタのthis.stateでまとめてステートを管理しますが、関数コンポーネントではHook(今回は'useState'関数)と言われるものを利用して一つ一つステートを定義します。 const [state, setState]=useState(初期値); 変数名(state)は何でもいいですが、setStateの部分は必ずset+変数名(キャメルケース)にしてください)。 ステートの値が使いたい場合は、普通の変数と同じようにstateを使いましょう。 しかし、ステートの値を変更する際は直接代入するのではなく、各ステートに対応した関数を使う点には注意してください。上記のコードを用いると以下のようになります。 //Bad state=1; //これだとDOMが更新されない //そもそもconstで定義しているので代入はできませんが・・・ //Good setState(1); //ちゃんとDOMが更新されます Squareを書き換えると以下のようになります。 const Square = (props) => { const [value, setValue] = useState(""); return ( <button className="square" onClick={() => setValue("X")}> {value} </button> ); }; State のリフトアップ これについては、ステートの定義方法が違うだけでクラスコンポーネントと同じ手法を用います。以下に変更結果を示します。 完成品 const Square = (props) => { return ( <button className="square" onClick={props.onClick}> {props.value} </button> ); }; const Board = (props) => { const [squares, setSquares] = useState(Array(9).fill(null)); const handleClick = (i) => { const newSquares = squares.slice(); newSquares[i] = "X"; setSquares(newSquares); }; const renderSquare = (i) => ( <Square value={squares[i]} onClick={() => { handleClick(i); }} /> ); const status = "Next player: X"; return ( <div> <div className="status">{status}</div> <div className="board-row"> {renderSquare(0)} {renderSquare(1)} {renderSquare(2)} </div> <div className="board-row"> {renderSquare(3)} {renderSquare(4)} {renderSquare(5)} </div> <div className="board-row"> {renderSquare(6)} {renderSquare(7)} {renderSquare(8)} </div> </div> ); }; 手番の処理 一部公式とは違う手法でやっていますが、基本同じです。 (異なる点:テンプレート文字列) const Board = (props) => { const [squares, setSquares] = useState(Array(9).fill(null)); const [xIsNext, setXIsNext] = useState(true); const handleClick = (i) => { const newSquares = squares.slice(); newSquares[i] = xIsNext ? "X" : "O"; setSquares(newSquares); setXIsNext(!xIsNext); }; const renderSquare = (i) => ( <Square value={squares[i]} onClick={() => { handleClick(i); }} /> ); const status = `Next player: ${xIsNext ? "X" : "O"}`; //以下変更なし ゲーム勝者の判定 Board内で関数を定義する、引き分けを追加するなど変更点はありますが大体同じです。 const Board = (props) => { const [squares, setSquares] = useState(Array(9).fill(null)); const [xIsNext, setXIsNext] = useState(true); const handleClick = (i) => { const newSquares = squares.slice(); if (calculateWinner(newSquares) || newSquares[i]) { return; } newSquares[i] = xIsNext ? "X" : "O"; setSquares(newSquares); setXIsNext(!xIsNext); }; const renderSquare = (i) => ( <Square value={squares[i]} onClick={() => { handleClick(i); }} /> ); const calculateWinner = (squares) => { const lines = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6] ]; for (let i = 0; i < lines.length; i++) { const [a, b, c] = lines[i]; if ( squares[a] && squares[a] === squares[b] && squares[a] === squares[c] ) { return squares[a]; } } return null; }; const status = () => { const winner = calculateWinner(squares); if (winner) { return "Winner: " + winner; } else if (squares.reduce((x, y) => x && y)) { return "Draw"; } else { return `Next player: ${xIsNext ? "X" : "O"}`; } }; return ( <div> <div className="status">{status()}</div> <div className="board-row"> {renderSquare(0)} {renderSquare(1)} {renderSquare(2)} </div> <div className="board-row"> {renderSquare(3)} {renderSquare(4)} {renderSquare(5)} </div> <div className="board-row"> {renderSquare(6)} {renderSquare(7)} {renderSquare(8)} </div> </div> ); }; タイムトラベル機能の追加 State のリフトアップ、再び historyステートはオブジェクトのリストではなく、2次元リストに変更しました。 その他定義順や記法が一部異なります。 const Board = (props) => { const renderSquare = (i) => ( <Square value={props.squares[i]} onClick={() => { props.onClick(i); }} /> ); return ( <div> <div className="board-row"> {renderSquare(0)} {renderSquare(1)} {renderSquare(2)} </div> <div className="board-row"> {renderSquare(3)} {renderSquare(4)} {renderSquare(5)} </div> <div className="board-row"> {renderSquare(6)} {renderSquare(7)} {renderSquare(8)} </div> </div> ); }; const Game = (props) => { const initSquares = Array(9).fill(null); const [history, setHistory] = useState([initSquares]); const [xIsNext, setXIsNext] = useState(true); const calculateWinner = (squares) => { const lines = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6] ]; for (let i = 0; i < lines.length; i++) { const [a, b, c] = lines[i]; if ( squares[a] && squares[a] === squares[b] && squares[a] === squares[c] ) { return squares[a]; } } return null; }; const status = (squares) => { const winner = calculateWinner(squares); if (winner) { return "Winner: " + winner; } else if (squares.reduce((x, y) => x && y)) { return "Draw"; } else { return `Next player: ${xIsNext ? "X" : "O"}`; } }; const current = history.slice(-1)[0]; const winner = calculateWinner(current); const handleClick = (i) => { const squares = current.slice(); if (winner || squares[i]) return; squares[i] = xIsNext ? "X" : "O"; setHistory([...history, squares]); setXIsNext(!xIsNext); }; return ( <div className="game"> <div className="game-board"> <Board squares={current} onClick={handleClick} /> </div> <div className="game-info"> <div>{status(current)}</div> <ol>{/* TODO */}</ol> </div> </div> ); }; 過去の着手の表示&Key を選ぶ 関数の定義順や場所に注意したこと以外に変更はありません。 これがチュートリアルの最後であるため、全文載せておきます。 import React, { useState } from "react"; import ReactDOM from "react-dom"; import "./index.css"; const Square = (props) => { return ( <button className="square" onClick={props.onClick}> {props.value} </button> ); }; const Board = (props) => { const renderSquare = (i) => ( <Square value={props.squares[i]} onClick={() => { props.onClick(i); }} /> ); return ( <div> <div className="board-row"> {renderSquare(0)} {renderSquare(1)} {renderSquare(2)} </div> <div className="board-row"> {renderSquare(3)} {renderSquare(4)} {renderSquare(5)} </div> <div className="board-row"> {renderSquare(6)} {renderSquare(7)} {renderSquare(8)} </div> </div> ); }; const Game = (props) => { const initSquares = Array(9).fill(null); const [history, setHistory] = useState([initSquares]); const [xIsNext, setXIsNext] = useState(true); const [stepNumber, setStepNumber] = useState(0); const calculateWinner = (squares) => { const lines = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6] ]; for (let i = 0; i < lines.length; i++) { const [a, b, c] = lines[i]; if ( squares[a] && squares[a] === squares[b] && squares[a] === squares[c] ) { return squares[a]; } } return null; }; const status = (squares) => { const winner = calculateWinner(squares); if (winner) { return "Winner: " + winner; } else if (squares.reduce((x, y) => x && y)) { return "Draw"; } else { return `Next player: ${xIsNext ? "X" : "O"}`; } }; const current = history[stepNumber]; const winner = calculateWinner(current); const handleClick = (i) => { const slicedHistory = history.slice(0, stepNumber + 1); const squares = current.slice(); if (winner || squares[i]) return; squares[i] = xIsNext ? "X" : "O"; setHistory([...slicedHistory, squares]); setXIsNext(!xIsNext); setStepNumber(slicedHistory.length); }; const jumpTo = (step) => { setStepNumber(step); setXIsNext(step % 2 === 0); }; const moves = history.map((step, move) => { const desc = move ? "Go to move #" + move : "Go to game start"; return ( <li key={move}> <button onClick={() => jumpTo(move)}>{desc}</button> </li> ); }); return ( <div className="game"> <div className="game-board"> <Board squares={current} onClick={handleClick} /> </div> <div className="game-info"> <div>{status(current)}</div> <ol>{moves}</ol> </div> </div> ); }; // ======================================== ReactDOM.render(<Game />, document.getElementById("root")); まとめ 以上が関数コンポーネント化させたReact公式チュートリアルになります。関数内で関数を定義したり、クロージャーを用いていたりと見慣れない書き方かもあるかもしれませんが、Reactや関数型プログラミングではよく見る光景なので慣れておくといいと思います。 一部筆者の好みで改変したため、こうした方が公式に近い、より良い書き方があるという方は、コメントなどでアドバイスをいただけると幸いです。 Reactは非常に便利なライブラリですので、これを活用してどんどんアプリケーションを作っていきましょう!
- 投稿日:2021-06-20T10:38:19+09:00
HTMLについて
HTMLについて 皆さんこんにちは!駆け出しエンジニアのコジマです! 本日は、HTMLについてお話しして行きたいと思います。 そもそもHTMLの正式名称は? まずは、HTMLについて簡単に解説して行きますね! ハイパーテキスト・マークアップ・ランゲージ (Hyper Text Markup Language)の略称になります。 最初自分は、いきなり魔法の呪文みたいな正式名称を 聞いて、びっくりしてしまいました (笑) 役割について 基本的に、WEBページに文字を出力してくれる役割を 担当してくれているのがHTMLになります! ちなみに文字に色を付けたり、大きくしたりする担当は、 CSSが担当しています! HTMLだけだと白黒テレビ状態ですがCSSを使うと、 カラーテレビみたいなると認識してます(笑)
- 投稿日:2021-06-20T09:54:04+09:00
jQueryを使った企業の宣伝サンプルWebページ
jQueryを使った企業の宣伝サンプルWebページを作成いたしました。 <!DOCTYPE html> <!-- 作成者 乃木坂好きのITエンジニア --> <!-- 作成日 2021/6/20 --> <html lang="ja"> <head> <meta charset="utf-8"> <title>アニメーション2</title> </head> <script src="jquery.js"></script> <script> $(function(){ $('h1').click(function(){ $('h1').css('color','blue'); }); }); $(function(){ $('h2').click(function(){ $('h2').css('background-color','yellow'); }); }); $(function(){ $('h3').click(function(){ $('h3').css('color','black'); $('h3').css('background-color','aqua'); }); }); $(function(){ $('h5').click(function(){ $('h5').css('color','black'); $('h5').css('background-color','lightgreen'); }); }); $(function(){ for(var num=0;num<10;num++){ $('h6').fadeOut(); $('h6').fadeIn(); } }); function fuori(){ let i = 0; while (i< 1){ window.open('http://www.fuoriclasse2.com','flora','width=480,height=360'); i++; } } </script> <style> .euro2020 { color:red; font-size:80px; text-align:center; padding:120px; } .fra { color:black; font-size:70px; text-align: center; padding:100px; } .esp { color:lawngreen; font-size:50px; text-align: center; color:darkred; padding: 100px; } .por { background-color:lightgreen; text-align: center; color:darkred; font-size:50px; padding: 100px; } .freestyle1 { background-color:floralwhite; text-align: center; color:mediumvioletred; font-size:50px; padding: 100px; } .fuori { background-color:lightgreen; text-align: center; border: 1px solid #b7a077; border-radius: 5px; color:deeppink; font-size:40px; padding: 50px; float:right; } #aono1 { font-size:50px; color:red; background-color:aquamarine; text-align: center; padding:200px; } .aono2 { font-size:10px; color:blue; } </style> <body> <h1 class="euro2020">EURO2020開催中</h1> <h2 class="fra">フランスがやらかした</h2> <h3 class="esp" >スペインもやらかした</h3> <h4 class="por">ポルトガル・・・・</h4> <h5 id="aono1" onLoad="tm()"><img src="aono.jpg" alt="ダークヒーロー青野" width="800",height="600" ><br><br>フリースタイル社長の<span>青野豪淑</span>です</h5> <h6 class="freestyle1">フリースタイルはサッカーゲームを作ります。<br>fuori-classeの皆さん期待してください</h6> <br> <a class="fuori" onclick=fuori()>fuori-classe</a> <br> <br> <br> <br> <br> <br> <br> </body> <footer> <small class="aono2">© 青野豪淑</small> </footer> jQueryの機能を使うとタグの文字を変えたり、タグ部分の背景色を変えたり、for文で文字の表示、非表示が出来ます。動的にWebページが出来て便利です。
- 投稿日:2021-06-20T09:41:04+09:00
CSSだけでうちわを作る
どうも7noteです。毎日暑い日が続くからCSSでうちわを作って涼みたい。 毎日毎日汗を拭いながら働く日々。 そんな辛い日々を癒してくれるうちわがあればいいなと。 CSSで作ってしまいましょう。 ソース index.html <div class="uchiwa"> <div class="mochite"></div> </div> style.css .uchiwa { width: 200px; height: 200px; background: #D9E3EC; /* background: url(uchiwa.png) center center / contain; */ /* 画像うちわ用 */ /* border: 1px solid #ccc; */ border-radius: 50%; position: relative; } .mochite { content: ''; width: 75%; height: 75%; background: #fff; border-radius: 50%; overflow: hidden; display: inline-block; position: absolute; bottom: -50%; left: 0; right: 0; margin: auto; } .mochite::before { content: ""; width: 80%; height: 70%; display: inline-block; background-image: linear-gradient(90deg, #fff 25%, #DDB76D 25%, #DDB76D 50%, #fff 50%, #fff 75%,#DDB76D 75%, #DDB76D); background-size: 4px 4px; border-bottom: solid 2px #DDB76D; border-radius: 50%; transform: perspective(.6em) rotateX(-380deg); transform-origin: bottom; position: absolute; top: -40%; left: 0; right: 0; margin: auto; } .mochite::after { content: ''; width: 9%; height: 50%; background: #DDB76D; display: inline-block; position: absolute; bottom: 20%; left: 0; right: 0; margin: auto; } 解説 丸に白い丸を重ねて紙の部分を作成。 そこに持ち手をつければ完成です。 紙の部分は好きな写真をはめ込んで推しうちわを作ったりもできますよ。 骨組みの部分はかなり無理矢理作ってるので解説は省きます。。。 まとめ 「結論」 CSSでうちわを作っても涼しくはならない。 けどCSSの練習にはなるかも。クーラー最高! おそまつ! ~ Qiitaで毎日投稿中!! ~ 【初心者向け】WEB制作のちょいテク詰め合わせ
- 投稿日:2021-06-20T05:55:35+09:00
初心者がWEBデザインするなら、STUDIO !(ヘッダー編)
今回はwebサイト制作で挫折しまくり初心者の私が、見つけた救世主"STUDIO"を使用して レスポンシブ対応からSEO対策まで備えたウェブサイトを作成します! しかも全て、、、、、、、ノーコードで!!!最高すぎませんか? STUDIOは日本に本社を構えるSTUDIO株式会社が2018年4月に正式リリースした国産のホームページ制作ツールです。2020年6月にはCMS機能も追加されました! 公式サイトSTUDIOで登録を行い基本無料で作成から公開までできる。 また有料コンテンツでは追加機能や独自ドメイン接続、外部アプリ連携などもできます。 STUDIOについてメリット、デメリットを説明します。 メリット ・ノーコードでデザインができる ・テンプレだけでなく自由度の高いデザインができる ・動きのあるデザインも簡単に作れ、細かく設定できる ・デザイン⇨公開までが簡単 ・レスポンシブ対応が簡単にできる ・チュートリアル動画も無料で充実 デメリット ・html、cssの必要最低限の知識がいる ・STUDIOに実装されていない機能は使えない 今回はheader部分を作成しレスポンシブ対応にさせました。モバイル対応のところは憧れのハンバーガーメニューを実装しました。STUDIOを使ってわずか3時間程で完成しました。 操作方法に慣れるまで大変かもしれませんが、それでも圧倒的に目で確認しながらレイアウトできると、楽しいですし分かりやすいと思います。 ではheaderの作成方法について ①、左作業スペースにあるメニューからボックスを選ぶ初期値は ②、右側の作業メニューでタブの種類変更ができるので、headerに変更。大きさは適当に横100%、縦70pxとかに始めはしてます。 ③、まず私は企業のロゴを配置したかったのでボックスからimageを選択 右クリックでimageボックスに入れる画像を選ぶ。アップロードした画像を指定 ④、headerのボックスにimageを入れます ※この時 imageボックスの横幅、縦幅がhederボックスより大きいと入らないので注意! ⑤、上記と同じような手順でメニューバーも作って行きます。テキストをlistボックスに入れて 一つ目の文字サイズ、文字間を調節したらコピーアンドペーストで必要項目分作ると時短です。 ⑥、メニュー項目ができたら、nuvボックスを作って中に入れて行きます。 要素を入れたら横並びに指定しましょう。padding等間隔調整もここでします。上部メニューに項目がありますので各要素ごとに行ってください。 ⑦、nuvボックスをheaderボックスに入れます。あとはボックス外側にある整列ようタブで調整するだけです。 ⑧、完成です。 ちなみに私が作ったのはこちら(PC用header) (モバイル用header)ハンバーガーメニューで メニューを開く動きからシャドーなど簡単にボタンで操作できます。 上記説明で分かりずらい方もいらっしゃると思うのでまずは自分でチュートリアルも見ながら、STUDIOを使ってみることをオススメします!ハンバーガーメニューはチュートリアルの項目にもありますのでぜひ作ってみてください! では、また作成次第更新して行きます
- 投稿日:2021-06-20T03:47:50+09:00
【HTML】HTMLでGoogleMap地図を埋め込み表示する
GoogleMap地図を埋め込み、ブラウザで表示する。 手順 1.表示させたい場所をGoogleMapで検索します。(例:東京タワー) 2.共有をクリックします。 3.画面中央に共有が出てくる為、地図を埋め込むをクリックします。 4.HTMLをコピーをクリックし、コードをコピーします。 5.コピーしたコードをHTMLファイルに貼り付けます。 ※デフォルトでMapの大きさは以下のようになっています。 小:width="400" height="300" 中:width="600" height="450" 大:width="800" height="600" 6.ブラウザで確認するとGoogleMap地図が表示されます。 まとめ 指定場所のGoogleMap地図を埋め込み表示することができました。