Плохое исполнение холста Threepenny-gui

Я попытался нарисовать 100 анимированных кругов с помощью tripennt-gui. Это было странно, поэтому я сделал 1000, и проблемы были очевидны:

  • Я мог видеть рисунок (то есть холст был черным, а затем появились круги, затем он снова стал черным и т. Д.
  • Рисование заняло несколько секунд всего один раз (и он должен рисовать 50 раз в секунду (потому что таймер не позволит мне сделать 60)
  • каждый кадр занимал постепенно больше. после нескольких кадров это не закончится вообще.

это был мой код:

let draw (Circle c r (x:+y)) = do
        canv # set' UI.fillStyle (UI.htmlColor c)
        canv # UI.beginPath
        canv # UI.arc (x, y) r (-pi) pi
        canv # UI.closePath
        canv # UI.fill

let drawAll circles = do
        UI.clearCanvas canv
        ppos <- liftIO $ readIORef player
        draw (Circle "green" playerRadius ppos)
        mapM draw circles

Итак, я подумал, может быть, это генерирует неэффективный js-код, то есть разворачивает цикл (хорошо, несколько тысяч строк должны все еще генерироваться и выполняться довольно быстро), поэтому я преобразовал круги в Json и использовал ffi-функцию theepenny следующим образом:

circleToJson (Circle color radius (x:+y)) = "{c:\"" ++ color ++ "\",r:" ++ show radius ++ ",x:" ++ show x ++ ",y:" ++ show y ++ "},"

circlesToJson xs = "[" ++ (foldr (++) "" $ map circleToJson xs) ++ "]"

jsDrawFunc = "(function(canvas, circles){var ctx = canvas.getContext(\"2d\"); for (c of circles) {ctx.fillStyle=c.c; ctx.beginPath(); ctx.arc(c.x,c.y,c.r,0,2*Math.PI,true); ctx.fill();}})"

jsCanvasArg = "$(\"canvas\")[0],"

jsDrawAll circles = jsDrawFunc ++ "(" ++ jsCanvasArg ++ circlesToJson circles ++ ");"

и в событии таймера:

runFunction $ ffi $ jsDrawAll circles

-Теперь я больше не мог видеть рисунок (т.е. все появляется сразу). вместо этого firefox перестал отвечать на пользовательский ввод, пока рисование не было закончено (также, насколько я могу судить, время кадра было более согласованным)- edit: у меня не было пустых скобок после beginPath, поэтому все круги были соединены. теперь он снова мигает (при 100; при 1000 рисование занимает ~1 секунду и не реагирует на вводимые пользователем данные).

что говорит о том, что проблема в холсте. (что кажется подтвержденным после некоторого поиска)

Есть ли решение этой проблемы? (в идеале тот, который не предполагает использование другого gui-lib)

0 ответов

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