Я бы сказал ... браузеры не следуют спецификациям и используют здесь «неограниченное число с плавающей запятой» вместо «неограниченное двойное». Ваше значение при сохранении как Float32 будет округлено до того же -81662752
значения:
const float32 = new Float32Array( [ -81662754.7269453 ] )[ 0 ];
const rounded = -81662752;
console.log( float32 );
console.log( float32 === rounded );
Я открыл проблему на трекере HTML спецификаций , но не слишком надеяться на изменение браузера.
Тем не менее обратите внимание, что вы столкнетесь с реальными проблемами во многих местах 2D-контекста со значениями выше 0xFFFFFF:
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = "green";
let v = 0xFFFFFE;
ctx.setTransform( 1, 0, 0, 1, -v, 0 );
// x -> 0xFFFFFE
ctx.fillRect( v, 0, 1, 25 );
ctx.fillStyle = "red";
// x -> 0xFFFFFF
ctx.fillRect( v + 1, 25, 1, 25 );
ctx.fillStyle = "blue";
// x -> 0x1000000
ctx.fillRect( v + 2, 50, 1, 25 );
<canvas id="canvas"></canvas>
А также обратите внимание, что это проблема только для 2D-контекста, браузеры действительно обрабатывают неограниченное двойное значение для других объектов DOMMatrix:
const mat = DOMMatrix.fromFloat64Array( new Float64Array([1, 0, 0, 1, -81662754.7269453, 0 ] ) );
console.log( mat );
Глядя на источники, кажется, что они определяют его правильно: для FF и для Chrome, но по крайней мере Chrome явно делает
// clamp to float to avoid float cast overflow when used as SkScalar
, и я думаю, что FF делает то же самое где-то еще.