🎨 リアルタイムデザインエディタと背景演出の概要
本ドキュメントは、再ビルドや再デプロイを必要とせずにテーマ設定を即座に反映するシステムと、4つの背景設定(単一色、グラデーション、背景画像、カスタムJavaScriptキャンバス)の基本構成について紹介します。
🌌 1. リアルタイムデザインエディタの概要
デザインエディタで設定値を変更して保存する際、ブログサーバーやCDNサービスを再ビルド・再デプロイする必要は一切ありません。保存するとデータベースが即座に更新され、訪問者のブラウザ画面にCSS変数と背景レンダリングモジュールが1秒で反映されます。
🎨 テーマの基本カスタマイズ
- カラー設定: メインテーマ色(Primary)、サブ色(Secondary)、本文テキスト色(Text)、アクセント強調色(Accent)、カード背景色(Card Bg)、枠線色(Border)などを調整できます。
- レイアウト設定: 左右余白(Side Margin)、画面の最大幅(Max Width)、カード角の丸み(Border Radius)、立体感を与えるシャドウ効果(Box Shadow)をサポートしています。
- タイポグラフィ設定: Google Fonts一覧から任意のフォント名を記入して適用できるほか、本文フォントの種類や基本文字サイズ(Base Font Size)を設定できます。
🧱 2. デバイス別の独立ウィジェット配置
レイアウト設計時には、ドラッグ&ドロップでサイドバーや本文領域のウィジェット位置と順序を調整できます。また、訪問者の画面サイズ(デバイスタイプ)に応じてレイアウトを動的に切り替えるフィルタリング機能を提供します。
- Desktop (デスクトップ専用): 画面幅の広いPC環境でのみ、指定されたウィジェット(例:タグクラウド、カテゴリツリーなど)を表示します。モバイル接続時には、読み込み速度を維持するため、HTML送信段階で該当要素をあらかじめ除外します。
- Mobile (モバイル専用): デスクトップ環境では非表示にし、スマートフォンなどのモバイル解像度でのみモバイル向けに表示されるよう制限します。
🌈 3. 4つの背景設定の種類
ブログ全体の雰囲気を決定する背景画面として、以下の4つのタイプがサポートされています。
① Solid(単一色背景)
- 任意のHEXコード(例:
#3b82f6)またはHSLカラーコードを指定して、最もシンプルで記事本文に集中しやすい画面を構成します。
② Gradient(グラデーション背景)
- グラデーションビルダーツールを使用して、複数のカラーがスムーズに混ざり合う線形グラデーションを作成します。
- 角度(Direction)スライダーの調整やカラーストップ(Stops)の追加・移動により、開始色、中間色、終了色を自由に配合できます。
③ Image(背景画像&グラスモフィズム効果)
- 背景に使用する画像のURLを入力するか、アップロード(Upload)ボタンを使用してメディアファイルをライブラリに追加します。
- アップロード画像の最適化: 画像を登録すると、システムが自動的にWebP形式へ変換し、読み込みパフォーマンスの低下を防ぎます。
- グラスモフィズム効果: 背景画像がテキストの視認性を妨げないよう、以下の設定を組み合わせて半透明なガラス窓風のスタイルを構成できます。
| 設定項目 | 推奨値の範囲 | 詳細説明 |
|---|---|---|
| 背景のぼかし (Glass Blur) | 5px ~ 15px |
本文カードの下部レイヤーに半透明なすりガラス風のフィルターを適用します。 |
| オーバーレイ不透明度 (Overlay Opacity) | 10% ~ 30% |
カードコンテナの背後に敷く半透明マスクの不透明度を決定します。 |
| オーバーレイ色 (Overlay Color) | #000000 または #ffffff |
マスクの色をダーク(暗)またはライト(明)に設定し、テキストのコントラストを確保します。 |
④ Custom JavaScript(カスタムJavaScript&Canvas背景)
- クライアントのブラウザ背景にインタラクティブなCanvasアニメーションを描画するため、カスタムJavaScriptの入力をサポートします。
- 背景キャンバス要素(
canvas id="bg-canvas")に対して直接描画を制御できます。連動するセキュリティ制限や省電力ポリシーの詳細は、以下の [4. カスタムJavaScript連携仕様] で説明します。
⚡ 4. カスタムJavaScript連携仕様
セキュリティリスクを防止し、モバイル端末のバッテリー消費を抑えるため、以下のサンドボックス環境および省電力システムが適用されています。
🔒 サンドボックス&CSPによるセキュリティ制限
悪意あるスクリプトの混入による脆弱性を防ぐため、以下のセキュリティ対策が常時稼働しています。
- 隔離されたサンドボックス構造: キャンバスコードは、スクリプト実行のみが許可された隔離された
iframe内で動作します。親ページのDOMノードやログイン情報などへのアクセスは技術的に遮断されます。 - コンテンツセキュリティポリシー (CSP) 制限: 外部サーバーへのネットワーク通信や外部スクリプトの呼び出しが全面的に遮断されます。これにより、外部サーバーへデータを流出させることが不可能です。
- JS APIの制限: セキュリティ上のリスクとなる
fetch,XMLHttpRequest,WebSocket,eval,new Function,document.cookie,localStorageなどのAPIが検出された場合、検証スクリプト(jsValidator.ts)によって自動的にコメント処理(/* f_e_t_c_h (blocked) */)されます。
🔋 バッテリー消費の最適化(省電力技術)
- 画面外での自動一時停止: ユーザーがスクロールして背景アニメーションが完全に視野から外れると、ブラウザが不要にCPU/GPUを消費しないよう、レンダリングループを スリープ状態(一時停止) に切り替えます。再び画面に表示されると、即座に再開されます。
- モバイル用フレーム制限: スマートフォンやタブレットでアクセスする場合、発熱を抑えるためデフォルトで背景スクリプトの実行を停止します。「モバイル端末でもアニメーションを実行」 オプションを明示的に有効にした場合は実行が可能となり、その際もパフォーマンスに負荷がかからないようパーティクル数を自動的に削減する制御パラメータが適用されます。
📝 5. サンプルスクリプト3種
背景設定メニューから [Custom JavaScript] を選択し、以下のコードのいずれかをコピーして適用できます。
[!NOTE]
スクリプトを作成する際は、描画対象のキャンバス要素を取得するために必ずdocument.getElementById('bg-canvas')のID名を使用してください。
❄️ サンプルA. 冬の雪(Snowfall)
画面上部から雪の結晶がゆっくりと舞い落ちる背景アニメーションです。
(function() {
const canvas = document.getElementById('bg-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
let width = canvas.width = window.innerWidth;
let height = canvas.height = window.innerHeight;
// モバイル省電力の判定
const divisor = (window.bgConfig && window.bgConfig.mobileThrottleDivisor) || 1;
const maxSnowflakes = Math.floor(100 / divisor);
const snowflakes = [];
class Snowflake {
constructor() {
this.reset();
this.y = Math.random() * height; // 初期ランダム高度
}
reset() {
this.x = Math.random() * width;
this.y = -10;
this.radius = Math.random() * 3 + 1;
this.speed = Math.random() * 1 + 0.5;
this.opacity = Math.random() * 0.6 + 0.2;
}
update() {
this.y += this.speed;
// 緩やかな揺らぎ
this.x += Math.sin(this.y / 30) * 0.5;
if (this.y > height || this.x < 0 || this.x > width) {
this.reset();
}
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = `rgba(25, 25, 255, ${this.opacity})`;
ctx.fill();
}
}
// パーティクルの生成
for (let i = 0; i < maxSnowflakes; i++) {
snowflakes.push(new Snowflake());
}
function animate() {
ctx.clearRect(0, 0, width, height);
for (let i = 0; i < snowflakes.length; i++) {
snowflakes[i].update();
snowflakes[i].draw();
}
requestAnimationFrame(animate);
}
// リサイズハンドラ
window.addEventListener('resize', () => {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
});
animate();
})();
🕸️ サンプルB. 星座ネットワーク(Constellation Network)
浮遊するノードパーティクル同士が近づいた際に、薄い半透明の線で結ばれ網状のネットワークを形成する背景アニメーションです。
(function() {
const canvas = document.getElementById('bg-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
let width = canvas.width = window.innerWidth;
let height = canvas.height = window.innerHeight;
const divisor = (window.bgConfig && window.bgConfig.mobileThrottleDivisor) || 1;
const particleCount = Math.floor(80 / divisor);
const particles = [];
const connectionDistance = 100;
class Particle {
constructor() {
this.x = Math.random() * width;
this.y = Math.random() * height;
this.vx = (Math.random() - 0.5) * 0.8;
this.vy = (Math.random() - 0.5) * 0.8;
this.radius = Math.random() * 2 + 1.5;
}
update() {
this.x += this.vx;
this.y += this.vy;
// 境界での反射
if (this.x < 0 || this.x > width) this.vx *= -1;
if (this.y < 0 || this.y > height) this.vy *= -1;
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(99, 102, 241, 0.4)'; // パステルインディゴ
ctx.fill();
}
}
for (let i = 0; i < particleCount; i++) {
particles.push(new Particle());
}
function drawLines() {
for (let i = 0; i < particles.length; i++) {
for (let j = i + 1; j < particles.length; j++) {
const dx = particles[i].x - particles[j].x;
const dy = particles[i].y - particles[j].y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < connectionDistance) {
const alpha = (connectionDistance - dist) / connectionDistance * 0.18;
ctx.beginPath();
ctx.moveTo(particles[i].x, particles[i].y);
ctx.lineTo(particles[j].x, particles[j].y);
ctx.strokeStyle = `rgba(99, 102, 241, ${alpha})`;
ctx.lineWidth = 1;
ctx.stroke();
}
}
}
}
function animate() {
ctx.clearRect(0, 0, width, height);
for (let i = 0; i < particles.length; i++) {
particles[i].update();
particles[i].draw();
}
drawLines();
requestAnimationFrame(animate);
}
window.addEventListener('resize', () => {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
});
animate();
})();
🌊 サンプルC. 穏やかな波(Fluid Sine Waves)
画面下部でパステル調の半透明な複数の波が緩やかに揺れる背景アニメーションです。
(function() {
const canvas = document.getElementById('bg-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
let width = canvas.width = window.innerWidth;
let height = canvas.height = window.innerHeight;
let wave1 = {
y: height * 0.85,
length: 0.005,
amplitude: 25,
frequency: 0.012
};
let wave2 = {
y: height * 0.88,
length: 0.008,
amplitude: 15,
frequency: 0.022
};
let increment = 0;
function animate() {
ctx.clearRect(0, 0, width, height);
// 背景の波の描画 (半透明ティール)
ctx.beginPath();
ctx.moveTo(0, height);
for (let i = 0; i < width; i++) {
ctx.lineTo(i, wave1.y + Math.sin(i * wave1.length + increment) * wave1.amplitude);
}
ctx.lineTo(width, height);
ctx.fillStyle = 'rgba(45, 212, 191, 0.1)';
ctx.fill();
// 手前の波の描画 (半透明スカイブルー)
ctx.beginPath();
ctx.moveTo(0, height);
for (let i = 0; i < width; i++) {
ctx.lineTo(i, wave2.y + Math.sin(i * wave2.length - increment * 1.5) * wave2.amplitude);
}
ctx.lineTo(width, height);
ctx.fillStyle = 'rgba(56, 189, 248, 0.15)';
ctx.fill();
// デバイスの設定に応じた速度の調整
const speedFactor = (window.bgConfig && window.bgConfig.mobileThrottleDivisor) ? 0.3 : 1;
increment += wave1.frequency * speedFactor;
requestAnimationFrame(animate);
}
window.addEventListener('resize', () => {
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
wave1.y = height * 0.85;
wave2.y = height * 0.88;
});
animate();
})();
📱 6. モバイル個別背景設定
利用環境に合わせて背景設定を変えることで、システムのパフォーマンスを最適化できます。
- デスクトップ背景: PC環境では Custom JavaScript を選択し、任意のCanvasアニメーションを実行できます。
- モバイル個別背景チェック: 「モバイルデバイスでデスクトップと異なる背景設定を使用する」 トグルを有効にします。
- モバイル背景の軽量化: 独立したモバイル設定パネルから背景を Solid または Gradient に設定し、モバイル端末のプロセッサ負荷を最小限に抑えます。
- 効果: スマートフォン接続時には軽量な背景を選択することでバッテリーを保護し、PC接続時には豊かなビジュアルモーション効果を最大限に表現するというイネーブル化が可能です。
コメント 0件
コメントを投稿するにはログインが必要です。