LogoMaker / index.js
SenY's picture
Init
3ed48fd
raw
history blame
5.8 kB
import { applyEffect, getAvailableEffects } from './effects.js';
// フォントの読み込みを管理する関数
async function loadGoogleFont(fontFamily) {
// フォントファミリー名を正しく整形
const formattedFamily = fontFamily.replace(/ /g, '+');
// Google Fonts APIのURLを構築
const url = `https://fonts.googleapis.com/css2?family=${formattedFamily}&display=swap`;
// 既存のリンクタグがあれば削除
const existingLink = document.querySelector(`link[href*="${formattedFamily}"]`);
if (existingLink) {
existingLink.remove();
}
// 新しいリンクタグを追加
const link = document.createElement('link');
link.href = url;
link.rel = 'stylesheet';
document.head.appendChild(link);
// フォントの読み込みを待つ
await new Promise((resolve, reject) => {
link.onload = async () => {
try {
// フォントの読み込みを確認
await document.fonts.load(`16px "${fontFamily}"`);
// 少し待機して確実にフォントを利用可能にする
setTimeout(resolve, 100);
} catch (error) {
reject(error);
}
};
link.onerror = reject;
});
}
// テキストを画像に変換する関数を更新
async function textToImage(text, fontFamily, fontSize = '48px', effectType = 'simple') {
console.debug(`テキスト描画開始: ${effectType}`, { text, fontFamily, fontSize });
try {
await document.fonts.load(`${fontSize} "${fontFamily}"`);
const fontSizeNum = parseInt(fontSize);
const verticalText = document.getElementById('verticalText').checked;
// エフェクトを適用
const imageUrl = await applyEffect(effectType, text, {
font: fontFamily,
fontSize: fontSizeNum,
vertical: verticalText
});
return imageUrl;
} catch (error) {
console.error('フォント描画エラー:', error);
throw error;
}
}
// デバウンス関数の実装
let renderTimeout = null;
let isRendering = false;
function debounceRender(callback, delay = 200) {
if (renderTimeout) {
clearTimeout(renderTimeout);
}
if (isRendering) {
return;
}
renderTimeout = setTimeout(async () => {
isRendering = true;
try {
await callback();
} finally {
isRendering = false;
}
}, delay);
}
// イベントリスナーの設定を更新
document.addEventListener('DOMContentLoaded', async () => {
const fontSelect = document.getElementById('googleFontInput');
const textInput = document.getElementById('textInput');
const fontSizeInput = document.getElementById('fontSize');
const verticalTextInput = document.getElementById('verticalText');
const effectGrid = document.querySelector('.effect-grid');
await loadGoogleFont(fontSelect.value);
// 縦書きモードの状態をグリッドに反映
verticalTextInput.addEventListener('change', (e) => {
effectGrid.dataset.vertical = e.target.checked;
renderAllPresets();
});
// すべてのプリセットを描画する関数
async function renderAllPresets() {
effectGrid.innerHTML = '';
const text = textInput.value || 'プレビュー';
const fontFamily = fontSelect.value;
const fontSize = fontSizeInput.value + 'px';
const effects = getAvailableEffects();
for (const effect of effects) {
try {
const imageUrl = await textToImage(text, fontFamily, fontSize, effect.name);
const presetCard = document.createElement('div');
presetCard.className = 'effect-item';
presetCard.innerHTML = `
<div class="effect-name">${effect.name}</div>
<div class="preview-container">
<img src="${imageUrl}" alt="${effect.name}">
</div>
`;
effectGrid.appendChild(presetCard);
} catch (error) {
console.error(`プリセット ${effect.name} の描画エラー:`, error);
const errorCard = document.createElement('div');
errorCard.className = 'effect-item error';
errorCard.innerHTML = `
<div class="effect-name text-danger">${effect.name}</div>
<div class="preview-container">
<div class="text-danger">
<small>エラー: ${error.message}</small>
</div>
</div>
`;
effectGrid.appendChild(errorCard);
}
}
}
// フォント変更時の処理
fontSelect.addEventListener('change', async (e) => {
try {
const fontFamily = e.target.value;
await loadGoogleFont(fontFamily);
await renderAllPresets();
} catch (error) {
console.error('フォント読み込みエラー:', error);
}
});
// テキストとフォントサイズの変更時にすべてのプリセットを再描画
[textInput, fontSizeInput, verticalTextInput].forEach(element => {
element.addEventListener('input', () => {
debounceRender(renderAllPresets);
});
});
// 初期描画
await renderAllPresets();
});