<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Canvasでテキストがオーバーフローしない角丸吹き出しを作る</title>
<script type="text/javascript">
window.onload = function() {
var canvas = document.createElement("canvas");
canvas.height = 500;
canvas.width = 500;
document.body.appendChild(canvas);
// 基本設定
var originX = 200;// 矢印X座標
var originY = 100;// 矢印Y座標
var boxWidth = 100;
var padding = 5;
var radius = 5;// 円弧の半径
var text="テストテストテストテストテスト\nテス\nト";
var context = canvas.getContext("2d");
context.fillStyle = "#b7e6ff";
// テキスト設定
var limitedWidth = boxWidth - (padding * 2);
var size = 12;
context.font = size + "px ''";
// テキスト調整 行に分解
var lineTextList = text.split("\n");
var newLineTextList = [];
lineTextList.forEach(function (lineText) {
if (context.measureText(lineText).width > limitedWidth) {
characterList = lineText.split("");// 1文字ずつ分割
var preLineText = "";
var lineText = "";
characterList.forEach(function (character) {
lineText += character;
if (context.measureText(lineText).width > limitedWidth) {
newLineTextList.push(preLineText);
lineText = character;
}
preLineText = lineText;
});
}
newLineTextList.push(lineText);
});
var lineLength = newLineTextList.length;
// 矢印
var arrow = {
"x" : originX,
"y" : originY,
"width" : 20,
"height" : 10,
}
context.beginPath();
context.moveTo(arrow.x, arrow.y);
context.lineTo(arrow.x + arrow.width / 2, arrow.y + arrow.height);
context.lineTo(arrow.x - arrow.width / 2, arrow.y + arrow.height);
context.fill();
// 角丸
var width = boxWidth;// 枠の幅
var height = (size * lineLength) + (padding * 3);// 枠の高さ
var toRadianCoefficient = Math.PI / 180;// 角度からラジアンへの変換係数
// 角丸原点(左上座標)
var boxOrigin = {
"x" : arrow.x - (width / 2),
"y" : arrow.y + arrow.height,
}
// 円弧から円弧までの直線は自動で引かれます、角度は回り方によって変わります。
// arc(中心x, 中心y, 半径, 開始角度, 終了角度, 反時計回り)
context.beginPath();
context.arc(boxOrigin.x + radius, boxOrigin.y + radius, radius, 180 * toRadianCoefficient, 270 * toRadianCoefficient, false);// 左上
context.arc(boxOrigin.x + width - radius, boxOrigin.y + radius, radius, 270 * toRadianCoefficient, 0, false);// 右上
context.arc(boxOrigin.x + width - radius, boxOrigin.y + height - radius, radius, 0, 90 * toRadianCoefficient, false);// 右下
context.arc(boxOrigin.x + radius, boxOrigin.y + height - radius, radius, 90 * toRadianCoefficient, 180 * toRadianCoefficient, false);// 左下
context.closePath();
context.fill();
// テキスト描画
context.fillStyle = "#000000";
newLineTextList.forEach(function (lineText, index) {
context.fillText(lineText, boxOrigin.x + padding, boxOrigin.y + padding + (size * (index + 1)));
});
}
</script>
</head>
<body></body>
</html>