Skip to content

Commit d1c7041

Browse files
committed
* Made compatible with segment text strings containing Unicode emoji (and any other characters) with code points that require 3 bytes to encode in UTF-8 in drawSegmentText()
* Made segment number wrap in `getRandomForSegment()` (extends the change from PR zarocknz#102) * Applied the change from PR zarocknz#64, "Add Image Width/Height in `drawImage`"
1 parent 229a47a commit d1c7041

File tree

1 file changed

+47
-30
lines changed

1 file changed

+47
-30
lines changed

Winwheel.js

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,9 @@ Winwheel.prototype.drawSegmentText = function()
796796
}
797797

798798
for (let i = 0; i < lines.length; i ++) {
799+
let lineChars = [...lines[i]];
800+
let lineLen = lineChars.length;
801+
799802
// If direction is reversed then do things differently than if normal (which is the default - see further down)
800803
if (direction == 'reversed') {
801804
// When drawing reversed or 'upside down' we need to do some trickery on our part.
@@ -888,8 +891,8 @@ Winwheel.prototype.drawSegmentText = function()
888891
// Loop though and output the characters.
889892
if (alignment == 'outer') {
890893
// In reversed mode outer means text in 6 o'clock segment sits at bottom of the wheel and we draw up.
891-
for (let c = (lines[i].length -1); c >= 0; c--) {
892-
let character = lines[i].charAt(c);
894+
for (let c = lineLen - 1; c >= 0; c--) {
895+
let character = lineChars[c];
893896

894897
if (fillStyle) {
895898
this.ctx.fillText(character, centerX + lineOffset, yPos);
@@ -903,8 +906,8 @@ Winwheel.prototype.drawSegmentText = function()
903906
}
904907
} else if (alignment == 'inner') {
905908
// In reversed mode inner text is drawn from top of segment at 6 o'clock position to bottom of the wheel.
906-
for (let c = 0; c < lines[i].length; c++) {
907-
let character = lines[i].charAt(c);
909+
for (let c = 0; c < lineLen; c++) {
910+
let character = lineChars[c]; // lines[i].charAt(c);
908911

909912
if (fillStyle) {
910913
this.ctx.fillText(character, centerX + lineOffset, yPos);
@@ -928,8 +931,8 @@ Winwheel.prototype.drawSegmentText = function()
928931

929932
let yPos = (centerY + innerRadius + ((outerRadius - innerRadius) / 2)) + centerAdjustment + margin;
930933

931-
for (let c = (lines[i].length -1); c >= 0; c--) {
932-
let character = lines[i].charAt(c);
934+
for (let c = (lineLen - 1); c >= 0; c--) {
935+
let character = lineChars[c]; // lines[i].charAt(c);
933936

934937
if (fillStyle) {
935938
this.ctx.fillText(character, centerX + lineOffset, yPos);
@@ -976,7 +979,8 @@ Winwheel.prototype.drawSegmentText = function()
976979
let drawAngle = 0;
977980

978981
// If more than one character in the text then...
979-
if (lines[i].length > 1) {
982+
//if (lines[i].length > 1) {
983+
if (lineLen > 1) {
980984
// Text is drawn from the left.
981985
this.ctx.textAlign = 'left';
982986

@@ -996,7 +1000,7 @@ Winwheel.prototype.drawSegmentText = function()
9961000
// Next we want the text to be drawn in the middle of the segment, without this it would start at the beginning of the segment.
9971001
// To do this we need to work out how much arc the text will take up in total then subtract half of this from the center
9981002
// of the segment so that it sits centred.
999-
let totalArc = (anglePerChar * lines[i].length);
1003+
let totalArc = (anglePerChar * lineLen);
10001004

10011005
// Now set initial draw angle to half way between the start and end of the segment.
10021006
drawAngle = seg.startAngle + (((seg.endAngle - seg.startAngle) / 2) - (totalArc / 2));
@@ -1019,10 +1023,10 @@ Winwheel.prototype.drawSegmentText = function()
10191023
// ----------------------
10201024
// Now the drawing itself.
10211025
// In reversed direction mode we loop through the characters in the text backwards in order for them to appear on screen correctly
1022-
for (let c = lines[i].length; c >= 0; c--) {
1026+
for (let c = lineLen; c >= 0; c--) {
10231027
this.ctx.save();
10241028

1025-
let character = lines[i].charAt(c);
1029+
let character = lineChars[c];
10261030

10271031
// Rotate the wheel to the draw angle as we need to add the character at this location.
10281032
this.ctx.translate(centerX, centerY);
@@ -1177,8 +1181,8 @@ Winwheel.prototype.drawSegmentText = function()
11771181
if (alignment == 'outer') {
11781182
// For this alignment we draw down from the top of a segment at the 12 o'clock position to simply
11791183
// loop though the characters in order.
1180-
for (let c = 0; c < lines[i].length; c++) {
1181-
let character = lines[i].charAt(c);
1184+
for (let c = 0; c < lineLen; c++) {
1185+
let character = lineChars[c];
11821186

11831187
if (fillStyle) {
11841188
this.ctx.fillText(character, centerX + lineOffset, yPos);
@@ -1193,8 +1197,8 @@ Winwheel.prototype.drawSegmentText = function()
11931197
} else if (alignment == 'inner') {
11941198
// Here we draw from the inner of the wheel up, but in order for the letters in the text text to
11951199
// remain in the correct order when reading, we actually need to loop though the text characters backwards.
1196-
for (let c = (lines[i].length -1); c >= 0; c--) {
1197-
let character = lines[i].charAt(c);
1200+
for (let c = (lineLen - 1); c >= 0; c--) {
1201+
let character = lineChars[c];
11981202

11991203
if (fillStyle) {
12001204
this.ctx.fillText(character, centerX + lineOffset, yPos);
@@ -1226,8 +1230,8 @@ Winwheel.prototype.drawSegmentText = function()
12261230
let yPos = (centerY - innerRadius - ((outerRadius - innerRadius) / 2)) - centerAdjustment - margin;
12271231

12281232
// Now loop and draw just like outer text rendering.
1229-
for (let c = 0; c < lines[i].length; c++) {
1230-
let character = lines[i].charAt(c);
1233+
for (let c = 0; c < lineLen; c++) {
1234+
let character = lineChars[c];
12311235

12321236
if (fillStyle) {
12331237
this.ctx.fillText(character, centerX + lineOffset, yPos);
@@ -1313,10 +1317,10 @@ Winwheel.prototype.drawSegmentText = function()
13131317
// ----------------------
13141318
// Now the drawing itself.
13151319
// Loop for each character in the text.
1316-
for (let c = 0; c < (lines[i].length); c++) {
1320+
for (let c = 0; c < (lineLen); c++) {
13171321
this.ctx.save();
13181322

1319-
let character = lines[i].charAt(c);
1323+
let character = lineChars[c];
13201324

13211325
// Rotate the wheel to the draw angle as we need to add the character at this location.
13221326
this.ctx.translate(centerX, centerY);
@@ -1929,22 +1933,35 @@ Winwheel.prototype.getRandomForSegment = function(segmentNumber)
19291933
{
19301934
let stopAngle = 0;
19311935

1932-
if (segmentNumber) {
1933-
if (typeof this.segments[segmentNumber] !== 'undefined') {
1934-
let startAngle = this.segments[segmentNumber].startAngle;
1935-
let endAngle = this.segments[segmentNumber].endAngle;
1936-
let range = (endAngle - startAngle) - 2;
1936+
// Ensure that the caller has specified a segment number
1937+
if (!segmentNumber) {
1938+
// Nope, they didn't. Use segment 0 as a default
1939+
console.log('segment number not specified, use 0 as a fallback value');
1940+
segmentNumber = 0;
1941+
}
1942+
1943+
// Wrap the segment number within the available segments; not sure
1944+
// if this actually is the correct code for this. -- dag
1945+
segmentNumber = segmentNumber % this.segments.length;
19371946

1938-
if (range > 0) {
1939-
stopAngle = (startAngle + 1 + Math.floor((Math.random() * range)));
1940-
} else {
1941-
console.log('Segment size is too small to safely get random angle inside it');
1942-
}
1947+
// Sanity check and only do something if the segment chosen actually exists
1948+
if (typeof this.segments[segmentNumber] !== 'undefined') {
1949+
// valid segment, determine the angular range the segment occupies
1950+
let startAngle = this.segments[segmentNumber].startAngle;
1951+
let endAngle = this.segments[segmentNumber].endAngle;
1952+
let range = (endAngle - startAngle) - 2;
1953+
1954+
// select a random angle within the segment's range to stop at
1955+
if (range > 0) {
1956+
stopAngle = (startAngle + 1 + Math.floor((Math.random() * range)));
19431957
} else {
1944-
console.log('Segment ' + segmentNumber + ' undefined');
1958+
// the segment is collapsed, land at the boundary as a fallback
1959+
console.log('Segment size is too small to safely get random angle inside it');
1960+
stopAngle = startAngle;
19451961
}
19461962
} else {
1947-
console.log('Segment number not specified');
1963+
// Seems the segment is out-of-range or otherwise invalid
1964+
console.log('Segment ' + segmentNumber + ' undefined');
19481965
}
19491966

19501967
return stopAngle;

0 commit comments

Comments
 (0)