Determine orientation by actual text start and end x

This commit is contained in:
Maximilian Krög
2020-09-25 23:28:54 +02:00
parent 9c964ce6de
commit 7660f3c522
+66 -48
View File
@@ -34,71 +34,89 @@ export function drawTextOnPath(
cache, cache,
rotation rotation
) { ) {
const result = []; let x2 = flatCoordinates[offset];
let y2 = flatCoordinates[offset + 1];
let x1 = 0;
let y1 = 0;
let segmentLength = 0;
let segmentM = 0;
function advance() {
x1 = x2;
y1 = y2;
offset += stride;
x2 = flatCoordinates[offset];
y2 = flatCoordinates[offset + 1];
segmentM += segmentLength;
segmentLength = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
do {
advance();
} while (offset < end - stride && segmentM + segmentLength < startM);
let interpolate = (startM - segmentM) / segmentLength;
const beginX = lerp(x1, x2, interpolate);
const beginY = lerp(y1, y2, interpolate);
const startOffset = offset - stride;
const startLength = segmentM;
const endM = startM + measureAndCacheTextWidth(font, text, cache);
while (offset < end - stride && segmentM + segmentLength < endM) {
advance();
}
interpolate = (endM - segmentM) / segmentLength;
const endX = lerp(x1, x2, interpolate);
const endY = lerp(y1, y2, interpolate);
// Keep text upright // Keep text upright
let reverse; let reverse;
if (rotation) { if (rotation) {
const rotatedCoordinates = rotate( const flat = [beginX, beginY, endX, endY];
flatCoordinates, rotate(flat, 0, 4, 2, rotation, flat, flat);
offset, reverse = flat[0] > flat[2];
end,
stride,
rotation,
[flatCoordinates[offset], flatCoordinates[offset + 1]]
);
reverse =
rotatedCoordinates[0] >
rotatedCoordinates[rotatedCoordinates.length - stride];
} else { } else {
reverse = flatCoordinates[offset] > flatCoordinates[end - stride]; reverse = beginX > endX;
} }
const numChars = text.length; offset = startOffset;
segmentLength = 0;
let x1 = flatCoordinates[offset]; segmentM = startLength;
let y1 = flatCoordinates[offset + 1]; x2 = flatCoordinates[offset];
offset += stride; y2 = flatCoordinates[offset + 1];
let x2 = flatCoordinates[offset]; advance();
let y2 = flatCoordinates[offset + 1];
let segmentM = 0;
let segmentLength = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
let angleChanged = false; let angleChanged = false;
let index, previousAngle; const PI = Math.PI;
for (let i = 0; i < numChars; ++i) { const result = [];
index = reverse ? numChars - i - 1 : i; let previousAngle = Math.atan2(y2 - y1, x2 - x1);
if (reverse) {
previousAngle += previousAngle > 0 ? -PI : PI;
}
for (let i = 0, ii = text.length; i < ii; ++i) {
const index = reverse ? ii - i - 1 : i;
const char = text[index]; const char = text[index];
const charLength = scale * measureAndCacheTextWidth(font, char, cache); const charLength = scale * measureAndCacheTextWidth(font, char, cache);
const charM = startM + charLength / 2; const charM = startM + charLength / 2;
while (offset < end - stride && segmentM + segmentLength < charM) { while (offset < end - stride && segmentM + segmentLength < charM) {
x1 = x2; advance();
y1 = y2; let angle = Math.atan2(y2 - y1, x2 - x1);
offset += stride; if (reverse) {
x2 = flatCoordinates[offset]; angle += angle > 0 ? -PI : PI;
y2 = flatCoordinates[offset + 1];
segmentM += segmentLength;
segmentLength = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}
const segmentPos = charM - segmentM;
let angle = Math.atan2(y2 - y1, x2 - x1);
if (reverse) {
angle += angle > 0 ? -Math.PI : Math.PI;
}
if (previousAngle !== undefined) {
let delta = angle - previousAngle;
angleChanged = angleChanged || delta !== 0;
delta +=
delta > Math.PI ? -2 * Math.PI : delta < -Math.PI ? 2 * Math.PI : 0;
if (Math.abs(delta) > maxAngle) {
return null;
} }
if (previousAngle !== undefined && angle !== previousAngle) {
let delta = angle - previousAngle;
delta += delta > PI ? -2 * PI : delta < -PI ? 2 * PI : 0;
if (Math.abs(delta) > maxAngle) {
return null;
}
angleChanged = true;
}
previousAngle = angle;
} }
previousAngle = angle; interpolate = (charM - segmentM) / segmentLength;
const interpolate = segmentPos / 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, angle, char]; result[index] = [x, y, charLength / 2, previousAngle, char];
startM += charLength; startM += charLength;
} }
return angleChanged return angleChanged