Sandbox

学習記録や試作したものを掲載しています

All(18)

Three.js

Blender で作成した 3D モデルをブラウザ上で動かす

Blender で作成した 3D モデルをブラウザ上で動かす

Blender で作成した 3D モデルを Three.js を用いてブラウザ上で読み込み、インタラクションを加えて動かす練習を行った。

Demo: https://koji014-laptop.vercel.app

  • 天板部(液晶ディスプレイを除く)をクリックすると、PC が開閉する
  • 電源ボタンをクリックすると、PC の電源が ON になる

参考

Blender

Blender に入門する

Blender に入門する

Web Designing 2025年6月号 p.36 ~ p.49 の内容を参考に Blender の学習を行った。
基本的な操作方法や、モデリングからレンダリングまでの一連の流れを把握することができた。

以下、モデリングしたラップトップのデモ動画。

参考

JavaScript

非同期遷移を行うためのクラスを自作する

非同期遷移を行うためのクラスを自作する

非同期遷移を行うための Pjax クラスを自作した。
ブラウザバック・フォワードへの対応や、ページ遷移前のアンマウント処理、遷移後のマウント処理をカスタマイズできるように実装しており、メモリリークの防止にも配慮した。

以下、上から順に(1)フェードによる遷移、(2)CSS mask による遷移、(3)SVG animate による遷移。

WebGL

WebGL オブジェクトと DOM 要素の位置同期ずれを防ぐ

WebGL オブジェクトと DOM 要素の位置同期ずれを防ぐ

WebGL オブジェクトと DOM 要素の位置を同期した際、モバイルデバイスのネイティブスクロールで両者の位置がずれることがある。2025年4月4日に Lusion が公表した投稿によると、Canvas を ページコンテンツに追従させ、Canvas の位置を translateY で補正することで、このずれを解消できるという。この効果を確認すべく、デモを作成した。なお、この方法を理解する上で、長谷川巧さん(@_unshift)の図解を大いに参考にした。

Demo: https://koji014-webgl-scroll-sync.vercel.app

以下、上から順に(1)固定していない状態、(2)固定して Padding をつけていない状態、(3)固定して Padding をつけた状態。(2)の Padding をつけない場合、上へ戻ろうとする際に Canvas が見切れている(画像の表示が欠けている)ことがわかる。(3)では Padding をつけることで、これが改善されている。

参考

WebGL

非同期遷移を介した DOM と板ポリゴンの再同期

非同期遷移を介した DOM と板ポリゴンの再同期

同期していた DOM と板ポリゴンの関係を非同期遷移前に破棄し、遷移後に再び同期する。

WebGL

DOM と板ポリゴンを同期する

DOM と板ポリゴンを同期する

WebGL School プラスワン講義回で Taro Yoshimura さん(@ysmrt6)が解説した内容を参考に、Three.js を使わずに実装した。

Demo: https://koji014-dom-gl-sync.vercel.app

参考

  • WebGL School 2024 プラスワン講義回 Taro Yoshimura さんの Three.js を用いた実装

JavaScript

スクロール量に応じた操作をするためのクラスを自作する

スクロール量に応じた操作をするためのクラスを自作する

GSAP の ScrollTrigger の仕組みを理解するため、同じような挙動をする ScrollTrigger クラスを作成した。

Demo: https://koji014-scroll-trigger.vercel.app

使用例

const box = document.querySelector('.box');

const trigger = new ScrollTrigger({
    trigger: '#trigger',
    start: '10% 10%',
    end: '70% 70%',
    markers: true,
    onEnter: () => console.log('🍎onEnter'),
    onLeave: () => console.log('🍐onLeave'),
    onEnterBack: () => console.log('🍎onEnterBack'),
    onLeaveBack: () => console.log('🍐onLeaveBack'),
    onToggle: () => console.log('🍇onToggle'),
    onUpdate: (self) => {
        const breakPoints = [0, 0.4, 0.8, 1];
        const lastIndex = breakPoints.length - 1;

        const normalizedProgress = breakPoints.map((bp, i, arr) => {
            if (i === 0) return 1.0;
            const prev = arr[i - 1];
            return Math.min(Math.max(0, (self.progress - prev) / (bp - prev)), 1);
        });

        const transform = {
            translateX: 200,
            translateY: 800,
            rotate: 360,
        };

        if (self.progress < breakPoints[1]) {
            box.style.transform = `
                translateY(${transform.translateY * normalizedProgress[1]}px)
                rotate(${transform.rotate * normalizedProgress[1]}deg)
            `;
        } else if (self.progress < breakPoints[2]) {
            box.style.transform = `
                translateX(${transform.translateX * normalizedProgress[2]}px)
                translateY(${transform.translateY}px)
                rotate(${transform.rotate}deg)
            `;
        } else {
            box.style.transform = `
                translateX(${transform.translateX}px)
                translateY(${transform.translateY}px)
                rotate(${transform.rotate}deg)
            `;
            box.style.backgroundColor = `rgb(
                ${Math.round(255 * (1 - normalizedProgress[lastIndex]))} 0 255 / 0.5
            )`;
        }
    },
});

