Почему при вызове setTransform с двойным значением результат принудительно равен int? - PullRequest
1 голос
/ 19 июня 2020

Согласно спецификациям setTransform, все значения в setTransform(a,b,c,d,e,f) могут быть «неограниченным двойным» значением.

Но когда мы сначала устанавливаем преобразование с помощью

_ctx.setTransform(1, 0, 0, 1, -81662754.7269453, 0)

затем

_ctx.getTransform()

возвращает

DOMMatrix {a: 1, b: 0, c: 0, d: 1, e: -81662752, 0}

const _ctx = document.createElement('canvas').getContext('2d');
_ctx.setTransform(1, 0, 0, 1, -81662754.7269453, 0)
console.log( _ctx.getTransform() )

Было установлено значение double, но возвращено как целое число.

Почему это так?

1 Ответ

0 голосов
/ 19 июня 2020

Я бы сказал ... браузеры не следуют спецификациям и используют здесь «неограниченное число с плавающей запятой» вместо «неограниченное двойное». Ваше значение при сохранении как 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 делает то же самое где-то еще.

...