query function

query returns the first element matching sel.

Parameters:

  • sel string

Returns:

  • js.Value
Show/Hide Function Body
{
	return dom.Doc().Query(sel).Value
}

animate function

animate drives a requestAnimationFrame loop for the given duration and

invokes step with the current progress (0..1).

Parameters:

  • el js.Value
  • duration time.Duration
  • step func(p float64)
Show/Hide Function Body
{
	start := js.Performance().Call("now").Float()
	total := float64(duration.Milliseconds())
	var cb js.Func
	cb = js.FuncOf(func(this js.Value, args []js.Value) any {
		now := js.Performance().Call("now").Float()
		p := (now - start) / total
		if p > 1 {
			p = 1
		}
		step(p)
		if p < 1 {
			js.RequestAnimationFrame(cb)
		} else {
			cb.Release()
		}
		return nil
	})
	js.RequestAnimationFrame(cb)
}

Keyframes function

Keyframes leverages the Web Animations API to animate the selected element

using the provided keyframes and options. The returned value is the

underlying Animation object, allowing further control if needed.

Parameters:

  • sel string
  • keyframes []map[string]any
  • options map[string]any

Returns:

  • js.Value
Show/Hide Function Body
{
	el := query(sel)

	frames := make([]any, len(keyframes))
	for i, f := range keyframes {
		frames[i] = f
	}

	opts := make(map[string]any, len(options))
	for k, v := range options {
		switch n := v.(type) {
		case int:
			opts[k] = float64(n)
		case int32:
			opts[k] = float64(n)
		case int64:
			opts[k] = float64(n)
		default:
			opts[k] = v
		}
	}

	return el.Call("animate", frames, opts)
}

Translate function

Translate moves the element selected by sel from the starting coordinates

to the destination using a translate transform.

Parameters:

  • sel string
  • fromX float64
  • fromY float64
  • toX float64
  • toY float64
  • duration time.Duration
Show/Hide Function Body
{
	el := query(sel)
	animate(el, duration, func(p float64) {
		x := fromX + (toX-fromX)*p
		y := fromY + (toY-fromY)*p
		el.Get("style").Set("transform", fmt.Sprintf("translate(%fpx,%fpx)", x, y))
	})
}

Fade function

Fade transitions the element's opacity from 'from' to 'to'.

Parameters:

  • sel string
  • from float64
  • to float64
  • duration time.Duration
Show/Hide Function Body
{
	el := query(sel)
	animate(el, duration, func(p float64) {
		val := from + (to-from)*p
		el.Get("style").Set("opacity", val)
	})
}

Scale function

Scale scales the element from the starting factor to the ending factor.

Parameters:

  • sel string
  • from float64
  • to float64
  • duration time.Duration
Show/Hide Function Body
{
	el := query(sel)
	animate(el, duration, func(p float64) {
		val := from + (to-from)*p
		el.Get("style").Set("transform", fmt.Sprintf("scale(%f)", val))
	})
}

ColorCycle function

ColorCycle iterates the element's background color through the provided

list over the given duration.

Parameters:

  • sel string
  • colors []string
  • duration time.Duration
Show/Hide Function Body
{
	el := query(sel)
	stepDur := duration / time.Duration(len(colors))
	go func() {
		for _, c := range colors {
			el.Get("style").Set("background", c)
			<-time.After(stepDur)
		}
	}()
}

TestKeyFrameMap function

TestKeyFrameMap verifies basic operations on KeyFrameMap.

Parameters:

  • t *testing.T
Show/Hide Function Body
{
	k := NewKeyFrame()
	if len(k) != 0 {
		t.Fatalf("expected empty keyframe map, got %d entries", len(k))
	}

	k.Add("opacity", 0.5).Add("transform", "scale(2)")
	if v, ok := k["opacity"]; !ok || v != 0.5 {
		t.Fatalf("expected opacity 0.5, got %v", v)
	}

	k.Delete("opacity")
	if _, ok := k["opacity"]; ok {
		t.Fatalf("expected opacity key removed")
	}
}

Scene struct

Fields:

  • el (js.Value)
  • keyframes ([]map[string]any)
  • options (map[string]any)