JavaScript

カルーセルを自作する

カルーセルを自作する

Demo

https://koji014-carousel.vercel.app

const targetSelector = '.my-carousel';

new Carousel(targetSelector, {
    isLoop: true,
    autoInterval: 4000,
    autoPlay: true,
    showIndicators: true,
    label: '秋冬の景色',
    enableLiveRegion: true,
 });
// 共通設定(初期設定)
.carousel {
     --_slidesPerView: 1; // 1ビューあたりのスライド数
     --_slidesPerGroup: 1;  // 1度のスワイプで何枚分移動させるか
     --_spaceBetween: 0rem;  // スライド間の距離(単位:rem)
     --_speed: 0.4s; // スライドの遷移時間(単位: s)
     --_inner: 3.6rem; // スライド両脇の余白
}

// 個別設定 
.my-carousel {
     --_slidesPerView: 1;
     --_slidesPerGroup: 1;
     --_spaceBetween: 1rem;      

     @include gl.mq('md') {    
          --_slidesPerView: 2.5;
          --_slidesPerGroup: 2;
          --_spaceBetween: 2rem;
     } 
}

実装機能

  • ナビゲーションボタン(前へ・次へ)
    • 活性・非活性制御
  • インジケータ
  • ループ機能
  • 自動再生機能
    • 停止ボタン
    • スライドをマウスオーバーすると自動再生を停止
  • タブレット操作時のドラッグ対応
  • アクセシビリティ
    • aria-属性の自動付与
    • ライブリージョン

参考

関連

Next.js

Next.js で基本的な UI 機能の実装練習をする

Next.js で基本的な UI 機能の実装練習をする

Next.js と TypeScript のアウトプットを目的として、基本的な UI 機能をスクラッチした。
同時に、Jest を使用した単体テストを書く練習を実施した。Webサイトという文脈でどれほどテストが重要視されているか認識できていないが、aria-属性の変化などを目視で確認せず済むことに利点を感じた。

参考

関連

CI/CD

microCMS の Webhook と GitHub Actions を連携してビルドとデプロイを自動化する

microCMS の Webhook と GitHub Actions を連携してビルドとデプロイを自動化する

microCMS の Webhook と GitHub Actions を連携し、ビルドと XServer へのデプロイを自動化した。
記事の更新や main ブランチへのプッシュをトリガーとしてワークフローが実行される。

参考

Laravel

Laravel で CMS を自作する

Laravel で CMS を自作する

小山健人さん(@koya_zo)の Udemy 講座を通じて、Laravel の学習を行った。

ログイン認証機能やブログ管理機能、メールフォームを Laravel で実装する方法を学んだ。
CSRF 等の脆弱性対策がフレームワーク側で自動的に行われるため、アプリ本体の機能開発に集中できることに Laravel の大きな利点を感じた。

なお、Laravel の環境構築をするに先んじて、Docker の学習を行った。環境構築には Laravel Sail を使用した。

参考

PHP

ToDo アプリをつくる(CRUD とトランザクションの練習)

ToDo アプリをつくる(CRUD とトランザクションの練習)

CRUD とトランザクションの練習として、ToDo アプリを作成した。

追加・編集・削除といった機能に加え、完了ステータスを JavaScript で監視することで、完了したタスクを別テーブルに移動(アーカイブ化)し、リアルタイムで表示が更新されるようにした。この操作にはトランザクションを使用し、途中で処理が失敗してもデータの整合性が保たれるようにした。

また、CRUD 操作において XSS, CSRF, SQLインジェクションの脆弱性対策を実施した。アーカイブ化における fetch を使用した非同期リクエストでは、HTML の meta タグから取得した CSRF トークンを X-CSRF-TOKEN ヘッダに付与し、サーバ側でそのトークンを検証している。

PHP

ログイン認証機能を自作する

ログイン認証機能を自作する

ログイン認証機能を自作した。

データベース抽象化レイヤーとして PDO を使用し、接続やデータ取得の手順を統一した。これにより、将来的にデータベースの置き換えが発生した際にも、プログラムの書き換えが不要となる(ただし、DB 固有の SQL 文に関しては、別途書き換えが必要)。

また、プレースホルダーを用いたプリペアドステートメントにより、SQL インジェクション対策を行った。そのほか、XSS, CSRF, セッションハイジャックの脆弱性対策を行った。

PHP

ログイン認証機能を自作する(事前練習)

ログイン認証機能を自作する(事前練習)

ログイン認証機能を自作するための事前練習を行った。

DB の接続を同時に考えると混乱する可能性があったため、まずはテキストファイルにユーザー情報を格納し、PHP だけでつくってみた。

PHP

PHP でメールフォームを自作する

PHP でメールフォームを自作する

PHP でメールフォームを自作した。XSS 対策やトークンを使った CSRF 対策、バリデーション、セッションの後処理を行った。

  • 1