Skip to content

Commit 2959f62

Browse files
committed
fix: add text wrapping to doShowText to prevent overflow
1 parent 4bef8c2 commit 2959f62

File tree

1 file changed

+79
-34
lines changed

1 file changed

+79
-34
lines changed

js/turtle.js

Lines changed: 79 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -884,12 +884,14 @@ Turtle.TurtleView = class {
884884
resizeDecoration(scale, width) {
885885
this._decorationBitmap.x = width - (30 * scale) / 2;
886886
this._decorationBitmap.y = (20 * scale) / 2; // Use 20 to match doTurtleShell
887-
this._decorationBitmap.scaleX = this._decorationBitmap.scaleY = this._decorationBitmap.scale =
888-
(this._decorationBaseScale * scale) / 2;
887+
this._decorationBitmap.scaleX =
888+
this._decorationBitmap.scaleY =
889+
this._decorationBitmap.scale =
890+
(this._decorationBaseScale * scale) / 2;
889891
}
890892

891893
/**
892-
* Adds a text object to the canvas.
894+
* Adds a text object to the canvas with auto-wrapping.
893895
*
894896
* @param size - specifies text size
895897
* @param myText - string of text to be displayed
@@ -900,38 +902,79 @@ Turtle.TurtleView = class {
900902
}
901903

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

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

937980
/**
@@ -966,8 +1009,10 @@ Turtle.TurtleView = class {
9661009

9671010
this._decorationBitmap.x = width - (offset * startBlock.protoblock.scale) / 2;
9681011
this._decorationBitmap.y = (35 * startBlock.protoblock.scale) / 2;
969-
this._decorationBitmap.scaleX = this._decorationBitmap.scaleY = this._decorationBitmap.scale =
970-
(0.5 * startBlock.protoblock.scale) / 2;
1012+
this._decorationBitmap.scaleX =
1013+
this._decorationBitmap.scaleY =
1014+
this._decorationBitmap.scale =
1015+
(0.5 * startBlock.protoblock.scale) / 2;
9711016
startBlock.updateCache();
9721017
}
9731018

0 commit comments

Comments
 (0)