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
поддерживаются как возвращаемые значения. Взгляните на исходный код для примеров.