CinemaBuilder struct

Fields:

  • root (js.Value)
  • scenes ([]*Scene)
  • current (*Scene)
  • scripts ([]func())
  • video (js.Value)
  • audio (js.Value)
  • loop (int)
  • start (func())
  • end (func())

Methods:

AddScene


Parameters:
  • sel string
  • opts map[string]any

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	s := &Scene{el: query(sel), options: opts}
	c.scenes = append(c.scenes, s)
	c.current = s
	return c
}

AddKeyFrame

AddKeyFrame appends a keyframe built with KeyFrameMap to the current scene.

For more advanced scenarios a raw map can be supplied using AddKeyFrameMap.


Parameters:
  • frame KeyFrameMap
  • offset float64

Returns:
  • *CinemaBuilder

References:


Show/Hide Method Body
{
	if c.current == nil {
		c.AddScene("", nil)
	}
	frame["offset"] = offset
	c.current.keyframes = append(c.current.keyframes, map[string]any(frame))
	return c
}

AddKeyFrameMap

AddKeyFrameMap appends a raw map as keyframe to the current scene and is kept

for backwards compatibility and advanced use cases.


Parameters:
  • frame map[string]any
  • offset float64

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.current == nil {
		c.AddScene("", nil)
	}
	frame["offset"] = offset
	c.current.keyframes = append(c.current.keyframes, frame)
	return c
}

AddTransition


Parameters:
  • props map[string]any
  • duration time.Duration

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	frames := []map[string]any{
		{"offset": 0},
		{"offset": 1},
	}
	for k, v := range props {
		frames[0][k] = v
		frames[1][k] = v
	}
	c.current.keyframes = append(c.current.keyframes, frames...)
	if c.current.options == nil {
		c.current.options = map[string]any{}
	}
	c.current.options["duration"] = duration.Milliseconds()
	return c
}

AddSequence


Parameters:
  • fn func(b *CinemaBuilder)

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	fn(c)
	return c
}

AddParallel


Parameters:
  • fn func(b *CinemaBuilder)

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	go fn(c)
	return c
}

AddPause


Parameters:
  • d time.Duration

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	c.scripts = append(c.scripts, func() { <-time.After(d) })
	return c
}

AddLoop


Parameters:
  • count int

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if count <= 0 {
		c.loop = 1
	} else {
		c.loop = count
	}
	return c
}

AddVideo


Parameters:
  • sel string

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	c.video = query(sel)
	return c
}

PlayVideo


Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.video.Truthy() {
		c.video.Call("play")
	}
	return c
}

PauseVideo


Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.video.Truthy() {
		c.video.Call("pause")
	}
	return c
}

StopVideo


Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.video.Truthy() {
		c.video.Call("pause")
		c.video.Set("currentTime", 0)
	}
	return c
}

SeekVideo


Parameters:
  • t float64

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.video.Truthy() {
		c.video.Set("currentTime", t)
	}
	return c
}

SetPlaybackRate


Parameters:
  • rate float64

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.video.Truthy() {
		c.video.Set("playbackRate", rate)
	}
	return c
}

SetVolume


Parameters:
  • v float64

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.video.Truthy() {
		c.video.Set("volume", v)
	}
	return c
}

MuteVideo


Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.video.Truthy() {
		c.video.Set("muted", true)
	}
	return c
}

UnmuteVideo


Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.video.Truthy() {
		c.video.Set("muted", false)
	}
	return c
}

AddSubtitle


Parameters:
  • kind string
  • label string
  • srcLang string
  • src string

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.video.Truthy() {
		track := js.Document().Call("createElement", "track")
		track.Set("kind", kind)
		track.Set("label", label)
		track.Set("srclang", srcLang)
		track.Set("src", src)
		c.video.Call("appendChild", track)
	}
	return c
}

AddAudio


Parameters:
  • src string

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	audio := js.Document().Call("createElement", "audio")
	audio.Set("src", src)
	audio.Set("controls", true)
	c.root.Call("appendChild", audio)
	c.audio = audio
	return c
}

PlayAudio


Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.audio.Truthy() {
		c.audio.Set("currentTime", 0)
		c.audio.Call("play")
	}
	return c
}

