Development guidance—Using CSS animation to implement HarmonyOS animation (1)

Note: The content of this article is shared and reproduced from the HarmonyOS Developer official website documentation

1. CSS syntax reference

CSS is a style language that describes the structure of HML pages. All components have system default styles, and different styles can be customized for components and pages in the page CSS style file. Please refer to Common Styles for component styles supported by the JS-compatible Web-like development paradigm.

measurement unit

● Logical pixel px (expressed as <length> in the document):

○ The default screen has a logical width of 720px (see the window section in the configuration file for configuration ). When actually displayed, the page layout will be scaled to the actual width of the screen, such as 100px. On a screen with an actual width of 1440 physical pixels, the actual rendering is 200 Physical pixels (from 720px to 1440 physical pixels, all sizes enlarged 2x).

○ When the additional configuration autoDesignWidth is true (see the window section in the configuration file for configuration), the logical pixel px will be scaled according to the screen density. For example, on a device with a screen density of 3, 100px will actually be rendered as 300 physical pixels . This method is recommended when the application needs to adapt to multiple devices.

● Percentage (expressed as <percentage> in the document): Indicates the percentage of the size of the parent component that this component occupies. For example, if the width of a component is set to 50%, it means that its width is 50% of the parent component.

style import

For modular management and code reuse, CSS style files support the @import statement to import css files.

Declaration style

There is a css file with the same name as the layout hml file in each page directory, which is used to describe the style of the components in the hml page and determine how the components should be displayed.

1. Internal style, supports the use of style and class attributes to control the style of components. For example:

<!-- index.hml --><div class="container">  <text style="color: red">Hello World</text></div>

/* index.css */.container {
    
      justify-content: center;}

2. File import and merge external style files. For example, define the style file style.css in the common directory and import it in the first line of the index.css file:

/* style.css */.title {
    
      font-size: 50px;}

/* index.css */@import '../../common/style.css';.container {
    
      justify-content: center;}

Selector

The css selector is used to select elements that need to be styled. The supported selectors are as shown in the following table:

Example:

<!-- 页面布局xxx.hml --><div id="containerId" class="container">  <text id="titleId" class="title">标题</text>  <div class="content">    <text id="contentId">内容</text>  </div></div>

