Draw substrings on straight line in one operation
This commit is contained in:
@@ -78,6 +78,8 @@ export function drawTextOnPath(
|
|||||||
reverse = beginX > endX;
|
reverse = beginX > endX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PI = Math.PI;
|
||||||
|
const result = [];
|
||||||
const singleSegment = startOffset + stride === offset;
|
const singleSegment = startOffset + stride === offset;
|
||||||
|
|
||||||
offset = startOffset;
|
offset = startOffset;
|
||||||
@@ -85,48 +87,60 @@ export function drawTextOnPath(
|
|||||||
segmentM = startLength;
|
segmentM = startLength;
|
||||||
x2 = flatCoordinates[offset];
|
x2 = flatCoordinates[offset];
|
||||||
y2 = flatCoordinates[offset + 1];
|
y2 = flatCoordinates[offset + 1];
|
||||||
advance();
|
|
||||||
|
|
||||||
const PI = Math.PI;
|
|
||||||
const result = [];
|
|
||||||
let previousAngle = Math.atan2(y2 - y1, x2 - x1);
|
|
||||||
if (reverse) {
|
|
||||||
previousAngle += previousAngle > 0 ? -PI : PI;
|
|
||||||
}
|
|
||||||
|
|
||||||
// All on the same segment
|
// All on the same segment
|
||||||
if (singleSegment) {
|
if (singleSegment) {
|
||||||
|
advance();
|
||||||
|
|
||||||
|
let previousAngle = Math.atan2(y2 - y1, x2 - x1);
|
||||||
|
if (reverse) {
|
||||||
|
previousAngle += previousAngle > 0 ? -PI : PI;
|
||||||
|
}
|
||||||
const x = (endX + beginX) / 2;
|
const x = (endX + beginX) / 2;
|
||||||
const y = (endY + beginY) / 2;
|
const y = (endY + beginY) / 2;
|
||||||
result[0] = [x, y, (endM - startM) / 2, previousAngle, text];
|
result[0] = [x, y, (endM - startM) / 2, previousAngle, text];
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0, ii = text.length; i < ii; ++i) {
|
let previousAngle;
|
||||||
const index = reverse ? ii - i - 1 : i;
|
for (let i = 0, ii = text.length; i < ii; ) {
|
||||||
const char = text[index];
|
advance();
|
||||||
const charLength = scale * measureAndCacheTextWidth(font, char, cache);
|
let angle = Math.atan2(y2 - y1, x2 - x1);
|
||||||
const charM = startM + charLength / 2;
|
if (reverse) {
|
||||||
let angle;
|
angle += angle > 0 ? -PI : PI;
|
||||||
while (offset < end - stride && segmentM + segmentLength < charM) {
|
|
||||||
advance();
|
|
||||||
angle = Math.atan2(y2 - y1, x2 - x1);
|
|
||||||
if (reverse) {
|
|
||||||
angle += angle > 0 ? -PI : PI;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (angle !== undefined) {
|
if (previousAngle !== undefined) {
|
||||||
let delta = angle - previousAngle;
|
let delta = angle - previousAngle;
|
||||||
delta += delta > PI ? -2 * PI : delta < -PI ? 2 * PI : 0;
|
delta += delta > PI ? -2 * PI : delta < -PI ? 2 * PI : 0;
|
||||||
if (Math.abs(delta) > maxAngle) {
|
if (Math.abs(delta) > maxAngle) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
previousAngle = angle;
|
|
||||||
}
|
}
|
||||||
interpolate = (charM - segmentM) / segmentLength;
|
previousAngle = angle;
|
||||||
|
|
||||||
|
const iStart = i;
|
||||||
|
let charLength = 0;
|
||||||
|
for (; i < ii; ++i) {
|
||||||
|
const index = reverse ? ii - i - 1 : i;
|
||||||
|
const len = scale * measureAndCacheTextWidth(font, text[index], cache);
|
||||||
|
if (
|
||||||
|
offset + stride < end &&
|
||||||
|
segmentM + segmentLength < startM + charLength + len / 2
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
charLength += len;
|
||||||
|
}
|
||||||
|
if (i === iStart) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const chars = reverse
|
||||||
|
? text.substring(ii - iStart, ii - i)
|
||||||
|
: text.substring(iStart, i);
|
||||||
|
interpolate = (startM + charLength / 2 - segmentM) / segmentLength;
|
||||||
const x = lerp(x1, x2, interpolate);
|
const x = lerp(x1, x2, interpolate);
|
||||||
const y = lerp(y1, y2, interpolate);
|
const y = lerp(y1, y2, interpolate);
|
||||||
result[index] = [x, y, charLength / 2, previousAngle, char];
|
result.push([x, y, charLength / 2, angle, chars]);
|
||||||
startM += charLength;
|
startM += charLength;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
Reference in New Issue
Block a user