Это из-за 4-го аргумента, который вы передаете drawImage - iw / 0.78
. Умножая ширину изображения на значение меньше единицы, вы получаете значение, превышающее ширину изображения. spe c для drawImage говорит:
Когда исходный прямоугольник находится за пределами исходного изображения, исходный прямоугольник должен быть обрезан до исходного изображения, а целевой прямоугольник должен быть обрезается в той же пропорции.
ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
Поскольку используемая ширина источника (sw
) больше, чем исходное изображение размер, прямоугольник назначения "обрезается в той же пропорции". Ширина прямоугольника назначения составляет 1 пиксель, потому что вы выбрали его в качестве ширины для каждой вертикальной линии, которую вы рисуете, и после обрезки ее ширина становится 1 * 0,78 = 0,78 пикселей. Ширина теперь меньше 1px, и, честно говоря, я не совсем уверен, как это на самом деле работает под капотом, но я предполагаю, что браузер все еще должен отрисовывать этот 1px, но, поскольку источник - 0.78px, он как бы растягивает источник в 1px и добавляет сглаживание для сглаживания перехода, что приводит к дополнительной прозрачности (т. е. браузеру не хватает информации для этого 1px, и он пытается заполнить его как можно лучше). Вы можете поэкспериментировать с этим, увеличивая sw
еще больше и наблюдая увеличение прозрачности.
Чтобы исправить вашу проблему, я использовал значение 20
вместо 0.78
, как для первой чашки, и это выглядело как ок.