Elm - 逐字符显示文本(带停顿)
Elm - Displaying Text Character By Character (with pauses)
我是一名 Elm 新手,作为实验,我试图以特定速率一次显示一个字符的字符串。我已经完成了这么多。但是,每当程序遇到句末字符(句号、问号、问号等)时,我想在输出中引入一个短暂的停顿。但是,我不知道如何让这种暂停发生。
这是我的工作代码(当然减去停顿):
import Time (..)
import Signal (..)
import Text (..)
import String
stringOut : String -> Float -> Signal String
stringOut str rate = let
t = round <~ (foldp (+) 0 <| (flip (/) rate) <~ fps 60)
in flip String.left str <~ t
main = asText <~ stringOut "This is a string. Yeah?" (20*millisecond)
我最初的想法是我应该在 Time 模块中使用延迟函数,但我不确定在不以 Signal Signal Int
结尾的情况下将它放入何处。任何帮助,将不胜感激。谢谢!
信号问题的信号
Signal (Signal x)
的问题通常来自使用或定义 return Signal
的函数。一般情况下最好避免这些。
问题与解决方案
现在,如果我对你想要的系统的理解正确的话,你有一段静态文本,一个按一定速率滴答的计数器,每次滴答都应该显示文本的一个新字符,但在某些字符处表示结束-句子应该有一个停顿。
时间刻度是程序的基本输入。如果你不只是计算你在课文中读了多远,你可以引入停顿。您需要跟踪您是否处于暂停状态以及暂停了多长时间。每次你敲到一个句子的末尾时,你设置了停顿,每个滴答声要么在停顿处吃掉,要么继续偏移到文本中。
代码
这可能有点矫枉过正,但我将您的程序的输入和状态形式化并以通常可扩展的风格编写它:
import Time
import Time (Time)
import Signal
import Signal (Signal, (<~))
import Text (asText)
import String
import List
import Graphics.Element (Element)
type alias Input = ()
type alias State = { text : String, offset : Int, delay : Int }
initialState : State
initialState = { text = "This is a string. Yeah?", offset = 0, delay = 0 }
stdRate : Time
stdRate = 50 * Time.millisecond
stdDelay : Int
stdDelay = 5
endOfSentence : List String
endOfSentence = [".", "?", "!"]
input : Signal Input
input = always () <~ Time.every stdRate
state : Signal State
state = Signal.foldp (always step) initialState input
step : State -> State
step state =
let
newChar = String.slice state.offset (state.offset+1) state.text
in
if| state.delay > 0 -> { state | delay <- state.delay-1 }
| List.member newChar endOfSentence ->
{ state | offset <- state.offset + 1, delay <- stdDelay }
| otherwise -> { state | offset <- state.offset + 1 }
view : State -> String
view { text, offset } = String.left offset text
main : Signal Element
main = asText << view <~ state
我是一名 Elm 新手,作为实验,我试图以特定速率一次显示一个字符的字符串。我已经完成了这么多。但是,每当程序遇到句末字符(句号、问号、问号等)时,我想在输出中引入一个短暂的停顿。但是,我不知道如何让这种暂停发生。
这是我的工作代码(当然减去停顿):
import Time (..)
import Signal (..)
import Text (..)
import String
stringOut : String -> Float -> Signal String
stringOut str rate = let
t = round <~ (foldp (+) 0 <| (flip (/) rate) <~ fps 60)
in flip String.left str <~ t
main = asText <~ stringOut "This is a string. Yeah?" (20*millisecond)
我最初的想法是我应该在 Time 模块中使用延迟函数,但我不确定在不以 Signal Signal Int
结尾的情况下将它放入何处。任何帮助,将不胜感激。谢谢!
信号问题的信号
Signal (Signal x)
的问题通常来自使用或定义 return Signal
的函数。一般情况下最好避免这些。
问题与解决方案
现在,如果我对你想要的系统的理解正确的话,你有一段静态文本,一个按一定速率滴答的计数器,每次滴答都应该显示文本的一个新字符,但在某些字符处表示结束-句子应该有一个停顿。
时间刻度是程序的基本输入。如果你不只是计算你在课文中读了多远,你可以引入停顿。您需要跟踪您是否处于暂停状态以及暂停了多长时间。每次你敲到一个句子的末尾时,你设置了停顿,每个滴答声要么在停顿处吃掉,要么继续偏移到文本中。
代码
这可能有点矫枉过正,但我将您的程序的输入和状态形式化并以通常可扩展的风格编写它:
import Time
import Time (Time)
import Signal
import Signal (Signal, (<~))
import Text (asText)
import String
import List
import Graphics.Element (Element)
type alias Input = ()
type alias State = { text : String, offset : Int, delay : Int }
initialState : State
initialState = { text = "This is a string. Yeah?", offset = 0, delay = 0 }
stdRate : Time
stdRate = 50 * Time.millisecond
stdDelay : Int
stdDelay = 5
endOfSentence : List String
endOfSentence = [".", "?", "!"]
input : Signal Input
input = always () <~ Time.every stdRate
state : Signal State
state = Signal.foldp (always step) initialState input
step : State -> State
step state =
let
newChar = String.slice state.offset (state.offset+1) state.text
in
if| state.delay > 0 -> { state | delay <- state.delay-1 }
| List.member newChar endOfSentence ->
{ state | offset <- state.offset + 1, delay <- stdDelay }
| otherwise -> { state | offset <- state.offset + 1 }
view : State -> String
view { text, offset } = String.left offset text
main : Signal Element
main = asText << view <~ state