|
import { applyEffect, getAvailableEffects } from './effects.js';
|
|
|
|
|
|
async function loadGoogleFont(fontFamily) {
|
|
|
|
const formattedFamily = fontFamily.replace(/ /g, '+');
|
|
|
|
|
|
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();
|
|
});
|
|
|