LoginSignup
2
1

More than 5 years have passed since last update.

Canvasでテキストがオーバーフローしない角丸吹き出しを作る

Last updated at Posted at 2017-08-08
<!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>

2
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1