Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
TextField: typewriter effect — Gideros Forum

TextField: typewriter effect

piepie Member
edited January 2015 in Code snippets
Hi, I'm sharing my custom textField to have typewriter effect on TextFields.
Just add speed (in milliseconds) as third parameter to TextField.new().
Base code from GiderosCodingEasy by @ar2sawseen: If you notice something to do to improve it please tell me :)
 
function TextField:init(...)
	local arg = {...}
 
	--typewriter effect
		local function typewriter(str, speed)
			 local i = 0
			 local in_str = str
			 local str_length = string.len(in_str)
			 local typeSpeedTimer = Timer.new(speed, str_length)
 
				local function getString()
					if i <= str_length then
						i = i+1 --1 is the number of characters to add each time 
						local out_str = string.sub(in_str, 1, i)
						self._text:setText(out_str)
						self._text:setVisible(true)
					end
				end
 
			 typeSpeedTimer:addEventListener(Event.TIMER, getString)
			 typeSpeedTimer:start()
		end
 
	self._text = _TextField.new(...)
	self._text:setVisible(false)
	self:addChild(self._text)
	self._font = arg[1]
 
	--if string and speed are specified
	if arg[2] and arg[3] then
		local str = arg[2]
		local typewritespeed = arg[3] 
		typewriter(str, typewritespeed)
	end
 
	self._offsetX = 0
	self._offsetY = 0
 
	local baseX, baseY = self._text:getBounds(stage)
	self._text:setPosition(-baseX, -baseY)
end
usage:
local testtxt= TextField.new(nil, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", 10)
stage:addChild(testtxt)
:)>-

EDIT - update fix.
However, there is a speed limit I didn't think of, since refresh rate can't go faster than some value (cpu? gpu?, ram speed?).
To avoid this, you can change the increment of characters in function getString() - keep in mind that timer should run accordingly:
Timer.new((str_lenght/number of characters per timer call), speed) )

Likes: MoKaLux

+1 -1 (+1 / -0 )Share on Facebook

Comments

  • MoKaLuxMoKaLux Member
    edited November 2023

    Likes: pie

    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
    +1 -1 (+1 / -0 )Share on Facebook
  • I completely forgot I did that :D

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • piepie Member
    edited November 2023
    I would say that using # to get the length of a string is usually much faster than using string:len() at least on my laptop and if today I didn't make a big mistake in maths.
    test = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur."
    local astartTime = os.timer()
    local v = #test
    local aendTime = os.timer() - astartTime
     
    local bstartTime = os.timer()
    local q = test:len()
    local bendTime = os.timer() - bstartTime
     
    print("#", aendTime, ":len()", bendTime)
    this is my output
    #	1.9999970390927047e-07	:len()	6.999998731771484e-07
    Uploading finished.
    #	1.9999970390927047e-07	:len()	8.999995770864189e-07
    Uploading finished.
    #	1.9999970390927047e-07	:len()	8.000006346264854e-07
    Uploading finished.
    #	2.0000000011677344e-07	:len()	5.999999999062311e-07
    Uploading finished.
    #	5.999999999062311e-07	:len()	5.000000005139782e-07
    EDIT: Before anyone decides to use # instead of utf8.len keep in mind that

    there could be an issue if you use non ascii chars. You’d better use utf8.len and utf8.sub to deal with multi byte characters.

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • piepie Member
    edited November 2023
    And I don't know if someone might ever need it, but this is the same function that returns the string through a callback function. It might be used in conjunction with a standard TextField without the need to create a new Core object.
    txt = "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
     
    --f is the output "typed" text, if e is present the text has been completely typed.
    local function typewriter_callback(f, e)
    	--ie. myTextfield:setText(f)
    	print(f)
    	if e then
    		--finished
    		print(e)
    	end
    end
     
     
     
    local function typeWriterr(text, speed, char, callback)
    	local i = 0
    	local in_str = text
    	local str_length = in_str:len()
    	local typeSpeedTimer = Timer.new(speed or 100, str_length)
    	char = char or 1
     
    	local function getString()
    		if i <= str_length then
    			i += char -- number of characters to add each time
    			local out_str = in_str:sub(1, i)
    				if i == str_length then
    					callback(out_str, "END")
    				else
    					callback(out_str)
    				end
    		end
    	end
    	typeSpeedTimer:addEventListener(Event.TIMER, getString)
    	typeSpeedTimer:start()
    end
     
     
    typeWriterr(txt,nil,nil,typewriter_callback)

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • hgy29hgy29 Maintainer
    If I may say, there could be an issue if you use non ascii chars. You’d better use utf8.len and utf8.sub to deal with multi byte characters.

    Likes: MoKaLux, pie

    +1 -1 (+2 / -0 )Share on Facebook
Sign In or Register to comment.