Skip to content

Commit 0360688

Browse files
committed
fix: add text wrapping to doShowText to prevent overflow
1 parent 938a676 commit 0360688

File tree

1 file changed

+71
-30
lines changed

1 file changed

+71
-30
lines changed

js/turtle.js

Lines changed: 71 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,7 @@ Turtle.TurtleView = class {
892892
}
893893

894894
/**
895-
* Adds a text object to the canvas.
895+
* Adds a text object to the canvas with auto-wrapping.
896896
*
897897
* @param size - specifies text size
898898
* @param myText - string of text to be displayed
@@ -903,38 +903,79 @@ Turtle.TurtleView = class {
903903
}
904904

905905
const textList = typeof myText !== "string" ? [myText.toString()] : myText.split("\\n");
906-
907906
const textSize = size.toString() + "px " + this.painter.font;
908-
for (let i = 0; i < textList.length; i++) {
909-
const text = new createjs.Text(textList[i], textSize, this.painter.canvasColor);
910-
text.textAlign = "left";
911-
text.textBaseline = "alphabetic";
912-
this.turtles.stage.addChild(text);
913-
this._media.push(text);
914-
text.x = this.container.x;
915-
text.y = this.container.y + i * size;
916-
text.rotation = this.orientation;
917-
918-
const xScaled = text.x * this.turtles.scale;
919-
const yScaled = text.y * this.turtles.scale;
920-
const sizeScaled = size * this.turtles.scale;
921-
this.painter.svgOutput +=
922-
'<text x="' +
923-
xScaled +
924-
'" y = "' +
925-
yScaled +
926-
'" fill="' +
927-
this.painter.canvasColor +
928-
'" font-family = "' +
929-
this.painter.font +
930-
'" font-size = "' +
931-
sizeScaled +
932-
'">' +
933-
myText +
934-
"</text>";
935907

936-
this.activity.refreshCanvas();
908+
// Skip wrapping for rotated text.
909+
const isRotated = this.orientation % 360 !== 0;
910+
911+
let maxWidth = Infinity;
912+
if (!isRotated) {
913+
const stageCanvas = this.turtles.stage && this.turtles.stage.canvas;
914+
const canvasWidth = stageCanvas ? stageCanvas.width : window.innerWidth;
915+
const available = canvasWidth - this.container.x - 20;
916+
maxWidth = Math.max(size, available); // at least one char wide
937917
}
918+
919+
const wrapText = (str, maxW) => {
920+
if (maxW === Infinity) return [str];
921+
922+
const lines = [];
923+
const tempText = new createjs.Text("", textSize, this.painter.canvasColor);
924+
let currentLine = "";
925+
926+
for (let j = 0; j < str.length; j++) {
927+
const testLine = currentLine + str[j];
928+
tempText.text = testLine;
929+
if (tempText.getMeasuredWidth() > maxW && currentLine.length > 0) {
930+
lines.push(currentLine);
931+
currentLine = str[j];
932+
} else {
933+
currentLine = testLine;
934+
}
935+
}
936+
if (currentLine.length > 0) {
937+
lines.push(currentLine);
938+
}
939+
return lines.length > 0 ? lines : [str];
940+
};
941+
942+
let currentYOffset = 0;
943+
944+
for (let i = 0; i < textList.length; i++) {
945+
const wrappedLines = wrapText(textList[i], maxWidth);
946+
947+
for (let k = 0; k < wrappedLines.length; k++) {
948+
const lineContent = wrappedLines[k];
949+
const text = new createjs.Text(lineContent, textSize, this.painter.canvasColor);
950+
text.textAlign = "left";
951+
text.textBaseline = "alphabetic";
952+
this.turtles.stage.addChild(text);
953+
this._media.push(text);
954+
text.x = this.container.x;
955+
text.y = this.container.y + currentYOffset;
956+
text.rotation = this.orientation;
957+
currentYOffset += text.getMeasuredHeight() + size * 0.2;
958+
959+
const xScaled = text.x * this.turtles.scale;
960+
const yScaled = text.y * this.turtles.scale;
961+
const sizeScaled = size * this.turtles.scale;
962+
this.painter.svgOutput +=
963+
'<text x="' +
964+
xScaled +
965+
'" y = "' +
966+
yScaled +
967+
'" fill="' +
968+
this.painter.canvasColor +
969+
'" font-family = "' +
970+
this.painter.font +
971+
'" font-size = "' +
972+
sizeScaled +
973+
'">' +
974+
lineContent +
975+
"</text>";
976+
}
977+
}
978+
this.activity.refreshCanvas();
938979
}
939980

940981
/**

0 commit comments

Comments
 (0)