На картинках мы видим эффект, в котором есть только вертикальные смещения букв по ходу движения. Нет никаких поворотов, растяжений, и.т.д. Только сдвиг по одной оси. Это упрощает задачу, сводя ее суть к описанному в соседнем ответе, но дальше вы там куда-то ушли в сторону трансформаций и горы масок. Это все сложно для восприятия и производительность будет оставлять желать лучшего. В контексте JS и 2D-канвасов можно пойти другим, более традиционным, путем:
- Определить разумную максимальную длину текста в пикселях.
- Сделать канвас этого размера, залить белым.
- Нарисовать на нем черный текст стандартным методом, чтобы он занимал 100% ширины. Подгонка текста по ширине - типовая задача, легко гуглится.
- Достать содержимое канваса в виде imageData. На этом этапе у нас есть текстура с нарисованным текстом.
- Сделать второй канвас, на котором пользователь работает. Залить белым.
- Достать его imageData или создать новую под его размер.
- Взять кривую в формате x(t), y(t). Пройти циклом по t. Разумный шаг определяется в зависимости от длины кривой на канвасе, он должен давать смещение не больше 1 по x. Для абсолютной надежности можно сделать шаг меньше, и на каждой итерации проверять, сместились ли мы. Своего рода трассировка луча по кривой.
- Сопоставить диапазон t и координату u в текстуре с текстом. Проход по t должен логически соответствовать проходу по горизонтали по всей текстуре.
- На каждой итерации цикла взять столбец из imageData текстуры с текущим u, скопировать его в imageData рабочего канваса по координатам x, y. Копируем не 1 в 1, а с учетом масштабирования, которое мы уже знаем из соотношений t и u, чтобы сохранить пропорции букв. С учетом наложений вероятно имеет смысл копировать только черное, не перекрашивая черное обратно в белое.
- Обновить imageData рабочего канваса.
- При обновлении данных повторять от п.6. Вероятно будет хорошей идеей не создавать imageData каждый раз заново, чтобы не перевыделять память под нее каждый раз.
Очевидно, что тут будут циклы в циклах, что тоже не идеально, хотя оверхед будет заметно меньше, чем у бесконечных вызовов штатных методов канваса для рисований текста и его обрезания. В целом для таких вещей можно было бы использовать webgl, чтобы происходящее с п.6 уже происходило в шейдерах и распараллеливалось. Но вполне вероятно, что и так сойдет.