2016-05-11 13 views
1

У меня есть конкретный случай, но мне также любопытно в целом.Как установить свойство типизированного объекта при сохранении его типа?

У меня есть холст, я получаю его ImgData с помощью createImageData, и я установил его свойство данных как нечто другое, чтобы затем использовать PutImageData и передать ему этот модифицированный ImgData.

Моя версия PureScript не работает, хотя запись логики в Javascript в консоли работает безупречно. Ошибка:

foreign.js:423 Uncaught TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': 
parameter 1 is not of type 'ImageData'. 

В PureScript:

getCleanBuffer :: forall e. Context2D -> Eff (canvas :: Canvas | e) ImageData 
getCleanBuffer ctx = do 
    imgData <- getImageData ctx 0.0 0.0 160.0 144.0 
    return imgData { data = buffer } 
where buffer = asUint8ClampedArray $ A.replicate (160*144*4) 0 

Запись этого JavaScript в консольных работы (обр 160 * 144 * 4 нулей)

var arr2 = new Uint8ClampedArray(arr); 
var imgData = ctx.getImageData(0,0,160,144); 
imgData.data = arr2; 
ctx.putImageData(imgData,0,0); 

Я отлаженный getCleanBuffer и вот что я нашел

var getCleanBuffer = function (ctx) { 
var buffer = Data_TypedArray.asUint8ClampedArray(Data_Array.replicate((160 * 144 | 0) * 4 | 0)(0)); 
return function __do() { 
    var v = Graphics_Canvas.getImageData(ctx)(0.0)(0.0)(160.0)(144.0)(); 
    var $9 = {}; 
    for (var $10 in v) { 
     if (v.hasOwnProperty($10)) { 
      $9[$10] = v[$10]; 
     }; 
    }; 
    $9.data = buffer; 
    return $9; 

Эта переменная $ 9 (копия ImgData с измененными данными) при проверке обнаруживает, что она не является типом ImgData, например v (исходная ImgData), но это просто «объект». Отсутствует ширина и высота, которые у v, но даже когда я исправляю ее во время отладки, я все равно получаю ту же ошибку.

Я думаю, проблема в том, что новый объект является беспричинной записью. Еще одна проблема заключается в том, что ширина и высота не были скопированы.

Я могу написать функцию javascript для установки атрибута данных вручную. Но этот случай в целом кажется общим, конечно, я чего-то не хватает, не так ли?

Спасибо!

+0

Это похоже на ошибку в библиотеке холста. Не могли бы вы подать там какой-нибудь вопрос? –

+0

Сначала я думал, что вы имеете в виду ошибку в холсте HTML5. После просмотра отчета об ошибке gb. Открылся, понял. Но что же тогда должен был ImgData? Не совсем, просто в общем. – PsyFish

ответ

3

В этом случае тип ImageData неверен, это синоним типа записи, но небезопасно обрабатывать типизированные значения класса JavaScript в качестве записей именно по той причине, что вы открываете здесь.

Я открыл a bug report, как предложил Фил.

Для общего случая, это то, где объективы пригождаются. Вы бы определили объектив как _data :: LensP ImageData Uint8ClampedArray, а затем могли бы сделать imgData # _data %~ buffer, чтобы достичь чего-то похожего на синтаксис обновления.

+1

Спасибо за пояснение линзы. Мой общий вопрос заключался не в том, как установить что-то так, как установить свойство типизированного значения класса, не нарушая его. Но теперь я понимаю, что проблема заключалась в том, как был определен тип ImgData. Но, как я спросил Фила в комментариях, какие типы, такие как ImgData, должны быть определены как? Просто импорт иностранных данных? С специализированными функциями набора? – PsyFish

+0

А, ладно, извините, я этого не понимал. Да, идея заключалась бы в том, чтобы предоставить тип как «чужие данные», а затем «getData' /' setData »импортные импортные функции для управления объектом (с помощью' setData' либо копируя его соответствующим образом, либо работая в 'Eff' и мутируя его напрямую в зависимости от того, что имеет больше смысла для интерфейса). –

0

Я вообще не знаю purescript, поэтому я не буду отвечать на заголовок вашего вопроса, но для вашего точного случая вы не должны создавать «clean ImageData».

Различные браузеры имеют различные реализации ImageData объекта и так specs требуется только "TypedArray" как data собственности, вы не можете быть уверены в том, что тип этого буфера должен быть Uint8ClampedArray в каждом UA (related Q/A). (сейчас living specs укажите тип этого TypedArray как Uint8ClampedArray).

Но достаточно к счастью, кажется, что вы пытаетесь изобрести колесо, когда холст API уже есть метод context2D.createImageData(width, height) или check-supported-browsersImageData(Uint8ClampedArray) Constructor если ваш в worker (где createImageData не доступен)

Просто используйте его, он будет работать в любом UA, поддерживающем API-интерфейс canvas, и вам не придется беспокоиться о копировании любого типа.

+0

Спасибо за ваш ответ Кайдо. Хотя это не видно в примерах, которые я поставил выше, я использую createImageData(), устанавливаю его свойство данных, а затем используйте putImageData() над ним. Так мне кажется, что он соответствует тому, что вы рекомендуете – PsyFish

+0

@PsyFish, то в чем цель 'getCleanBuffer'? Вы не должны изменять свойство 'data', как вы это делаете. – Kaiido

+0

Возможно, я вас неправильно понял, извините. Вы имели в виду, что getCleanBuffer должен был использовать createImageData, а не getImageData? Извините, я смутил эти 2 функции. Можно ли установить свойство данных ImgData, полученное через getImageData? – PsyFish

 Смежные вопросы

  • Нет связанных вопросов^_^