rui_orig/transform.go

740 lines
26 KiB
Go
Raw Normal View History

2021-09-07 17:36:50 +03:00
package rui
import (
"fmt"
"math"
"strings"
)
// Constants for [TransformProperty] specific properties
2021-09-07 17:36:50 +03:00
const (
// Transform is the constant for "transform" property tag.
2024-11-13 12:56:39 +03:00
//
2024-12-05 20:15:39 +03:00
// Used by View.
// Specify translation, scale and rotation over x, y and z axes as well as a distortion of a view along x and y axes.
2024-11-13 12:56:39 +03:00
//
2024-12-05 20:15:39 +03:00
// Supported types: TransformProperty, string.
2024-11-13 12:56:39 +03:00
//
2024-12-05 20:15:39 +03:00
// See TransformProperty description for more details.
2024-11-13 12:56:39 +03:00
//
// Conversion rules:
2024-12-05 20:15:39 +03:00
// - TransformProperty - stored as is, no conversion performed.
// - string - string representation of TransformProperty interface. Example: "_{translate-x = 10px, scale-y = 1.1}".
Transform PropertyName = "transform"
2024-11-13 12:56:39 +03:00
// Perspective is the constant for "perspective" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
2024-11-13 12:56:39 +03:00
// Distance between the z-plane and the user in order to give a 3D-positioned element some perspective. Each 3D element
// with z > 0 becomes larger, each 3D-element with z < 0 becomes smaller. The default value is 0 (no 3D effects).
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-13 12:56:39 +03:00
Perspective PropertyName = "perspective"
// PerspectiveOriginX is the constant for "perspective-origin-x" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View.
2024-11-13 12:56:39 +03:00
// x-coordinate of the position at which the viewer is looking. It is used as the vanishing point by the "perspective"
// property. The default value is 50%.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-13 12:56:39 +03:00
PerspectiveOriginX PropertyName = "perspective-origin-x"
// PerspectiveOriginY is the constant for "perspective-origin-y" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View.
2024-11-13 12:56:39 +03:00
// y-coordinate of the position at which the viewer is looking. It is used as the vanishing point by the "perspective"
// property. The default value is 50%.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-13 12:56:39 +03:00
PerspectiveOriginY PropertyName = "perspective-origin-y"
// BackfaceVisible is the constant for "backface-visibility" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View.
// Controls whether the back face of a view is visible when turned towards the user. Default value is true.
//
2024-12-05 20:15:39 +03:00
// Supported types: bool, int, string.
//
// Values:
2024-12-05 20:15:39 +03:00
// - true, 1, "true", "yes", "on", "1" - Back face is visible when turned towards the user.
// - false, 0, "false", "no", "off", "0" - Back face is hidden, effectively making the view invisible when turned away from the user.
2024-11-13 12:56:39 +03:00
BackfaceVisible PropertyName = "backface-visibility"
// TransformOriginX is the constant for "transform-origin-x" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View.
// x-coordinate of the point around which a view transformation is applied. The default value is 50%.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
TransformOriginX PropertyName = "transform-origin-x"
// TransformOriginY is the constant for "transform-origin-y" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View.
// y-coordinate of the point around which a view transformation is applied. The default value is 50%.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
TransformOriginY PropertyName = "transform-origin-y"
// TransformOriginZ is the constant for "transform-origin-z" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View.
// z-coordinate of the point around which a view transformation is applied. The default value is 50%.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
TransformOriginZ PropertyName = "transform-origin-z"
// TranslateX is the constant for "translate-x" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
//
// x-axis translation value of a 2D/3D translation.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-13 12:56:39 +03:00
TranslateX PropertyName = "translate-x"
// TranslateY is the constant for "translate-y" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
//
// x-axis translation value of a 2D/3D translation.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-13 12:56:39 +03:00
TranslateY PropertyName = "translate-y"
// TranslateZ is the constant for "translate-z" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
//
// z-axis translation value of a 3D translation.
//
2024-12-05 20:15:39 +03:00
// Supported types: SizeUnit, SizeFunc, string, float, int.
//
2024-12-05 20:15:39 +03:00
// Internal type is SizeUnit, other types converted to it during assignment.
// See SizeUnit description for more details.
2024-11-13 12:56:39 +03:00
TranslateZ PropertyName = "translate-z"
// ScaleX is the constant for "scale-x" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
//
2024-11-13 12:56:39 +03:00
// x-axis scaling value of a 2D/3D scale. The original scale is 1. Values between 0 and 1 are used to decrease original
// scale, more than 1 - to increase. The default value is 1.
//
2024-12-05 20:15:39 +03:00
// Supported types: float, int, string.
//
2024-12-05 20:15:39 +03:00
// Internal type is float, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
ScaleX PropertyName = "scale-x"
// ScaleY is the constant for "scale-y" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
//
2024-11-13 12:56:39 +03:00
// y-axis scaling value of a 2D/3D scale. The original scale is 1. Values between 0 and 1 are used to decrease original
// scale, more than 1 - to increase. The default value is 1.
//
2024-12-05 20:15:39 +03:00
// Supported types: float, int, string.
//
2024-12-05 20:15:39 +03:00
// Internal type is float, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
ScaleY PropertyName = "scale-y"
// ScaleZ is the constant for "scale-z" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
//
2024-11-13 12:56:39 +03:00
// z-axis scaling value of a 3D scale. The original scale is 1. Values between 0 and 1 are used to decrease original
// scale, more than 1 - to increase. The default value is 1.
//
2024-12-05 20:15:39 +03:00
// Supported types: float, int, string.
//
2024-12-05 20:15:39 +03:00
// Internal type is float, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
ScaleZ PropertyName = "scale-z"
// Rotate is the constant for "rotate" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
//
// Angle of the view rotation. A positive angle denotes a clockwise rotation, a negative angle a counter-clockwise.
//
2024-12-05 20:15:39 +03:00
// Supported types: AngleUnit, string, float, int.
//
2024-12-05 20:15:39 +03:00
// Internal type is AngleUnit, other types will be converted to it during assignment.
// See AngleUnit description for more details.
//
// Conversion rules:
2024-12-05 20:15:39 +03:00
// - AngleUnit - stored as is, no conversion performed.
// - string - must contain string representation of AngleUnit. If numeric value will be provided without any suffix then AngleUnit with value and Radian value type will be created.
// - float - a new AngleUnit value will be created with Radian as a type.
// - int - a new AngleUnit value will be created with Radian as a type.
2024-11-13 12:56:39 +03:00
Rotate PropertyName = "rotate"
// RotateX is the constant for "rotate-x" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
//
// x-coordinate of the vector denoting the axis of rotation in range 0 to 1.
//
2024-12-05 20:15:39 +03:00
// Supported types: float, int, string.
//
2024-12-05 20:15:39 +03:00
// Internal type is float, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
RotateX PropertyName = "rotate-x"
// RotateY is the constant for "rotate-y" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
//
// y-coordinate of the vector denoting the axis of rotation in range 0 to 1.
//
2024-12-05 20:15:39 +03:00
// Supported types: float, int, string.
//
2024-12-05 20:15:39 +03:00
// Internal type is float, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
RotateY PropertyName = "rotate-y"
// RotateZ is the constant for "rotate-z" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
//
// z-coordinate of the vector denoting the axis of rotation in range 0 to 1.
//
2024-12-05 20:15:39 +03:00
// Supported types: float, int, string.
//
2024-12-05 20:15:39 +03:00
// Internal type is float, other types converted to it during assignment.
2024-11-13 12:56:39 +03:00
RotateZ PropertyName = "rotate-z"
// SkewX is the constant for "skew-x" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
//
// Angle to use to distort the element along the abscissa. The default value is 0.
//
2024-12-05 20:15:39 +03:00
// Supported types: AngleUnit, string, float, int.
//
2024-12-05 20:15:39 +03:00
// Internal type is AngleUnit, other types will be converted to it during assignment.
// See AngleUnit description for more details.
//
// Conversion rules:
2024-12-05 20:15:39 +03:00
// - AngleUnit - stored as is, no conversion performed.
// - string - must contain string representation of AngleUnit. If numeric value will be provided without any suffix then AngleUnit with value and Radian value type will be created.
// - float - a new AngleUnit value will be created with Radian as a type.
// - int - a new AngleUnit value will be created with Radian as a type.
2024-11-13 12:56:39 +03:00
SkewX PropertyName = "skew-x"
// SkewY is the constant for "skew-y" property tag.
//
2024-12-05 20:15:39 +03:00
// Used by View, TransformProperty.
//
// Angle to use to distort the element along the ordinate. The default value is 0.
//
2024-12-05 20:15:39 +03:00
// Supported types: AngleUnit, string, float, int.
//
2024-12-05 20:15:39 +03:00
// Internal type is AngleUnit, other types will be converted to it during assignment.
// See AngleUnit description for more details.
//
// Conversion rules:
2024-12-05 20:15:39 +03:00
// - AngleUnit - stored as is, no conversion performed.
// - string - must contain string representation of AngleUnit. If numeric value will be provided without any suffix then AngleUnit with value and Radian value type will be created.
// - float - a new AngleUnit value will be created with Radian as a type.
// - int - a new AngleUnit value will be created with Radian as a type.
2024-11-13 12:56:39 +03:00
SkewY PropertyName = "skew-y"
2021-09-07 17:36:50 +03:00
)
// TransformProperty interface specifies view transformation parameters: the x-, y-, and z-axis translation values,
// the x-, y-, and z-axis scaling values, the angle to use to distort the element along the abscissa and ordinate,
// the angle of the view rotation.
2024-12-05 20:15:39 +03:00
//
2024-11-13 12:56:39 +03:00
// Valid property tags: Perspective ("perspective"), TranslateX ("translate-x"), TranslateY ("translate-y"), TranslateZ ("translate-z"),
// ScaleX ("scale-x"), ScaleY ("scale-y"), ScaleZ ("scale-z"), Rotate ("rotate"), RotateX ("rotate-x"),
// RotateY ("rotate-y"), RotateZ ("rotate-z"), SkewX ("skew-x"), and SkewY ("skew-y")
type TransformProperty interface {
Properties
fmt.Stringer
stringWriter
2024-11-13 12:56:39 +03:00
transformCSS(session Session) string
2024-12-02 15:47:06 +03:00
getSkew(session Session) (AngleUnit, AngleUnit, bool)
getTranslate(session Session) (SizeUnit, SizeUnit, SizeUnit)
}
type transformPropertyData struct {
2024-11-13 12:56:39 +03:00
dataProperty
}
// NewTransform creates a new transform property data and return its interface
2024-12-05 20:15:39 +03:00
//
// The following properties can be used:
//
// Perspective ("perspective"), TranslateX ("translate-x"), TranslateY ("translate-y"), TranslateZ ("translate-z"),
// ScaleX ("scale-x"), ScaleY ("scale-y"), ScaleZ ("scale-z"), Rotate ("rotate"), RotateX ("rotate-x"),
// RotateY ("rotate-y"), RotateZ ("rotate-z"), SkewX ("skew-x"), and SkewY ("skew-y")
func NewTransformProperty(params Params) TransformProperty {
transform := new(transformPropertyData)
2024-11-13 12:56:39 +03:00
transform.init()
for tag, value := range params {
transform.Set(tag, value)
}
return transform
}
func (transform *transformPropertyData) init() {
2024-11-13 12:56:39 +03:00
transform.dataProperty.init()
transform.normalize = normalizeTransformTag
2024-11-13 12:56:39 +03:00
transform.set = transformSet
transform.supportedProperties = []PropertyName{
RotateX, RotateY, RotateZ, Rotate, SkewX, SkewY, ScaleX, ScaleY, ScaleZ,
Perspective, TranslateX, TranslateY, TranslateZ,
}
}
func normalizeTransformTag(tag PropertyName) PropertyName {
tag = defaultNormalize(tag)
name := string(tag)
if strings.HasPrefix(name, "push-") {
tag = PropertyName(name[5:])
}
return tag
}
func (transform *transformPropertyData) String() string {
2024-11-13 12:56:39 +03:00
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
transform.writeString(buffer, "")
return buffer.String()
}
func (transform *transformPropertyData) writeString(buffer *strings.Builder, indent string) {
2024-11-13 12:56:39 +03:00
buffer.WriteString("_{ ")
comma := false
for _, tag := range transform.supportedProperties {
if value, ok := transform.properties[tag]; ok {
if comma {
buffer.WriteString(", ")
}
buffer.WriteString(string(tag))
buffer.WriteString(" = ")
writePropertyValue(buffer, tag, value, indent)
comma = true
}
}
buffer.WriteString(" }")
}
func transformSet(properties Properties, tag PropertyName, value any) []PropertyName {
switch tag {
case RotateX, RotateY, RotateZ:
return setFloatProperty(properties, tag, value, 0, 1)
case Rotate, SkewX, SkewY:
return setAngleProperty(properties, tag, value)
case ScaleX, ScaleY, ScaleZ:
return setFloatProperty(properties, tag, value, -math.MaxFloat64, math.MaxFloat64)
case Perspective, TranslateX, TranslateY, TranslateZ:
return setSizeProperty(properties, tag, value)
}
return nil
}
func valueToTransformProperty(value any) TransformProperty {
parseObject := func(obj DataObject) TransformProperty {
transform := NewTransformProperty(nil)
ok := true
for i := 0; i < obj.PropertyCount(); i++ {
if prop := obj.Property(i); prop.Type() == TextNode {
2024-11-13 12:56:39 +03:00
if !transform.Set(PropertyName(prop.Tag()), prop.Text()) {
ok = false
}
} else {
ok = false
}
}
2024-11-13 12:56:39 +03:00
if !ok && transform.empty() {
return nil
}
return transform
}
switch value := value.(type) {
case TransformProperty:
return value
case DataObject:
return parseObject(value)
case DataNode:
if obj := value.Object(); obj != nil {
return parseObject(obj)
}
case string:
if obj := ParseDataText(value); obj != nil {
return parseObject(obj)
}
}
return nil
}
func setTransformProperty(properties Properties, tag PropertyName, value any) bool {
if transform := valueToTransformProperty(value); transform != nil {
properties.setRaw(tag, transform)
return true
}
notCompatibleType(tag, value)
return false
}
func getTransformProperty(properties Properties, tag PropertyName) TransformProperty {
if val := properties.getRaw(tag); val != nil {
if transform, ok := val.(TransformProperty); ok {
return transform
}
}
return nil
}
func setTransformPropertyElement(properties Properties, tag, transformTag PropertyName, value any) []PropertyName {
srcTag := tag
tag = normalizeTransformTag(tag)
switch tag {
2024-11-13 12:56:39 +03:00
case Perspective, RotateX, RotateY, RotateZ, Rotate, SkewX, SkewY, ScaleX, ScaleY, ScaleZ, TranslateX, TranslateY, TranslateZ:
var result []PropertyName = nil
if transform := getTransformProperty(properties, transformTag); transform != nil {
if result = transformSet(transform, tag, value); result != nil {
result = []PropertyName{srcTag, transformTag}
2024-11-13 12:56:39 +03:00
}
} else {
transform := NewTransformProperty(nil)
if result = transformSet(transform, tag, value); result != nil {
properties.setRaw(transformTag, transform)
result = []PropertyName{srcTag, transformTag}
}
}
return result
}
ErrorLogF(`"TransformProperty" interface does not support the "%s" property`, tag)
2024-11-13 12:56:39 +03:00
return nil
}
2021-09-07 17:36:50 +03:00
func getPerspectiveOrigin(style Properties, session Session) (SizeUnit, SizeUnit) {
x, _ := sizeProperty(style, PerspectiveOriginX, session)
y, _ := sizeProperty(style, PerspectiveOriginY, session)
return x, y
}
func getTransformOrigin(style Properties, session Session) (SizeUnit, SizeUnit, SizeUnit) {
x, _ := sizeProperty(style, TransformOriginX, session)
y, _ := sizeProperty(style, TransformOriginY, session)
z, _ := sizeProperty(style, TransformOriginZ, session)
2021-09-07 17:36:50 +03:00
return x, y, z
}
func (transform *transformPropertyData) getSkew(session Session) (AngleUnit, AngleUnit, bool) {
skewX, okX := angleProperty(transform, SkewX, session)
skewY, okY := angleProperty(transform, SkewY, session)
return skewX, skewY, okX || okY
2021-09-07 17:36:50 +03:00
}
func (transform *transformPropertyData) getTranslate(session Session) (SizeUnit, SizeUnit, SizeUnit) {
x, _ := sizeProperty(transform, TranslateX, session)
y, _ := sizeProperty(transform, TranslateY, session)
z, _ := sizeProperty(transform, TranslateZ, session)
2021-09-07 17:36:50 +03:00
return x, y, z
}
func (transform *transformPropertyData) transformCSS(session Session) string {
2021-09-07 17:36:50 +03:00
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
2024-11-13 12:56:39 +03:00
if perspective, ok := sizeProperty(transform, Perspective, session); ok && perspective.Type != Auto && perspective.Value != 0 {
buffer.WriteString(`perspective(`)
buffer.WriteString(perspective.cssString("0", session))
buffer.WriteString(") ")
}
skewX, skewY, skewOK := transform.getSkew(session)
if skewOK {
2021-09-07 17:36:50 +03:00
buffer.WriteString(`skew(`)
buffer.WriteString(skewX.cssString())
buffer.WriteRune(',')
buffer.WriteString(skewY.cssString())
2024-11-13 12:56:39 +03:00
buffer.WriteString(") ")
2021-09-07 17:36:50 +03:00
}
x, y, z := transform.getTranslate(session)
2024-11-13 12:56:39 +03:00
if z.Type != Auto && z.Value != 0 {
buffer.WriteString(`translate3d(`)
buffer.WriteString(x.cssString("0", session))
buffer.WriteRune(',')
buffer.WriteString(y.cssString("0", session))
buffer.WriteRune(',')
buffer.WriteString(z.cssString("0", session))
buffer.WriteString(") ")
} else if (x.Type != Auto && x.Value != 0) || (y.Type != Auto && y.Value != 0) {
buffer.WriteString(`translate(`)
buffer.WriteString(x.cssString("0", session))
buffer.WriteRune(',')
buffer.WriteString(y.cssString("0", session))
buffer.WriteString(") ")
}
2022-08-18 18:18:36 +03:00
scaleX, okScaleX := floatTextProperty(transform, ScaleX, session, 1)
scaleY, okScaleY := floatTextProperty(transform, ScaleY, session, 1)
2024-11-13 12:56:39 +03:00
scaleZ, okScaleZ := floatTextProperty(transform, ScaleZ, session, 1)
if okScaleZ {
2022-08-18 18:18:36 +03:00
2024-11-13 12:56:39 +03:00
buffer.WriteString(`scale3d(`)
buffer.WriteString(scaleX)
buffer.WriteRune(',')
buffer.WriteString(scaleY)
buffer.WriteRune(',')
buffer.WriteString(scaleZ)
buffer.WriteString(") ")
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
} else if okScaleX || okScaleY {
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
buffer.WriteString(`scale(`)
buffer.WriteString(scaleX)
buffer.WriteRune(',')
buffer.WriteString(scaleY)
buffer.WriteString(") ")
}
if angle, ok := angleProperty(transform, Rotate, session); ok {
rotateX, xOK := floatTextProperty(transform, RotateX, session, 1)
rotateY, yOK := floatTextProperty(transform, RotateY, session, 1)
rotateZ, zOK := floatTextProperty(transform, RotateZ, session, 1)
if xOK || yOK || zOK {
2022-08-18 18:18:36 +03:00
2021-09-07 17:36:50 +03:00
buffer.WriteString(`rotate3d(`)
2022-08-18 18:18:36 +03:00
buffer.WriteString(rotateX)
2021-09-07 17:36:50 +03:00
buffer.WriteRune(',')
2022-08-18 18:18:36 +03:00
buffer.WriteString(rotateY)
2021-09-07 17:36:50 +03:00
buffer.WriteRune(',')
2022-08-18 18:18:36 +03:00
buffer.WriteString(rotateZ)
2021-09-07 17:36:50 +03:00
buffer.WriteRune(',')
buffer.WriteString(angle.cssString())
2024-11-13 12:56:39 +03:00
buffer.WriteString(") ")
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
} else {
2021-09-07 17:36:50 +03:00
buffer.WriteString(`rotate(`)
buffer.WriteString(angle.cssString())
2024-11-13 12:56:39 +03:00
buffer.WriteString(") ")
2021-09-07 17:36:50 +03:00
}
}
2024-11-13 12:56:39 +03:00
length := buffer.Len()
if length == 0 {
return ""
}
result := buffer.String()
return result[:length-1]
2021-09-07 17:36:50 +03:00
}
func (style *viewStyle) writeViewTransformCSS(builder cssBuilder, session Session) {
2024-11-13 12:56:39 +03:00
x, y := getPerspectiveOrigin(style, session)
z := AutoSize()
if css := transformOriginCSS(x, y, z, session); css != "" {
builder.add(`perspective-origin`, css)
2024-11-13 12:56:39 +03:00
}
2021-09-07 17:36:50 +03:00
2024-11-13 12:56:39 +03:00
if backfaceVisible, ok := boolProperty(style, BackfaceVisible, session); ok {
if backfaceVisible {
builder.add(`backface-visibility`, `visible`)
} else {
builder.add(`backface-visibility`, `hidden`)
2021-09-07 17:36:50 +03:00
}
2024-11-13 12:56:39 +03:00
}
2021-09-07 17:36:50 +03:00
x, y, z = getTransformOrigin(style, session)
if css := transformOriginCSS(x, y, z, session); css != "" {
builder.add(`transform-origin`, css)
2021-09-07 17:36:50 +03:00
}
if transform := getTransformProperty(style, Transform); transform != nil {
2024-11-25 23:13:29 +03:00
builder.add(`transform`, transform.transformCSS(session))
}
2021-09-07 17:36:50 +03:00
}
func transformOriginCSS(x, y, z SizeUnit, session Session) string {
if z.Type == Auto && x.Type == Auto && y.Type == Auto {
return ""
}
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
if x.Type == SizeInPercent {
switch x.Value {
case 0:
buffer.WriteString("left")
case 50:
buffer.WriteString("center")
case 100:
buffer.WriteString("right")
default:
buffer.WriteString(x.cssString("center", session))
}
} else {
buffer.WriteString(x.cssString("center", session))
}
buffer.WriteRune(' ')
if y.Type == SizeInPercent {
switch y.Value {
case 0:
buffer.WriteString("top")
case 50:
buffer.WriteString("center")
case 100:
buffer.WriteString("bottom")
default:
buffer.WriteString(y.cssString("center", session))
}
} else {
buffer.WriteString(y.cssString("center", session))
}
if z.Type != Auto && z.Value != 0 {
buffer.WriteRune(' ')
buffer.WriteString(z.cssString("0", session))
}
return buffer.String()
}
2024-12-02 15:47:06 +03:00
// GetTransform returns a view transform: translation, scale and rotation over x, y and z axes as well as a distortion of a view along x and y axes.
// The default value is nil (no transform)
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetTransform(view View, subviewID ...string) TransformProperty {
return transformStyledProperty(view, subviewID, Transform)
}
2021-09-07 17:36:50 +03:00
2024-12-02 15:47:06 +03:00
// GetPerspective returns a distance between the z = 0 plane and the user in order to give a 3D-positioned
// element some perspective. Each 3D element with z > 0 becomes larger; each 3D-element with z < 0 becomes smaller.
// The default value is 0 (no 3D effects).
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetPerspective(view View, subviewID ...string) SizeUnit {
return sizeStyledProperty(view, subviewID, Perspective, false)
}
2021-09-07 17:36:50 +03:00
2024-12-02 15:47:06 +03:00
// GetPerspectiveOrigin returns a x- and y-coordinate of the position at which the viewer is looking.
// It is used as the vanishing point by the Perspective property. The default value is (50%, 50%).
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetPerspectiveOrigin(view View, subviewID ...string) (SizeUnit, SizeUnit) {
view = getSubview(view, subviewID)
if view == nil {
return AutoSize(), AutoSize()
}
return getPerspectiveOrigin(view, view.Session())
}
2021-09-07 17:36:50 +03:00
2024-12-02 15:47:06 +03:00
// GetBackfaceVisible returns a bool property that sets whether the back face of an element is
// visible when turned towards the user. Values:
// true - the back face is visible when turned towards the user (default value).
// false - the back face is hidden, effectively making the element invisible when turned away from the user.
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetBackfaceVisible(view View, subviewID ...string) bool {
return boolStyledProperty(view, subviewID, BackfaceVisible, false)
}
2024-11-13 12:56:39 +03:00
2024-12-02 15:47:06 +03:00
// GetTransformOrigin returns a x-, y-, and z-coordinate of the point around which a view transformation is applied.
// The default value is (50%, 50%, 50%).
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetTransformOrigin(view View, subviewID ...string) (SizeUnit, SizeUnit, SizeUnit) {
view = getSubview(view, subviewID)
if view == nil {
return AutoSize(), AutoSize(), AutoSize()
}
return getTransformOrigin(view, view.Session())
}
2021-09-07 17:36:50 +03:00
2024-12-02 15:47:06 +03:00
// GetTranslate returns a x-, y-, and z-axis translation value of a 2D/3D translation
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetTranslate(view View, subviewID ...string) (SizeUnit, SizeUnit, SizeUnit) {
if transform := GetTransform(view, subviewID...); transform != nil {
return transform.getTranslate(view.Session())
}
return AutoSize(), AutoSize(), AutoSize()
}
// GetSkew returns a angles to use to distort the element along the abscissa (x-axis)
// and the ordinate (y-axis). The default value is 0.
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetSkew(view View, subviewID ...string) (AngleUnit, AngleUnit) {
if transform := GetTransform(view, subviewID...); transform != nil {
x, y, _ := transform.getSkew(view.Session())
return x, y
}
return AngleUnit{Value: 0, Type: Radian}, AngleUnit{Value: 0, Type: Radian}
}
2021-09-07 17:36:50 +03:00
2024-12-02 15:47:06 +03:00
// GetScale returns a x-, y-, and z-axis scaling value of a 2D/3D scale. The default value is 1.
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetScale(view View, subviewID ...string) (float64, float64, float64) {
if transform := GetTransform(view, subviewID...); transform != nil {
session := view.Session()
x, _ := floatProperty(transform, ScaleX, session, 1)
y, _ := floatProperty(transform, ScaleY, session, 1)
z, _ := floatProperty(transform, ScaleZ, session, 1)
return x, y, z
2021-09-07 17:36:50 +03:00
}
2024-12-02 15:47:06 +03:00
return 1, 1, 1
}
2021-09-07 17:36:50 +03:00
2024-12-02 15:47:06 +03:00
// GetRotate returns a x-, y, z-coordinate of the vector denoting the axis of rotation, and the angle of the view rotation
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetRotate(view View, subviewID ...string) (float64, float64, float64, AngleUnit) {
if transform := GetTransform(view, subviewID...); transform != nil {
session := view.Session()
angle, _ := angleProperty(transform, Rotate, view.Session())
rotateX, _ := floatProperty(transform, RotateX, session, 1)
rotateY, _ := floatProperty(transform, RotateY, session, 1)
rotateZ, _ := floatProperty(transform, RotateZ, session, 1)
return rotateX, rotateY, rotateZ, angle
}
return 0, 0, 0, AngleUnit{Value: 0, Type: Radian}
2021-09-07 17:36:50 +03:00
}