PauseAudio


Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.audio.Truthy() {
		c.audio.Call("pause")
	}
	return c
}

StopAudio


Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.audio.Truthy() {
		c.audio.Call("pause")
		c.audio.Set("currentTime", 0)
	}
	return c
}

SetAudioVolume


Parameters:
  • v float64

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.audio.Truthy() {
		c.audio.Set("volume", v)
	}
	return c
}

MuteAudio


Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.audio.Truthy() {
		c.audio.Set("muted", true)
	}
	return c
}

UnmuteAudio


Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.audio.Truthy() {
		c.audio.Set("muted", false)
	}
	return c
}

BindProgress


Parameters:
  • sel string

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	if c.video.Truthy() {
		bar := query(sel)
		if bar.Truthy() {
			bar.Set("max", 100)

			update := func(js.Value) {
				dur := c.video.Get("duration").Float()
				if dur > 0 {
					cur := c.video.Get("currentTime").Float()
					bar.Set("value", cur/dur*100)
				}
			}
			input := func(js.Value) {
				dur := c.video.Get("duration").Float()
				if dur > 0 {
					valStr := bar.Get("value").String()
					if val, err := strconv.ParseFloat(valStr, 64); err == nil {
						c.video.Set("currentTime", val/100*dur)
					}
				}
			}

			events.OnTimeUpdate(c.video, update)
			events.OnInput(bar, input)
		}
	}
	return c
}

AddScripted


Parameters:
  • fn func(el js.Value)

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	c.scripts = append(c.scripts, func() { fn(c.root) })
	return c
}

OnStart


Parameters:
  • fn func()

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	c.start = fn
	return c
}

OnEnd


Parameters:
  • fn func()

Returns:
  • *CinemaBuilder

Show/Hide Method Body
{
	c.end = fn
	return c
}

Play


Show/Hide Method Body
{
	for i := 0; i < c.loop; i++ {
		if c.start != nil {
			c.start()
		}
		for _, s := range c.scenes {
			if len(s.keyframes) > 0 {
				KeyframesForScene(s)
			}
		}
		for _, fn := range c.scripts {
			fn()
		}
		if c.end != nil {
			c.end()
		}
	}
}

NewCinemaBuilder function

Parameters:

  • sel string

Returns:

  • *CinemaBuilder
Show/Hide Function Body
{
	return &CinemaBuilder{root: query(sel), loop: 1}
}

KeyframesForScene function

Parameters:

  • s *Scene

Returns:

  • js.Value
Show/Hide Function Body
{
	// convert frames to []any to ensure proper conversion to JS values
	frames := make([]any, len(s.keyframes))
	for i, f := range s.keyframes {
		frames[i] = f
	}

	// convert option numeric types to float64 for syscall/js compatibility
	opts := make(map[string]any, len(s.options))
	for k, v := range s.options {
		switch n := v.(type) {
		case int:
			opts[k] = float64(n)
		case int32:
			opts[k] = float64(n)
		case int64:
			opts[k] = float64(n)
		default:
			opts[k] = v
		}
	}

	return s.el.Call("animate", frames, opts)
}

KeyFrameMap type

KeyFrameMap simplifies building keyframe properties without

dealing with raw map structures.

Type Definition:

map[string]any

NewKeyFrame function

NewKeyFrame returns an empty KeyFrameMap.

Returns:

  • KeyFrameMap

References:

Show/Hide Function Body
{
	return KeyFrameMap{}
}

fmt import

Import example:

import "fmt"

time import

Import example:

import "time"

github.com/rfwlab/rfw/v1/dom import

Import example:

import "github.com/rfwlab/rfw/v1/dom"

Imported as:

dom

github.com/rfwlab/rfw/v1/js import

Import example:

import "github.com/rfwlab/rfw/v1/js"

Imported as:

js

testing import

Import example:

import "testing"

strconv import

Import example:

import "strconv"

time import

Import example:

import "time"

github.com/rfwlab/rfw/v1/events import

Import example:

import "github.com/rfwlab/rfw/v1/events"

Imported as:

events

github.com/rfwlab/rfw/v1/js import

Import example:

import "github.com/rfwlab/rfw/v1/js"

Imported as:

js