Haskell Threepenny Gui: чтение цвета с холста в определенной точке?

Есть ли способ прочитать цвет определенной точки холста?

Что-то вроде:

getColor :: Canvas -> Point -> Color

Я проверил документацию на Graphics.UI.Threepenny.Canvas, но не смог найти для этого никакой функции. Может быть, я просто не видел этого, потому что я не так давно использую Haskell.

Если у вас есть намеки на меня, пожалуйста, дайте мне знать.

Большое спасибо заранее, Клем

РЕДАКТИРОВАТЬ: Благодаря ответу Генриха Апфельмуса я смог написать рабочее решение и хотел поделиться им в случае, если кому-то нужна та же функция. Конечно, если вы используете его и вносите изменения, не стесняйтесь поделиться им:)

import qualified Graphics.UI.Threepenny as UI
import Graphics.UI.Threepenny.Core
import Codec.Picture.Types

-- to UI (PixelRGB8) is also possible just change from fst to snd after the return
getCanvCol :: UI.Canvas -> UI.Point -> UI (UI.Color) 
getCanvCol canvas (x,y) = do  
-- str returns a string with comma separated values i.e. "255,0,255"  
str <- callFunction $ ffi ("(%1.getContext('2d').getImageData(%2,%3,1,1).data[0])+\
                            \\",\"+(%1.getContext('2d').getImageData(%2,%3,1,1).data[1])+\
                            \\",\"+(%1.getContext('2d').getImageData(%2,%3,1,1).data[2])") 
                            canvas x y
  return $ fst $ tripleToCol $ lsToRGB $ wordsWhen (==',') str
   where
   -- could also use splitOn
   wordsWhen     :: (Char -> Bool) -> String -> [String]
   wordsWhen p s =  case dropWhile p s of
                         "" -> []
                         s' -> w : wordsWhen p s''
                               where (w, s'') = break p s'
   -- take a list of strings and make a triple of ints 
   lsToRGB :: [String] -> (Int,Int,Int)
   lsToRGB (a:b:c:xs) = (read a, read b, read c)
   lsToRGB _          = (0,0,0) 
   -- make a triple of Int to Color needed
   tripleToCol :: (Int,Int,Int) -> (UI.Color, PixelRGB8)
   tripleToCol (r,g,b) = ((UI.RGB r g b),(PixelRGB8 r' g' b'))
     where (r',g',b') = (fromIntegral r,fromIntegral g,fromIntegral b)

1 ответ

Решение

(Автор здесь)

Начиная с threepenny-gui-0.5.0.0, в настоящее время нет предопределенной функции, которая могла бы сделать это. Однако вы можете использовать включенный JavaScript FFI для вызова функции JavaScript, которая возвращает нужное вам значение. Например, вот исходный код drawImage функция:

drawImage :: Element -> Vector -> Canvas -> UI ()
drawImage image (x,y) canvas =
    runFunction $ ffi "%1.getContext('2d').drawImage(%2,%3,%4)" canvas image x y

ffi Функция позволяет вызывать произвольную функцию JavaScript. Единственная проблема в том, что вам нужно будет привести результат к типу Color; на данный момент только пара типов как Int или же String поддерживаются как возвращаемые значения. Взгляните на исходный код для примеров.

Другие вопросы по тегам