/* 页面样式xxx.css *//* 对所有div组件设置样式 */div {
    
      flex-direction: column;}/* 对class="title"的组件设置样式 */.title {
    
      font-size: 30px;}/* 对id="contentId"的组件设置样式 */#contentId {
    
      font-size: 20px;}/* 对所有class="title"以及class="content"的组件都设置padding为5px */.title, .content {
    
      padding: 5px;}/* 对class="container"的组件下的所有text设置样式 */.container text {
    
      color: #007dff;}/* 对class="container"的组件下的直接后代text设置样式 */.container > text {
    
      color: #fa2a2d;}

The effect of the above style is as follows:

Where ".container text" sets the "title" and "content" to blue, while the ".container > text" direct descendant selector sets the "title" to red. The two have the same priority, but the declaration order of the direct descendant selector is later, and the former style is overwritten (for priority calculation, see selector priority ).

selector priority

The priority calculation rules of selectors are consistent with w3c rules (only supported: inline style, id, class, tag, descendants and direct descendants), where inline style is the style declared in the element's style attribute.

When multiple selector declarations match the same element, the priority of various selectors from high to low is: inline style > id > class > tag.

Pseudo class

CSS pseudo-classes are keywords in selectors that specify the special state of the element to be selected. For example, the :disabled state can be used to style an element when its disabled attribute becomes true.

In addition to a single pseudo-class, a combination of pseudo-classes is also supported. For example, the :focus:checked state can be used to set the style when the focus attribute and the checked attribute of the element are both true. The supported individual pseudo-classes are listed in the following table, in descending order of priority:

Examples of pseudo-classes are as follows. Setting the :active pseudo-class of a button can control the style when pressed by the user:

<!-- index.hml --><div class="container">  <input type="button" class="button" value="Button"></input></div>

/* index.css */.button:active {
    
      background-color: #888888;/*按钮被激活时,背景颜色变为#888888 */}

illustrate

Pseudo-class effects are not supported for pop-up window components and their sub-elements, including pop-up, dialog, menu, option, and picker.

Style precompilation

Precompilation provides a program that uses unique syntax to generate CSS. It can provide variables, operations and other functions, allowing developers to define component styles more conveniently. It currently supports precompilation of less, sass and scss. When using style precompilation, you need to change the suffix of the original css file to less, sass or scss, for example, change index.css to index.less, index.sass or index.scss.

● The current file is precompiled using styles, for example, change the original index.css to index.less:

/* index.less *//* 定义变量 */@colorBackground: #000000;.container {
    
      background-color: @colorBackground; /* 使用当前less文件中定义的变量 */}

● Reference the precompiled file, for example, the style.scss file exists in common, change the original index.css to index.scss, and introduce style.scss:

/* style.scss *//* 定义变量 */$colorBackground: #000000;

Quoted in index.scss:

/* index.scss *//* 引入外部scss文件 */@import '../../common/style.scss';.container {
    
      background-color: $colorBackground; /* 使用style.scss中定义的变量 */}

illustrate

It is recommended that the referenced precompiled files be placed in the common directory for management.

CSS style inheritance 6+

CSS style inheritance provides the ability for child nodes to inherit the styles of parent nodes. The inherited styles have the lowest priority in the scenario of multi-selector style matching. Currently, the inheritance of the following styles is supported:

● font-family

● font-weight

● font-size

● font-style

● text-align

● line-height

● letter-spacing

● color

● visibility

2. CSS animation

1. Attribute style animation

Dynamically set the width and height of the parent component in keyframes to make the component larger or smaller. The child component sets the scale attribute to scale the parent and child components at the same time, and then sets the opacity to display and hide the parent and child components.

<!-- xxx.hml --><div class="container">  <div class="fade">    <text>fading away</text>  </div>  <div class="bigger">    <text>getting bigger</text>  </div></div>

/* xxx.css */.container {
    
      background-color:#F1F3F5;  display: flex;  justify-content: center;  align-items: center;  flex-direction: column;  width: 100%;  height: 100%;}.fade {
    
      width: 30%;  height: 200px;  left: 35%;  top: 25%;  position: absolute;  animation: 2s change infinite friction;}.bigger {
    
      width: 20%;  height: 100px;  background-color: blue;  animation: 2s change1 infinite linear-out-slow-in;}text {
    
      width: 100%;  height: 100%;  text-align: center;  color: white;  font-size: 35px;  animation: 2s change2 infinite linear-out-slow-in;}/* 颜色变化 */@keyframes change{
    
      from {
    
        background-color: #f76160;    opacity: 1;  }  to {
    
        background-color: #09ba07;    opacity: 0;  }}/* 父组件大小变化 */@keyframes change1 {
    
      0% {
    
        width: 20%;    height: 100px;  }  100% {
    
        width: 80%;    height: 200px;  }}/* 子组件文字缩放 */@keyframes change2 {
    
      0% {
    
        transform: scale(0);  }  100% {
    
        transform: scale(1.5);  }}

illustrate

● The animation values ​​are not distinguished in order. Duration (animation execution time)/delay (animation delay execution time) are parsed in the order of appearance.

● The animation-duration style must be set, otherwise if the duration is 0, there will be no animation effect. When the animation-fill-mode attribute is set to forwards, the component directly displays the style of the last frame.

2. transform style animation

Set the transform property to rotate, scale, move, and tilt the component.

Set static animation

Create a square and rotate it 90° to become a rhombus, and use the rectangle below to cover the lower part of the rhombus to form a roof. Set the rectangular translate attribute value to (150px,-150px) to determine the coordinate position to form the door, and then use the position attribute to make the horizontal and vertical lines Follow the parent component (square) to the specified coordinate position, then set the scale attribute to make the parent and child components grow together to form the window size. Finally, use the skewX attribute to tilt the component and set the coordinates translate(200px,-710px) to get the chimney.

<!-- xxx.hml --><div class="container">  <div class="top"></div>  <div class="content"></div>  <div class="door"></div>  <!-- 窗户 -->  <div class="window">    <div class="horizontal"></div>    <div class="vertical"></div>  </div>  <div class="chimney"></div></div>
/* xxx.css */.container {
    
      width:100%;  height:100%;  background-color:#F1F3F5;  align-items: center;  flex-direction: column;}.top{
    
      z-index: -1;  position: absolute;  width: 428px;  height: 428px;  background-color: #860303;  transform: rotate(45deg);  margin-top: 284px;  margin-left: 148px;}.content{
    
      margin-top: 500px;  width: 600px;  height: 400px;  background-color: white;  border:  1px solid black;}.door{
    
      width: 100px;  height: 135px;  background-color: #1033d9;  transform: translate(150px,-137px);}.window{
    
      z-index: 1;  position: relative;     width: 100px;  height: 100px;  background-color: white;  border: 1px solid black;  transform: translate(-150px,-400px) scale(1.5);}/* 窗户的横轴 */.horizontal{
    
      position: absolute;  top: 50%;  width: 100px;  height: 5px;  background-color: black;}/* 窗户的纵轴 */.vertical{
    
      position: absolute;  left: 50%;  width: 5px;  height: 100px;  background-color: black;}.chimney{
    
      z-index: -2;  width: 40px;  height: 100px;  border-radius: 15px;  background-color: #9a7404;  transform: translate(200px,-710px) skewX(-5deg);}

Set pan animation

The ball drops animation. Change the Y-axis coordinate of the ball to realize the ball falling. In the next period of time, reduce the Y-axis coordinate to realize the ball rebound. Let the height of each rebound gradually decrease until the rebound height is 0. The animation of the ball falling is simulated.

<!-- xxx.hml --><div class="container">  <div class="circle"></div>  <div class="flower"></div></div>
/* xxx.css */.container {
    
      width:100%;  height:100%;  background-color:#F1F3F5;  display: flex;  justify-content: center;}.circle{
    
      width: 100px;  height: 100px;  border-radius: 50px;  background-color: red;  /* forwards停在动画的最后一帧 */  animation: down 3s fast-out-linear-in forwards;}.flower{
    
      position: fixed;  width: 80%;  margin-left: 10%;  height: 5px;  background-color: black;  top: 1000px;}@keyframes down {
    
      0%{
    
        transform: translate(0px,0px);  }  /* 下落 */  15%{
    
        transform: translate(10px,900px);  }  /* 开始回弹 */  25%{
    
        transform: translate(20px,500px);  }  /* 下落 */  35%{
    
        transform: translate(30px,900px);  }  /* 回弹 */  45%{
    
        transform: translate(40px,700px);  }  55%{
    
        transform: translate(50px,900px);  }  65%{
    
        transform: translate(60px,800px);  }  80%{
    
        transform: translate(70px,900px);  }  90%{
    
        transform: translate(80px,850px);  }  /* 停止 */  100%{
    
        transform: translate(90px,900px);  }}

Set rotation animation

Setting different origin positions (transform-origin) changes the center of rotation around the element. The first three parameter values ​​of the rotate3d attribute are the rotation vectors of the X-axis, Y-axis, and Z-axis respectively. The fourth value is the rotation angle. The rotation angle can be a negative value. A negative value means the rotation direction is counterclockwise.

<!-- xxx.hml --><div class="container">  <div class="rotate">    <div class="rect rect1"></div>    <div class="rect rect2"></div>    <div class="rect rect3"></div>  </div>  <!-- 3d属性 -->  <div class="rotate3d">    <div class="content">        <div class="rect4"></div>        <div class="rect5"> </div>    </div>    <div class="mouse"></div>  </div></div>

/* xxx.css */.container {
    
        flex-direction: column;    background-color:#F1F3F5;    display: flex;    align-items: center;    justify-content: center;    width: 100%;    height: 100%;}.rect {
    
        width: 100px;    height: 100px;    animation: rotate 3s infinite;    margin-left: 30px;}.rect1 {
    
        background-color: #f76160;}.rect2 {
    
        background-color: #60f76f;/* 改变原点位置*/    transform-origin: 10% 10px;}.rect3 {
    
        background-color: #6081f7;/*  改变原点位置*/    transform-origin: right bottom;}@keyframes rotate {
    
        from {
    
            transform: rotate(0deg)    }    to {
    
            transform: rotate(360deg);    }}/* 3d示例样式 */.rotate3d {
    
        margin-top: 150px;    flex-direction: column;    background-color:#F1F3F5;    display: flex;    align-items: center;    width: 80%;    height: 600px;    border-radius: 300px;    border: 1px solid #ec0808;}.content {
    
        padding-top: 150px;    display: flex;    align-items: center;    justify-content: center;}/* react4 react5 翻转形成眼睛 */.rect4 {
    
        width: 100px;    height: 100px;    animation: rotate3d1 1000ms infinite;    background-color: darkmagenta;}.rect5 {
    
        width: 100px;    height: 100px;    animation: rotate3d1 1000ms infinite;    margin-left: 100px;    background-color: darkmagenta;}.mouse {
    
        margin-top: 150px;    width: 200px;    height: 100px;    border-radius: 50px;    border: 1px solid #e70303;    animation: rotate3d2 1000ms infinite;}/* 眼睛的动效 */@keyframes rotate3d1 {
    
        0% {
    
            transform:rotate3d(0,0,0,0deg)    }    50% {
    
            transform:rotate3d(20,20,20,360deg);    }    100% {
    
            transform:rotate3d(0,0,0,0deg);    }}/* 嘴的动效 */@keyframes rotate3d2 {
    
        0% {
    
            transform:rotate3d(0,0,0,0deg)    }    33% {
    
            transform:rotate3d(0,0,10,30deg);    }    66% {
    
            transform:rotate3d(0,0,10,-30deg);    }    100% {
    
            transform:rotate3d(0,0,0,0deg);    }}

illustrate

transform-origin transforms the origin position of the object. If only one value is set, the other value is 50%. If two values ​​are set, the first value represents the position of the X axis, and the second value represents the position of the Y axis.

Set zoom animation

Set the scale style attribute to implement ripple animation. First use positioning to determine the position of the element. After determining the coordinates, create multiple components to achieve the overlapping effect. Then set the opacity attribute to change the opacity of the component to hide and display the component. At the same time, set the scale value so that the component can be enlarged at the same time. Hide one side, and finally set different animation execution times for the two components to achieve a diffusion effect.

Set the scaling parameters of the X-axis, Y-axis, and Z-axis in sacle3d to implement animation.

<!-- xxx.hml --><div class="container">  <div class="circle">    <text>ripple</text>  </div>  <div class="ripple"></div>  <div class="ripple ripple2"></div>  <!-- 3d -->  <div class="content">    <text>spring</text>  </div></div>

/* xxx.css */.container {
    
        flex-direction: column;    background-color:#F1F3F5;    width: 100%;    position: relative;}.circle{
    
        margin-top: 400px;    margin-left: 40%;    width: 100px;    height: 100px;    border-radius: 50px;    background-color: mediumpurple;    z-index: 1;  position: absolute;}.ripple{
    
        margin-top: 400px;    margin-left: 40%;    position: absolute;  z-index: 0;    width: 100px;    height: 100px;    border-radius: 50px;    background-color: blueviolet;    animation: ripple 5s infinite;}/* 设置不同的动画时间 */.ripple2{
    
        animation-duration: 2.5s;}@keyframes ripple{
    
        0%{
    
            transform: scale(1);        opacity: 0.5;    }    50%{
    
            transform: scale(3);        opacity: 0;    }    100%{
    
            transform: scale(1);        opacity: 0.5;    }}text{
    
        color: white;    text-align: center;    height: 100%;    width: 100%;}.content {
    
        margin-top: 700px;    margin-left: 33%;    width: 200px;    height: 100px;    animation:rubberBand 1s infinite;    background-color: darkmagenta;    position: absolute;}@keyframes rubberBand {
    
        0% {
    
            transform: scale3d(1, 1, 1);    }    30% {
    
            transform: scale3d(1.25, 0.75, 1.1);    }    40% {
    
            transform: scale3d(0.75, 1.25, 1.2);    }    50% {
    
            transform: scale3d(1.15, 0.85, 1.3);    }    65% {
    
            transform: scale3d(.95, 1.05, 1.2);    }    75% {
    
            transform: scale3d(1.05, .95, 1.1);    }    100%{
    
            transform: scale3d(1, 1, 1);    }}

illustrate

After setting the transform attribute value, the child element will change together with the parent element. If only other attribute values ​​of the parent element are changed (such as height, width), the child element will not change.

Set matrix properties

matrix is ​​a matrix with six input parameters. The six values ​​represent: scaleX, skewY, skewX, scaleY, translateX, translateY. In the following example, the matrix property is set to matrix(1,0,0,1,0,200) to make the component move and tilt.

<!-- xxx.hml --><div class="container">  <div class="rect"> </div></div>

/* xxx.css */.container{
    
      background-color:#F1F3F5;  display: flex;  justify-content: center;  width: 100%;  height: 100%;}.rect{
    
      width: 100px;  height: 100px;  background-color: red;  animation: down 3s infinite forwards;}@keyframes down{
    
      0%{
    
        transform: matrix(1,0,0,1,0,0);  }  10%{
    
        transform: matrix(1,0,0,1,0,200);  }  60%{
    
        transform: matrix(2,1.5,1.5,2,0,700);  }  100%{
    
        transform: matrix(1,0,0,1,0,0);  }}

Integrate transform attribute

Transform can set multiple values ​​and multiple values ​​can be set at the same time. The following case shows the animation effect when the scale, translate, and rotate attributes are set at the same time.

<!-- xxx.hml --><div class="container">  <div class="rect1"></div>  <div class="rect2"></div>  <div class="rect3"></div>  <div class="rect4"></div>  <div class="rect5"></div></div>
/* xxx.css */.container{
    
        width: 100%;    height: 100%;    flex-direction:column;    background-color:#F1F3F5;    padding:50px;}.rect1{
    
        width: 100px;    height: 100px;    background-color: red;    animation: change1 3s infinite forwards;}.rect2{
    
        margin-top: 50px;    width: 100px;    height: 100px;    background-color: darkblue;    animation: change2 3s infinite forwards;}.rect3{
    
        margin-top: 50px;    width: 100px;    height: 100px;    background-color: darkblue;    animation: change3 3s infinite;}.rect4{
    
        align-self: center;    margin-left: 50px;    margin-top: 200px;    width: 100px;    height: 100px;    background-color: darkmagenta;    animation: change4 3s infinite;}.rect5{
    
        margin-top: 300px;    width: 100px;    height: 100px;   background-color: cadetblue;    animation: change5 3s infinite;}/* change1 change2 对比 */@keyframes change1{
    
        0%{
    
            transform: translate(0,0);    transform: rotate(0deg)    }    100%{
    
            transform: translate(0,500px);        transform: rotate(360deg)    }}/* change2 change3 对比属性顺序不同的动画效果 */@keyframes change2{
    
        0%{
    
            transform:translate(0,0) rotate(0deg) ;    }    100%{
    
            transform: translate(300px,0) rotate(360deg);    }}@keyframes change3{
    
        0%{
    
            transform:rotate(0deg) translate(0,0);    }    100%{
    
            transform:rotate(360deg)  translate(300px,0);    }}/* 属性值不对应的情况 */@keyframes change4{
    
        0%{
    
            transform: scale(0.5);    }    100%{
    
            transform:scale(2) rotate(45deg);    }}/* 多属性的写法 */@keyframes change5{
    
        0%{
    
            transform:scale(0) translate(0,0) rotate(0);    }    100%{
    
            transform: scale(1.5) rotate(360deg) translate(200px,0);    }}

illustrate

● When multiple transforms are set, subsequent transform values ​​will overwrite the previous ones. If you want to use multiple animation styles at the same time, you can use compound writing, for example: transform: scale(1) rotate(0) translate(0,0).

● When transform is written in a composite way, different animation effects will occur depending on the order of multiple style values ​​in the changing style.

● The style values ​​set by the transform attribute must correspond one to one. If the front and back do not correspond, the animation will not take effect. If multiple style values ​​are set, only the animation effect of the corresponding value will be displayed.

Guess you like

Origin blog.csdn.net/HarmonyOSDev/article/details/132619972