文字間隔をスライダー化
Browse files- effects/base.js +5 -3
- index.html +8 -0
- index.js +17 -2
effects/base.js
CHANGED
|
@@ -133,6 +133,8 @@ export class BaseEffect {
|
|
| 133 |
*/
|
| 134 |
calculateCoordinates(ctx, lines, metrics, lineSpacing, padding) {
|
| 135 |
this.coordinates = [];
|
|
|
|
|
|
|
| 136 |
|
| 137 |
if (ctx.canvas.dataset.vertical === 'true') {
|
| 138 |
// 右端から開始(文字の右端がここに来るようにする)
|
|
@@ -157,10 +159,9 @@ export class BaseEffect {
|
|
| 157 |
|
| 158 |
// 行の開始位置を中央揃えに
|
| 159 |
let charY = padding + (ctx.canvas.height - totalLineHeight - padding * 2) / 2;
|
| 160 |
-
|
| 161 |
for (const char of line) {
|
| 162 |
const metrics = ctx.measureText(char);
|
| 163 |
-
const charHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent *
|
| 164 |
const shouldRotate = this.isRotatableCharacter(char);
|
| 165 |
|
| 166 |
// 文字の配置を調整
|
|
@@ -331,8 +332,9 @@ export class BaseEffect {
|
|
| 331 |
const canvas = document.createElement('canvas');
|
| 332 |
const ctx = canvas.getContext('2d');
|
| 333 |
|
| 334 |
-
//
|
| 335 |
canvas.dataset.vertical = options.vertical;
|
|
|
|
| 336 |
|
| 337 |
// キャンバスサイズの設定
|
| 338 |
const padding = this.getPadding();
|
|
|
|
| 133 |
*/
|
| 134 |
calculateCoordinates(ctx, lines, metrics, lineSpacing, padding) {
|
| 135 |
this.coordinates = [];
|
| 136 |
+
console.log(ctx.canvas.dataset.verticalSpacing);
|
| 137 |
+
const verticalLetterSpacing = parseFloat(ctx.canvas.dataset.verticalSpacing) || 1.3;
|
| 138 |
|
| 139 |
if (ctx.canvas.dataset.vertical === 'true') {
|
| 140 |
// 右端から開始(文字の右端がここに来るようにする)
|
|
|
|
| 159 |
|
| 160 |
// 行の開始位置を中央揃えに
|
| 161 |
let charY = padding + (ctx.canvas.height - totalLineHeight - padding * 2) / 2;
|
|
|
|
| 162 |
for (const char of line) {
|
| 163 |
const metrics = ctx.measureText(char);
|
| 164 |
+
const charHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent * verticalLetterSpacing;
|
| 165 |
const shouldRotate = this.isRotatableCharacter(char);
|
| 166 |
|
| 167 |
// 文字の配置を調整
|
|
|
|
| 332 |
const canvas = document.createElement('canvas');
|
| 333 |
const ctx = canvas.getContext('2d');
|
| 334 |
|
| 335 |
+
// 縦書きモードと文字間隔の状態を保存
|
| 336 |
canvas.dataset.vertical = options.vertical;
|
| 337 |
+
canvas.dataset.verticalSpacing = options.verticalSpacing;
|
| 338 |
|
| 339 |
// キャンバスサイズの設定
|
| 340 |
const padding = this.getPadding();
|
index.html
CHANGED
|
@@ -106,6 +106,14 @@
|
|
| 106 |
<label class="form-check-label" for="verticalText">縦書き</label>
|
| 107 |
</div>
|
| 108 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
<div class="effect-grid">
|
| 110 |
<!-- プリセットギャラリーはJavaScriptで動的に追加されます -->
|
| 111 |
</div>
|
|
|
|
| 106 |
<label class="form-check-label" for="verticalText">縦書き</label>
|
| 107 |
</div>
|
| 108 |
|
| 109 |
+
<div class="mb-3" id="verticalSpacingContainer" style="display: none;">
|
| 110 |
+
<label for="verticalSpacing" class="form-label">文字間隔</label>
|
| 111 |
+
<input type="range" class="form-range" id="verticalSpacing" min="1" max="2" step="0.1" value="1.3">
|
| 112 |
+
<div class="text-center">
|
| 113 |
+
<span id="verticalSpacingValue">1.3</span>
|
| 114 |
+
</div>
|
| 115 |
+
</div>
|
| 116 |
+
|
| 117 |
<div class="effect-grid">
|
| 118 |
<!-- プリセットギャラリーはJavaScriptで動的に追加されます -->
|
| 119 |
</div>
|
index.js
CHANGED
|
@@ -43,12 +43,14 @@ async function textToImage(text, fontFamily, fontSize = '48px', effectType = 'si
|
|
| 43 |
await document.fonts.load(`${fontSize} "${fontFamily}"`);
|
| 44 |
const fontSizeNum = parseInt(fontSize);
|
| 45 |
const verticalText = document.getElementById('verticalText').checked;
|
|
|
|
| 46 |
|
| 47 |
// エフェクトを適用
|
| 48 |
const imageUrl = await applyEffect(effectType, text, {
|
| 49 |
font: fontFamily,
|
| 50 |
fontSize: fontSizeNum,
|
| 51 |
-
vertical: verticalText
|
|
|
|
| 52 |
});
|
| 53 |
|
| 54 |
return imageUrl;
|
|
@@ -149,7 +151,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 149 |
});
|
| 150 |
|
| 151 |
// テキストとフォントサイズの変更時にすべてのプリセットを再描画
|
| 152 |
-
[textInput, fontSizeInput, verticalTextInput].forEach(element => {
|
| 153 |
element.addEventListener('input', () => {
|
| 154 |
debounceRender(renderAllPresets);
|
| 155 |
});
|
|
@@ -158,3 +160,16 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
| 158 |
// 初期描画
|
| 159 |
await renderAllPresets();
|
| 160 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
await document.fonts.load(`${fontSize} "${fontFamily}"`);
|
| 44 |
const fontSizeNum = parseInt(fontSize);
|
| 45 |
const verticalText = document.getElementById('verticalText').checked;
|
| 46 |
+
const verticalSpacing = document.getElementById('verticalSpacing').value;
|
| 47 |
|
| 48 |
// エフェクトを適用
|
| 49 |
const imageUrl = await applyEffect(effectType, text, {
|
| 50 |
font: fontFamily,
|
| 51 |
fontSize: fontSizeNum,
|
| 52 |
+
vertical: verticalText,
|
| 53 |
+
verticalSpacing: verticalSpacing
|
| 54 |
});
|
| 55 |
|
| 56 |
return imageUrl;
|
|
|
|
| 151 |
});
|
| 152 |
|
| 153 |
// テキストとフォントサイズの変更時にすべてのプリセットを再描画
|
| 154 |
+
[textInput, fontSizeInput, verticalTextInput, verticalSpacing].forEach(element => {
|
| 155 |
element.addEventListener('input', () => {
|
| 156 |
debounceRender(renderAllPresets);
|
| 157 |
});
|
|
|
|
| 160 |
// 初期描画
|
| 161 |
await renderAllPresets();
|
| 162 |
});
|
| 163 |
+
|
| 164 |
+
// 縦書きモードの切り替え時の処理
|
| 165 |
+
document.getElementById('verticalText').addEventListener('change', function(e) {
|
| 166 |
+
const spacingContainer = document.getElementById('verticalSpacingContainer');
|
| 167 |
+
spacingContainer.style.display = e.target.checked ? 'block' : 'none';
|
| 168 |
+
// ロゴの再生成処理を呼び出す
|
| 169 |
+
});
|
| 170 |
+
|
| 171 |
+
// 文字間隔の変更時の処理
|
| 172 |
+
document.getElementById('verticalSpacing').addEventListener('input', function(e) {
|
| 173 |
+
document.getElementById('verticalSpacingValue').textContent = e.target.value;
|
| 174 |
+
// ロゴの再生成処理を呼び出す
|
| 175 |
+
});
|