mirror of https://github.com/anoshenko/rui.git
Optimised animation
This commit is contained in:
parent
09031b9fa0
commit
2f3de8fce3
22
animation.go
22
animation.go
|
@ -120,6 +120,7 @@ type AnimatedProperty struct {
|
|||
type animationData struct {
|
||||
propertyList
|
||||
keyFramesName string
|
||||
usageCounter int
|
||||
}
|
||||
|
||||
// Animation interface is used to set animation parameters. Used properties:
|
||||
|
@ -132,6 +133,8 @@ type Animation interface {
|
|||
transitionCSS(buffer *strings.Builder, session Session)
|
||||
hasAnimatedProperty() bool
|
||||
animationName() string
|
||||
used()
|
||||
unused(session Session)
|
||||
}
|
||||
|
||||
func parseAnimation(obj DataObject) Animation {
|
||||
|
@ -179,6 +182,17 @@ func (animation *animationData) animationName() string {
|
|||
return animation.keyFramesName
|
||||
}
|
||||
|
||||
func (animation *animationData) used() {
|
||||
animation.usageCounter++
|
||||
}
|
||||
|
||||
func (animation *animationData) unused(session Session) {
|
||||
animation.usageCounter--
|
||||
if animation.usageCounter <= 0 && animation.keyFramesName != "" {
|
||||
session.removeAnimation(animation.keyFramesName)
|
||||
}
|
||||
}
|
||||
|
||||
func (animation *animationData) normalizeTag(tag string) string {
|
||||
tag = strings.ToLower(tag)
|
||||
if tag == Direction {
|
||||
|
@ -387,7 +401,7 @@ func (animation *animationData) animationCSS(session Session) string {
|
|||
}
|
||||
|
||||
animatedProps, ok := props.([]AnimatedProperty)
|
||||
if !ok {
|
||||
if !ok || len(animatedProps) == 0 {
|
||||
ErrorLog("Invalid animated properties.")
|
||||
return ""
|
||||
}
|
||||
|
@ -549,6 +563,7 @@ func (session *sessionData) registerAnimation(props []AnimatedProperty) string {
|
|||
|
||||
var cssBuilder cssStyleBuilder
|
||||
|
||||
cssBuilder.init(0)
|
||||
cssBuilder.startAnimation(name)
|
||||
|
||||
fromParams := Params{}
|
||||
|
@ -606,10 +621,7 @@ func (session *sessionData) registerAnimation(props []AnimatedProperty) string {
|
|||
cssBuilder.endAnimationFrame()
|
||||
|
||||
cssBuilder.endAnimation()
|
||||
|
||||
style := cssBuilder.finish()
|
||||
session.animationCSS += style
|
||||
session.addAnimationCSS(style)
|
||||
session.addAnimationCSS(cssBuilder.finish())
|
||||
|
||||
return name
|
||||
}
|
||||
|
|
|
@ -150,9 +150,11 @@ func (builder *cssValueBuilder) addValues(key, separator string, values ...strin
|
|||
}
|
||||
}
|
||||
|
||||
func (builder *cssStyleBuilder) init() {
|
||||
func (builder *cssStyleBuilder) init(kbSize int) {
|
||||
builder.buffer = allocStringBuilder()
|
||||
builder.buffer.Grow(16 * 1024)
|
||||
if kbSize > 0 {
|
||||
builder.buffer.Grow(kbSize * 1024)
|
||||
}
|
||||
}
|
||||
|
||||
func (builder *cssStyleBuilder) finish() string {
|
||||
|
@ -168,7 +170,7 @@ func (builder *cssStyleBuilder) finish() string {
|
|||
|
||||
func (builder *cssStyleBuilder) startMedia(rule string) {
|
||||
if builder.buffer == nil {
|
||||
builder.init()
|
||||
builder.init(0)
|
||||
}
|
||||
builder.buffer.WriteString(`@media screen`)
|
||||
builder.buffer.WriteString(rule)
|
||||
|
@ -178,7 +180,7 @@ func (builder *cssStyleBuilder) startMedia(rule string) {
|
|||
|
||||
func (builder *cssStyleBuilder) endMedia() {
|
||||
if builder.buffer == nil {
|
||||
builder.init()
|
||||
builder.init(0)
|
||||
}
|
||||
builder.buffer.WriteString(`}\n`)
|
||||
builder.media = false
|
||||
|
@ -192,7 +194,7 @@ func (builder *cssStyleBuilder) startStyle(name string) {
|
|||
}
|
||||
|
||||
if builder.buffer == nil {
|
||||
builder.init()
|
||||
builder.init(0)
|
||||
}
|
||||
if builder.media {
|
||||
builder.buffer.WriteString(`\t`)
|
||||
|
@ -210,7 +212,7 @@ func (builder *cssStyleBuilder) startStyle(name string) {
|
|||
|
||||
func (builder *cssStyleBuilder) endStyle() {
|
||||
if builder.buffer == nil {
|
||||
builder.init()
|
||||
builder.init(0)
|
||||
}
|
||||
if builder.media {
|
||||
builder.buffer.WriteString(`\t`)
|
||||
|
@ -220,7 +222,7 @@ func (builder *cssStyleBuilder) endStyle() {
|
|||
|
||||
func (builder *cssStyleBuilder) startAnimation(name string) {
|
||||
if builder.buffer == nil {
|
||||
builder.init()
|
||||
builder.init(0)
|
||||
}
|
||||
|
||||
builder.media = true
|
||||
|
@ -231,7 +233,7 @@ func (builder *cssStyleBuilder) startAnimation(name string) {
|
|||
|
||||
func (builder *cssStyleBuilder) endAnimation() {
|
||||
if builder.buffer == nil {
|
||||
builder.init()
|
||||
builder.init(0)
|
||||
}
|
||||
builder.buffer.WriteString(`}\n`)
|
||||
builder.media = false
|
||||
|
@ -239,7 +241,7 @@ func (builder *cssStyleBuilder) endAnimation() {
|
|||
|
||||
func (builder *cssStyleBuilder) startAnimationFrame(name string) {
|
||||
if builder.buffer == nil {
|
||||
builder.init()
|
||||
builder.init(0)
|
||||
}
|
||||
|
||||
builder.buffer.WriteString(`\t`)
|
||||
|
@ -249,7 +251,7 @@ func (builder *cssStyleBuilder) startAnimationFrame(name string) {
|
|||
|
||||
func (builder *cssStyleBuilder) endAnimationFrame() {
|
||||
if builder.buffer == nil {
|
||||
builder.init()
|
||||
builder.init(0)
|
||||
}
|
||||
builder.buffer.WriteString(`\t}\n`)
|
||||
}
|
||||
|
@ -257,7 +259,7 @@ func (builder *cssStyleBuilder) endAnimationFrame() {
|
|||
func (builder *cssStyleBuilder) add(key, value string) {
|
||||
if value != "" {
|
||||
if builder.buffer == nil {
|
||||
builder.init()
|
||||
builder.init(0)
|
||||
}
|
||||
if builder.media {
|
||||
builder.buffer.WriteString(`\t`)
|
||||
|
@ -276,7 +278,7 @@ func (builder *cssStyleBuilder) addValues(key, separator string, values ...strin
|
|||
}
|
||||
|
||||
if builder.buffer == nil {
|
||||
builder.init()
|
||||
builder.init(0)
|
||||
}
|
||||
if builder.media {
|
||||
builder.buffer.WriteString(`\t`)
|
||||
|
|
40
session.go
40
session.go
|
@ -143,7 +143,7 @@ type Session interface {
|
|||
finishUpdateScript(htmlID string)
|
||||
sendResponse()
|
||||
addAnimationCSS(css string)
|
||||
clearAnimation()
|
||||
removeAnimation(keyframe string)
|
||||
canvasStart(htmlID string)
|
||||
callCanvasFunc(funcName string, args ...any)
|
||||
createCanvasVar(funcName string, args ...any) any
|
||||
|
@ -464,14 +464,46 @@ func (session *sessionData) sendResponse() {
|
|||
}
|
||||
|
||||
func (session *sessionData) addAnimationCSS(css string) {
|
||||
session.animationCSS += css
|
||||
if session.bridge != nil {
|
||||
session.bridge.appendAnimationCSS(css)
|
||||
}
|
||||
}
|
||||
|
||||
func (session *sessionData) clearAnimation() {
|
||||
if session.bridge != nil {
|
||||
session.bridge.setAnimationCSS("")
|
||||
func (session *sessionData) removeAnimation(keyframe string) {
|
||||
css := session.animationCSS
|
||||
index := strings.Index(css, "@keyframes "+keyframe)
|
||||
if index < 0 {
|
||||
return
|
||||
}
|
||||
|
||||
start := strings.IndexRune(css[index:], '{')
|
||||
if start < 0 {
|
||||
return
|
||||
}
|
||||
|
||||
n := 1
|
||||
end := -1
|
||||
for i := start + index + 1; i < len(css); i++ {
|
||||
if css[i] == '}' {
|
||||
n--
|
||||
if n == 0 {
|
||||
end = i + 1
|
||||
if end < len(css) && css[end] == '\n' {
|
||||
end++
|
||||
}
|
||||
break
|
||||
}
|
||||
} else if css[i] == '{' {
|
||||
n++
|
||||
}
|
||||
}
|
||||
|
||||
if end > index {
|
||||
session.animationCSS = css[:index] + css[end:]
|
||||
if session.bridge != nil {
|
||||
session.bridge.setAnimationCSS(session.animationCSS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
theme.go
2
theme.go
|
@ -589,7 +589,7 @@ func (theme *theme) cssText(session Session) string {
|
|||
}
|
||||
|
||||
var builder cssStyleBuilder
|
||||
builder.init()
|
||||
builder.init(16)
|
||||
|
||||
styleList := func(styles map[string]ViewStyle) []string {
|
||||
ruiStyles := []string{}
|
||||
|
|
19
view.go
19
view.go
|
@ -341,6 +341,25 @@ func (view *viewData) set(tag string, value any) bool {
|
|||
}
|
||||
view.viewID = text
|
||||
|
||||
case AnimationTag:
|
||||
oldAnimations := []Animation{}
|
||||
if val, ok := view.properties[AnimationTag]; ok && val != nil {
|
||||
if animation, ok := val.([]Animation); ok {
|
||||
oldAnimations = animation
|
||||
}
|
||||
}
|
||||
|
||||
if !view.setAnimation(tag, value) {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, animation := range oldAnimations {
|
||||
animation.unused(view.session)
|
||||
}
|
||||
if view.created {
|
||||
viewPropertyChanged(view, tag)
|
||||
}
|
||||
|
||||
case TabIndex, "tab-index":
|
||||
if !view.setIntProperty(tag, value) {
|
||||
return false
|
||||
|
|
|
@ -143,18 +143,26 @@ func (style *viewStyle) setTransition(tag string, value any) bool {
|
|||
}
|
||||
|
||||
func (style *viewStyle) setAnimation(tag string, value any) bool {
|
||||
|
||||
set := func(animations []Animation) {
|
||||
style.properties[tag] = animations
|
||||
for _, animation := range animations {
|
||||
animation.used()
|
||||
}
|
||||
}
|
||||
|
||||
switch value := value.(type) {
|
||||
case Animation:
|
||||
style.properties[tag] = []Animation{value}
|
||||
set([]Animation{value})
|
||||
return true
|
||||
|
||||
case []Animation:
|
||||
style.properties[tag] = value
|
||||
set(value)
|
||||
return true
|
||||
|
||||
case DataObject:
|
||||
if animation := parseAnimation(value); animation.hasAnimatedProperty() {
|
||||
style.properties[tag] = []Animation{animation}
|
||||
set([]Animation{animation})
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -174,7 +182,7 @@ func (style *viewStyle) setAnimation(tag string, value any) bool {
|
|||
}
|
||||
}
|
||||
if result && len(animations) > 0 {
|
||||
style.properties[tag] = animations
|
||||
set(animations)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -284,7 +284,6 @@ func (bridge *webBridge) removeProperty(htmlID, property string) {
|
|||
}
|
||||
|
||||
func (bridge *webBridge) appendAnimationCSS(css string) {
|
||||
//bridge.callFunc("appendAnimationCSS", css)
|
||||
bridge.writeMessage(`{
|
||||
let styles = document.getElementById('ruiAnimations');
|
||||
if (styles) {
|
||||
|
@ -294,7 +293,6 @@ func (bridge *webBridge) appendAnimationCSS(css string) {
|
|||
}
|
||||
|
||||
func (bridge *webBridge) setAnimationCSS(css string) {
|
||||
//bridge.callFunc("setAnimationCSS", css)
|
||||
bridge.writeMessage(`{
|
||||
let styles = document.getElementById('ruiAnimations');
|
||||
if (styles) {
|
||||
|
|
Loading…
Reference in New Issue