Skip to content

Instantly share code, notes, and snippets.

@ksasao
Created July 28, 2025 13:27
Show Gist options
  • Save ksasao/73a39bf48abd4125a793490a6c5e7bac to your computer and use it in GitHub Desktop.
Save ksasao/73a39bf48abd4125a793490a6c5e7bac to your computer and use it in GitHub Desktop.
ekimemo-font
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文字縁取りサンプル</title>
<link href="https://fonts.googleapis.com/css2?family=M+PLUS+Rounded+1c:wght@100;300;400;500;700;800;900&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
margin: 0;
padding: 20px;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
canvas {
border: 2px solid #333;
background: rgba(255, 255, 255, 0.1);
margin: 10px;
}
.controls {
background: rgba(255, 255, 255, 0.9);
padding: 20px;
border-radius: 10px;
margin: 20px 0;
text-align: center;
}
input, button {
margin: 5px;
padding: 8px;
border: 1px solid #ccc;
border-radius: 5px;
}
button {
background: #4ecdc4;
color: white;
cursor: pointer;
}
button:hover {
background: #45b7aa;
}
</style>
</head>
<body>
<h1 style="color: white; text-shadow: 2px 2px 4px rgba(0,0,0,0.5);">文字縁取りサンプル</h1>
<div class="controls">
<label>テキスト: </label>
<input type="text" id="textInput" value="連続2324日目/通算2324日目" placeholder="表示したい文字を入力">
<br>
<label>フォントサイズ: </label>
<input type="range" id="fontSizeSlider" min="20" max="120" value="21">
<span id="fontSizeValue">21px</span>
<br>
<label>縁取りの太さ: </label>
<input type="range" id="outlineThicknessSlider" min="1" max="8" value="3">
<span id="outlineThicknessValue">2px</span>
<br>
<button onclick="drawText()">描画</button>
</div>
<canvas id="canvas" width="800" height="200"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const textInput = document.getElementById('textInput');
const fontSizeSlider = document.getElementById('fontSizeSlider');
const fontSizeValue = document.getElementById('fontSizeValue');
const outlineThicknessSlider = document.getElementById('outlineThicknessSlider');
const outlineThicknessValue = document.getElementById('outlineThicknessValue');
// スライダーの値を表示に反映
fontSizeSlider.addEventListener('input', () => {
fontSizeValue.textContent = fontSizeSlider.value + 'px';
drawText();
});
outlineThicknessSlider.addEventListener('input', () => {
outlineThicknessValue.textContent = outlineThicknessSlider.value + 'px';
drawText();
});
textInput.addEventListener('input', drawText);
function drawText() {
const text = textInput.value || '縁取り文字';
const fontSize = parseInt(fontSizeSlider.value);
const outlineThickness = parseInt(outlineThicknessSlider.value);
// キャンバスをクリア
ctx.clearRect(0, 0, canvas.width, canvas.height);
// フォント設定
ctx.font = `300 ${fontSize}px Arial, sans-serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const x = canvas.width / 2;
const y = canvas.height / 2;
// 縁取り用のオフセット配列を生成
const offsets = generateOffsets(outlineThickness);
// 1. 縁取り部分を描画(白色で複数回ずらして描画)
ctx.fillStyle = 'white';
offsets.forEach(offset => {
ctx.fillText(text, x + offset.x, y + offset.y);
});
// 2. メインの文字を描画(前面に表示)
ctx.fillStyle = '#333';
ctx.fillText(text, x, y);
}
function generateOffsets(thickness) {
const offsets = [];
const t = 2;
for(let x=-t; x<=t; x=x+thickness){
for(let y = -t; y<=t; y=y+thickness){
offsets.push({x,y});
}
}
return offsets;
}
// 初期描画
drawText();
// ウィンドウリサイズ時の対応
window.addEventListener('resize', () => {
const rect = canvas.getBoundingClientRect();
if (rect.width > 0) {
drawText();
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment