gpt4 book ai didi

javascript - Fay、渲染循环和鼠标事件

转载 作者:行者123 更新时间:2023-11-30 05:41:00 25 4
gpt4 key购买 nike

序曲。我是 Haskell 和函数式编程的新手,但我忍不住用 Haskell 编码,因为它太令人兴奋了!因此,我的问题可能非常简单和/或微不足道。我仍在阅读“为您学习 Haskell 大有裨益”,而 Monad 仍在路上。

考虑以下行为:

  • 创建事件堆栈(简单数组)
    • 监听 mousemove 事件,当事件触发时,将它们压入堆栈
  • 运行渲染循环:
    • 使用requestAnimationFrame开始循环
    • 每次检查是否有事件堆叠
    • 从堆栈中获取最后一个事件,用它做一些东西并渲染
    • 清空堆栈
    • 请求下一帧

我无法实现的是如何从事件中获取感兴趣的值,例如pageX 或 clientX,看起来我必须对数据定义做一些事情,但我一直坚持下去。请帮忙。

附言我也无法理解如何检查外部函数的结果,例如当我尝试获取 DOM 元素时,结果可能是元素或 null,因此,比方说,getElById 是不纯的,我需要检查我得到的结果。如何实现?似乎我可以使用类似的东西:data Element = Null |元素 ... 然后模式匹配结果,但是如何让外部函数知道预期结果?

更新
这里是所需逻辑的工作示例:

module MouseTracker where

import FFI
import Prelude

data Element
data Event
type EventStack = [Event]
data Frame


consLog :: a -> Fay ()
consLog = ffi "console.log(%1)"


reqFrame :: (Frame -> Fay ()) -> Fay ()
reqFrame = ffi "requestAnimationFrame(%1)"


getDoc :: Fay Element
getDoc = ffi "document"


createEl :: String -> Fay Element
createEl = ffi "document.createElement(%1)"


elById :: String -> Fay Element
elById = ffi "document.getElementById(%1)"


elSetId :: Element -> String -> Fay ()
elSetId = ffi "%1.setAttribute('id',%2)"


elSetHtml :: Element -> String -> Fay ()
elSetHtml = ffi "%1.innerHTML = %2"


docBodyAppend :: Element -> Fay ()
docBodyAppend = ffi "document.body.appendChild(%1)"


elListenWith :: Element -> String -> (Event -> Fay ()) -> Fay ()
elListenWith = ffi "%1.addEventListener(%2, %3)"


winListenWith :: String -> (Event -> Fay ()) -> Fay ()
winListenWith = ffi "window.addEventListener(%1,%2)"


docListener :: String -> (Event -> Fay ()) -> Fay ()
docListener evtType fn = do
doc <- getDoc
elListenWith doc evtType fn




createTrace :: Fay ()
createTrace = do
div <- createEl "div"
docBodyAppend div
elSetId div "trace"


createStack :: Fay ()
createStack = ffi "window._eventStack = []"


getStack :: Fay EventStack
getStack = ffi "window._eventStack"


updateStack :: EventStack -> Fay ()
updateStack = ffi "window._eventStack = %1"


emptyStack :: Fay ()
emptyStack = createStack




listenMice :: Fay()
listenMice = docListener "mousemove" trackMouse
where trackMouse :: Event -> Fay ()
trackMouse evt = do
stk <- getStack
updateStack (evt:stk)


renderFrame :: Frame -> Fay ()
renderFrame frame = do
stack <- getStack
if length stack > 0
then (do
let e = head stack
traceEventCoord e)
else (do return ())
reqFrame renderFrame
emptyStack
where traceEventCoord :: Event -> Fay ()
traceEventCoord e = do
eX <- pageX e
eY <- pageY e
let str = show eX ++ " x " ++ show eY
trace <- elById "trace"
elSetHtml trace str


pageX :: Event -> Fay Int
pageX = ffi "%1['pageX']"
pageY :: Event -> Fay Int
pageY = ffi "%1['pageY']"


main = do
docListener "DOMContentLoaded" $ \ _ -> do
putStrLn "DOM ready"
createTrace
createStack
listenMice
reqFrame renderFrame

最佳答案

参见 this answer了解声明数据类型的不同方式及其权衡。您是自己创建事件还是包装 DOM 事件?如果您要包装,我建议使用 EmptyDataDecl。这意味着您没有针对每种事件的构造函数,但您可以添加为您检查该类型的函数。如果您创建自己的事件,则使用带构造函数的普通数据声明更有意义。

当包装 DOM 事件时,您最终会得到:

data Event
pageX :: Event -> Fay Int
pageX = ffi "%1['pageX']"

Fay 有 Nullable 类型来处理可为 null 的值:

getElementById :: String -> Nullable Element
getElementById = ffi "document['getElementById'](%1)"

对此有更详细的描述 on the wiki

关于javascript - Fay、渲染循环和鼠标事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20823763/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com