ΠΠ½ΠΈΠΌΠ°ΡΠΈΡ Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡΡ
React β ΠΏΠΎΠΏΡΠ»ΡΡΠ½Π°Ρ ΠΈ ΠΎΠ±ΡΡΠΆΠ΄Π°Π΅ΠΌΠ°Ρ ΡΠ΅ΠΌΠ°. ΠΠ΅Π»ΠΎ Π² ΡΠΎΠΌ, ΡΡΠΎ ΡΠΏΠΎΡΠΎΠ±ΠΎΠ² Π΅Π΅ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΎΡΠ΅Π½Ρ ΠΌΠ½ΠΎΠ³ΠΎ. ΠΠ΅ΠΊΠΎΡΠΎΡΡΠ΅ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡ CSS, Π΄ΠΎΠ±Π°Π²Π»ΡΡ ΡΠ΅Π³ΠΈ Π² HTML-ΠΊΠ»Π°ΡΡΡ. ΠΡΠ»ΠΈΡΠ½ΡΠΉ ΡΠΏΠΎΡΠΎΠ±, Π΅Π³ΠΎ ΡΡΠΎΠΈΡ ΠΏΡΠΈΠΌΠ΅Π½ΡΡΡ. ΠΠΎ, Π΅ΡΠ»ΠΈ Π²Ρ Ρ
ΠΎΡΠΈΡΠ΅ ΡΠ°Π±ΠΎΡΠ°ΡΡ ΡΠΎ ΡΠ»ΠΎΠΆΠ½ΡΠΌΠΈ Π²ΠΈΠ΄Π°ΠΌΠΈ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΉ, ΡΡΠΎΠΈΡ ΡΠ΄Π΅Π»ΠΈΡΡ Π²ΡΠ΅ΠΌΡ ΠΈΠ·ΡΡΠ΅Π½ΠΈΡ GreenSock, ΡΡΠΎ ΠΏΠΎΠΏΡΠ»ΡΡΠ½Π°Ρ ΠΈ ΠΌΠΎΡΠ½Π°Ρ ΠΏΠ»Π°ΡΡΠΎΡΠΌΠ°. Π’Π°ΠΊΠΆΠ΅ Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΉ ΡΡΡΠ΅ΡΡΠ²ΡΠ΅Ρ ΠΌΠ°ΡΡΠ° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊ ΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ². ΠΠ°Π²Π°ΠΉΡΠ΅ ΠΏΠΎΠ³ΠΎΠ²ΠΎΡΠΈΠΌ ΠΎ Π½ΠΈΡ
.
Π ΡΡΠ°ΡΡΠ΅ ΡΠ°ΡΡΠΌΠ°ΡΡΠΈΠ²Π°Π΅ΡΡΡ ΠΏΡΡΡ ΡΠΏΠΎΡΠΎΠ±ΠΎΠ² Π°Π½ΠΈΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ React-ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ:
- CSS;
- ReactTransitionGroup;
- React-animations;
- React-reveal;
- TweenOne ΠΈ Ant Design.
Skillbox ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅Ρ: ΠΠ±ΡΠ°Π·ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΡΠΉ ΠΎΠ½Π»Π°ΠΉΠ½-ΠΊΡΡΡ
Β«ΠΡΠΎΡΠ΅ΡΡΠΈΡ Java-ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΒ» .
ΠΠ°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ: Π΄Π»Ρ Π²ΡΠ΅Ρ ΡΠΈΡΠ°ΡΠ΅Π»Π΅ΠΉ Β«Π₯Π°Π±ΡΠ°Β» β ΡΠΊΠΈΠ΄ΠΊΠ° 10 000 ΡΡΠ±Π»Π΅ΠΉ ΠΏΡΠΈ Π·Π°ΠΏΠΈΡΠΈ Π½Π° Π»ΡΠ±ΠΎΠΉ ΠΊΡΡΡ Skillbox ΠΏΠΎ ΠΏΡΠΎΠΌΠΎΠΊΠΎΠ΄Ρ Β«Π₯Π°Π±ΡΒ».
ΠΡΠ΅ ΠΏΡΠΈΠΌΠ΅ΡΡ Π΄ΠΎΡΡΡΠΏΠ½Ρ Π²
CSS
ΠΠ°ΠΊ ΡΠ°Π· ΠΎΠ± ΡΡΠΎΠΌ ΠΌΠ΅ΡΠΎΠ΄Π΅ Π³ΠΎΠ²ΠΎΡΠΈΠ»ΠΎΡΡ Π² ΡΠ°ΠΌΠΎΠΌ Π½Π°ΡΠ°Π»Π΅, ΠΈ ΠΎΠ½ Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ Ρ ΠΎΡΠΎΡ. ΠΡΠ»ΠΈ Π²ΠΌΠ΅ΡΡΠΎ ΡΠΎΠ³ΠΎ, ΡΡΠΎΠ±Ρ ΠΈΠΌΠΏΠΎΡΡΠΈΡΠΎΠ²Π°ΡΡ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ JavaScript, ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π΅Π³ΠΎ, ΡΠ±ΠΎΡΠΊΠ° Π±ΡΠ΄Π΅Ρ Π½Π΅Π±ΠΎΠ»ΡΡΠΎΠΉ, Π±ΡΠ°ΡΠ·Π΅ΡΡ Π½Π΅ ΠΏΠΎΡΡΠ΅Π±ΡΠ΅ΡΡΡ ΠΌΠ½ΠΎΠ³ΠΎ ΡΠ΅ΡΡΡΡΠΎΠ². Π ΡΡΠΎ, ΠΊΠΎΠ½Π΅ΡΠ½ΠΎ ΠΆΠ΅, Π²Π»ΠΈΡΠ΅Ρ Π½Π° ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ. ΠΡΠ»ΠΈ Π²Π°ΡΠ° Π°Π½ΠΈΠΌΠ°ΡΠΈΡ Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡΡΡ ΠΎΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΏΡΠΎΡΡΠΎΠΉ, ΠΎΠ±ΡΠ°ΡΠΈΡΠ΅ Π½Π° ΡΡΠΎΡ ΠΌΠ΅ΡΠΎΠ΄ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅.
Π ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ ΠΏΡΠΈΠΌΠ΅ΡΠ° β Π°Π½ΠΈΠΌΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΌΠ΅Π½Ρ:
ΠΠ½ΠΎ ΠΎΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΏΡΠΎΡΡΠΎΠ΅, ΡΠΎ ΡΠ²ΠΎΠΉΡΡΠ²ΠΎΠΌ CSS ΠΈ ΡΡΠΈΠ³Π³Π΅ΡΠΎΠΌ ΡΠΈΠΏΠ° className = Β«is-nav-openΒ» Π΄Π»Ρ ΡΠ΅Π³Π° HTML.
ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΡΠΎΡ ΠΌΠ΅ΡΠΎΠ΄ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ°Π·Π½ΡΠΌΠΈ ΡΠΏΠΎΡΠΎΠ±Π°ΠΌΠΈ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΡΠΎΠ·Π΄Π°ΡΡ Π½Π°Π΄ Π½Π°Π²ΠΈΠ³Π°ΡΠΈΠ΅ΠΉ wrapper, Π° Π·Π°ΡΠ΅ΠΌ Π²ΡΠ·ΡΠ²Π°ΡΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ ΠΏΠΎΠ»Π΅ΠΉ. ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ Π½Π°Π²ΠΈΠ³Π°ΡΠΈΡ ΠΈΠΌΠ΅Π΅Ρ ΠΏΠΎΡΡΠΎΡΠ½Π½ΡΡ ΡΠΈΡΠΈΠ½Ρ, ΠΊΠΎΡΠΎΡΠ°Ρ ΡΠ°Π²Π½Π° 250px, ΡΠΈΡΠΈΠ½Π° wrapper ΡΠΎ ΡΠ²ΠΎΠΉΡΡΠ²ΠΎΠΌ margin-left ΠΈΠ»ΠΈ translateX Π΄ΠΎΠ»ΠΆΠ½Π° ΠΈΠΌΠ΅ΡΡ ΡΡ ΠΆΠ΅ ΡΠΈΡΠΈΠ½Ρ. ΠΡΠΈ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΡΡΠΈ ΠΏΠΎΠΊΠ°Π·Π°ΡΡ Π½Π°Π²ΠΈΠ³Π°ΡΠΈΡ Π½ΡΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ className = Β«is-nav-openΒ» Π΄Π»Ρ wrapper ΠΈ ΠΏΠ΅ΡΠ΅ΠΌΠ΅ΡΡΠΈΡΡ wrapper Π½Π° margin-left / translateX: 0;.
Π ΠΊΠΎΠ½Π΅ΡΠ½ΠΎΠΌ ΠΈΡΠΎΠ³Π΅ ΠΈΡΡ ΠΎΠ΄Π½ΠΈΠΊ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ Π±ΡΠ΄Π΅Ρ Π²ΡΠ³Π»ΡΠ΄Π΅ΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ:
export default class ExampleCss extends Component {
handleClick() {
const wrapper = document.getElementById('wrapper');
wrapper.classList.toggle('is-nav-open')
}
render() {
return (
<div id="wrapper" className="wrapper">
<div className="nav">
<icon
className="nav__icon"
type="menu-fold"
onClick={() => this.handleClick()}/>
<div className="nav__body">
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Beatae ducimus est laudantium libero nam optio repellat
sit unde voluptatum?
</div>
</div>
</div>
);
}
}
Π Π²ΠΎΡ CSS-ΡΡΠΈΠ»ΠΈ:
.wrapper {
display: flex;
width: 100%;
height: 100%;
transition: margin .5s;
margin: 0 0 0 -250px;
}
.wrapper.is-nav-open {
margin-left: 0;
}
.nav {
position: relative;
width: 250px;
height: 20px;
padding: 20px;
border-right: 1px solid #ccc;
}
.nav__icon {
position: absolute;
top: 0;
right: -60px;
padding: 20px;
font-size: 20px;
cursor: pointer;
transition: color .3s;
}
.nav__icon:hover {
color: #5eb2ff;
}
ΠΠΎΠ²ΡΠΎΡΡΡΡ, Π΅ΡΠ»ΠΈ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ ΠΎΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΏΡΠΎΡΡΠ°, ΡΠΎ ΡΡΠΎΡ ΠΌΠ΅ΡΠΎΠ΄ β ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΉ. ΠΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Π΅ΠΉ ΠΏΠΎΡΠ°Π΄ΡΠ΅Ρ Π±ΡΡΡΡΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ Π±ΡΠ°ΡΠ·Π΅ΡΠ°.
ReactTransitionGroup
ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ ReactTransitionGroup ΡΠ°Π·ΡΠ°Π±ΠΎΡΠ°Π»Π° ΠΊΠΎΠΌΠ°Π½Π΄Π° ΡΠΎΠΎΠ±ΡΠ΅ΡΡΠ²Π° ReactJS. Π‘ Π΅Π³ΠΎ ΠΏΠΎΠΌΠΎΡΡΡ ΠΌΠΎΠΆΠ½ΠΎ Π±Π΅Π· ΠΏΡΠΎΠ±Π»Π΅ΠΌ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°ΡΡ ΠΎΡΠ½ΠΎΠ²Π½ΡΠ΅ CSS-Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ ΠΈ ΠΏΠ΅ΡΠ΅Ρ ΠΎΠ΄Ρ.
ReactTransitionGroup ΠΏΡΠ΅Π΄Π½Π°Π·Π½Π°ΡΠ΅Π½ Π΄Π»Ρ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ ΠΊΠ»Π°ΡΡΠΎΠ² ΠΏΡΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ ΠΆΠΈΠ·Π½Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠΈΠΊΠ»Π° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°. Π£ Π½Π΅Π³ΠΎ Π½Π΅Π±ΠΎΠ»ΡΡΠΎΠΉ ΡΠ°Π·ΠΌΠ΅Ρ, Π΅Π³ΠΎ Π½ΡΠΆΠ½ΠΎ ΡΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ Π² ΠΏΠ°ΠΊΠ΅ΡΠ΅ Π΄Π»Ρ React-ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ, ΡΡΠΎ Π½Π΅Π·Π½Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΡΠ²Π΅Π»ΠΈΡΠΈΡ ΠΎΠ±ΡΠΈΠΉ ΡΠ°Π·ΠΌΠ΅Ρ ΡΠ±ΠΎΡΠΊΠΈ. ΠΡΠΎΠΌΠ΅ ΡΠΎΠ³ΠΎ, ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΈ CDN.
Π£ ReactTransitionGroup Π΅ΡΡΡ ΡΡΠΈ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠ°, ΡΡΠΎ Transition, CSSTransition ΠΈ TransitionGroup. ΠΠ»Ρ Π·Π°ΠΏΡΡΠΊΠ° Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ Π² Π½ΠΈΡ Π½ΡΠΆΠ½ΠΎ ΠΎΠ±Π΅ΡΠ½ΡΡΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ. Π‘ΡΠΈΠ»Ρ, Π² ΡΠ²ΠΎΡ ΠΎΡΠ΅ΡΠ΅Π΄Ρ, Π½ΡΠΆΠ½ΠΎ ΠΏΡΠΎΠΏΠΈΡΡΠ²Π°ΡΡ Π² ΠΊΠ»Π°ΡΡΠ°Ρ CSS.
ΠΠΎΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ, Π° Π΄Π°Π»ΡΡΠ΅ β ΡΠΏΠΎΡΠΎΠ± Π΅Π΅ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ.
ΠΠ΅ΡΠ²ΡΠΌ Π΄Π΅Π»ΠΎΠΌ Π½ΡΠΆΠ½ΠΎ ΠΈΠΌΠΏΠΎΡΡΠΈΡΠΎΠ²Π°ΡΡ CSSTransitionGroup ΠΈΠ· react-transition-group. ΠΠΎΡΠ»Π΅ ΡΡΠΎΠ³ΠΎ ΡΡΠ΅Π±ΡΠ΅ΡΡΡ ΠΎΠ±Π΅ΡΠ½ΡΡΡ ΡΠΏΠΈΡΠΎΠΊ ΠΈ ΡΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ ΡΠ²ΠΎΠΉΡΡΠ²ΠΎ transitionName. ΠΠ°ΠΆΠ΄ΡΠΉ ΡΠ°Π· ΠΏΡΠΈ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠΈ ΠΈΠ»ΠΈ ΡΠ΄Π°Π»Π΅Π½ΠΈΠΈ Π΄ΠΎΡΠ΅ΡΠ½Π΅Π³ΠΎ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠ° Π² CSSTransitionGroup ΠΎΠ½ ΠΏΠΎΠ»ΡΡΠ°Π΅Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΎΠ½Π½ΡΠ΅ ΡΡΠΈΠ»ΠΈ.
<CSSTransitionGroup
transitionName="example">
{items}
</CSSTransitionGroup>
ΠΡΠΈ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠ΅ ΡΠ²ΠΎΠΉΡΡΠ²Π° transitionName = Β«exampleΒ» ΠΊΠ»Π°ΡΡΡ Π² ΡΠ°Π±Π»ΠΈΡΠ°Ρ ΡΡΠΈΠ»Π΅ΠΉ Π΄ΠΎΠ»ΠΆΠ½Ρ Π½Π°ΡΠΈΠ½Π°ΡΡΡΡ Ρ ΠΈΠΌΠ΅Π½ΠΈ ΠΏΡΠΈΠΌΠ΅ΡΠ°.
.example-eneter {
opacity: 0.01;
}
.example-enter.example-enter-active {
opacity: 1;
transition: opacity 300ms ease-in;
}
.example-leave {
opacity: 1;
}
.example-leave.example-leave-active {
opacity: 0.01;
transition: opacity 300ms ease-in;
ΠΡΡΠ΅ ΠΏΠΎΠΊΠ°Π·Π°Π½ ΠΏΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ReactTransitionGroup.
ΠΡΠΆΠ½Π° Π΅ΡΠ΅ ΠΈ Π»ΠΎΠ³ΠΈΠΊΠ°, ΠΏΡΠΈΡΠ΅ΠΌ Π΄Π²Π° ΠΌΠ΅ΡΠΎΠ΄Π° Π΄Π»Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΏΡΠΈΠΌΠ΅ΡΠ° Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΡ ΡΠΏΠΈΡΠΊΠ° ΠΊΠΎΠ½ΡΠ°ΠΊΡΠΎΠ².
ΠΠ΅ΡΠ²ΡΠΉ ΠΌΠ΅ΡΠΎΠ΄ handleAdd β ΠΎΠ½ Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅Ρ Π½ΠΎΠ²ΡΠ΅ ΠΊΠΎΠ½ΡΠ°ΠΊΡΡ, ΠΏΠΎΠ»ΡΡΠ°Π΅Ρ ΡΠ»ΡΡΠ°ΠΉΠ½ΠΎΠ΅ ΠΈΠΌΡ, ΠΊΠΎΡΠΎΡΠΎΠ΅ Π·Π°ΡΠ΅ΠΌ ΠΏΠΎΠΌΠ΅ΡΠ°Π΅Ρ Π² ΠΌΠ°ΡΡΠΈΠ² state.items.
ΠΠ»Ρ ΡΠ΄Π°Π»Π΅Π½ΠΈΡ ΠΊΠΎΠ½ΡΠ°ΠΊΡΠ° ΠΏΠΎ ΠΈΠ½Π΄Π΅ΠΊΡΡ Π² ΠΌΠ°ΡΡΠΈΠ²Π΅ state.items ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ handleRemove.
import React, { Component, Fragment } from 'react';
import { CSSTransitionGroup } from 'react-transition-group'
import random from 'random-name'
import Button from './button'
import Item from './item'
import './style.css';
export default class ReactTransitionGroup extends Component {
constructor(props) {
super(props);
this.state = { items: ['Natividad Steen']};
this.handleAdd = this.handleAdd.bind(this);
}
handleAdd() {
let newItems = this.state.items;
newItems.push(random());
this.setState({ items: newItems });
}
render () {
const items = this.state.items.map((item, i) => (
<Item
item={item}
key={i}
keyDelete={i}
handleRemove={(i) => this.handleRemove(i)}
/>
));
return (
<Fragment>
<Button onClick={this.handleAdd}/>
<div className="project">
<CSSTransitionGroup
transitionName="example"
transitionEnterTimeout={500}
transitionLeaveTimeout={300}
>
{items}
</CSSTransitionGroup>
</div>
</Fragment>
);
}
};
React-animations
Π― Π·Π½Π°Ρ, ΡΡΠΎ Π²Ρ Π΄ΡΠΌΠ°Π΅ΡΠ΅:
Π’Π΅ΠΏΠ΅ΡΡ ΠΏΡΠΎΠ²Π΅ΡΠΈΠΌ, ΠΊΠ°ΠΊ ΡΡΠΎ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ Π½Π° ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ ΠΏΠΎΠ΄ΠΏΡΡΠ³ΠΈΠ²Π°Π½ΠΈΡ.
ΠΠ΅ΡΠ²ΡΠΌ Π΄Π΅Π»ΠΎΠΌ ΠΈΠΌΠΏΠΎΡΡΠΈΡΡΠ΅ΠΌ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ ΠΈΠ· react-animations.
const Bounce = styled.div`animation: 2s ${keyframes`${bounce}`} infinite`;
ΠΠ°ΡΠ΅ΠΌ, ΠΏΠΎΡΠ»Π΅ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°, ΠΎΠ±ΠΎΡΠ°ΡΠΈΠ²Π°Π΅ΠΌ Π»ΡΠ±ΠΎΠΉ HTML-ΠΊΠΎΠ΄ ΠΈΠ»ΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Π΄Π»Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
<bounce><h1>Hello Animation Bounce</h1></bounce>
ΠΡΠΈΠΌΠ΅Ρ:
import React, { Component } from 'react';
import styled, { keyframes } from 'styled-components';
import { bounce } from 'react-animations';
import './style.css';
const Bounce = styled.div`animation: 2s ${keyframes`${bounce}`} infinite`;
export default class ReactAnimations extends Component {
render() {
return (
<Bounce><h1>Hello Animation Bounce</h1></bounce>
);
}
}
ΠΡΠ΅ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ, Π°Π½ΠΈΠΌΠ°ΡΠΈΡ ΠΎΡΠ΅Π½Ρ ΠΏΡΠΎΡΡΠ°Ρ. ΠΡΠΎΠΌΠ΅ ΡΠΎΠ³ΠΎ, Π΅ΡΡΡ ΠΎΡΠ»ΠΈΡΠ½ΠΎΠ΅ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Π΄Π»Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ ΠΏΠΎΠ΄ΠΏΡΡΠ³ΠΈΠ²Π°Π½ΠΈΡ ΠΏΡΠΈ ΠΏΡΠΎΠΊΡΡΡΠΊΠ΅ β
React-reveal
import Fade from 'react-reveal/Fade';
<Fade top>
<h1>Title</h1>
</Fade>
ΠΡΠ΅Π³ΠΎ Π΅ΡΡΡ ΠΏΡΡΡ Π±Π»ΠΎΠΊΠΎΠ², Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΈΠ· Π½ΠΈΡ
ΠΏΠΎΠ»Π½ΠΎΡΠΊΡΠ°Π½Π½Π°Ρ ΡΡΡΠ°Π½ΠΈΡΠ° ΠΈ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ.
import React, { Component, Fragment } from 'react';
import Fade from 'react-reveal/Fade';
const animateList = [1, 2, 3, 4, 5];
export default class ReactReveal extends Component {
render() {
return (
<Fragment>
{animateList.map((item, key) => (
<div style={styles.block} key={key}>
<Fade top>
<h1 style={styles.title}>{`block ${item}`}</h1>
</Fade>
</div>
))}
</Fragment>
);
}
}
const styles = {
block: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100%',
background: '#000',
borderBottom: '1px solid rgba(255,255,255,.2)',
},
title: {
textAlign: 'center',
fontSize: 100,
color: '#fff',
fontFamily: 'Lato, sans-serif',
fontWeight: 100,
},
};
Π’Π΅ΠΏΠ΅ΡΡ Π²Π²ΠΎΠ΄ΠΈΠΌ ΠΊΠΎΠ½ΡΡΠ°Π½ΡΡ animateList. Π ΠΌΠ°ΡΡΠΈΠ² Π²ΠΊΠ»ΡΡΠ΅Π½Ρ ΠΏΡΡΡ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ². ΠΠΎΡΠ»Π΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΌΠ΅ΡΠΎΠ΄Π° ΠΌΠ°ΡΡΠΈΠ²Π° map Π΅ΡΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ ΡΠ΅Π½Π΄Π΅ΡΠΈΡΡ Π»ΡΠ±ΠΎΠΉ ΡΠ»Π΅ΠΌΠ΅Π½Ρ Π² ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°Ρ Fade, Π²ΡΡΠ°Π²Π»ΡΡ ΡΠ»Π΅ΠΌΠ΅Π½ΡΡ Π² Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ. Π‘ΡΠΈΠ»ΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Ρ Π² ΠΊΠΎΠ½ΡΡΠ°Π½ΡΠ΅ styles, ΠΏΠΎΠ»ΡΡΠ°ΡΡ ΠΊΠΎΡΠΎΡΠΊΠΈΠ΅ CSS-ΡΡΠΈΠ»ΠΈ ΠΊΠ°ΠΊ Π΄Π»Ρ Π±Π»ΠΎΠΊΠ°, ΡΠ°ΠΊ ΠΈ Π΄Π»Ρ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ°. ΠΡΡΠ΅ β ΠΏΡΡΡ Π±Π»ΠΎΠΊΠΎΠ² Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΠ΅ΠΉ Fade.
TweenOne ΠΈ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ Π² Ant Design
Π ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π΄ΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ ΠΌΠ½ΠΎΠ³ΠΎ Π°Π½ΠΈΠΌΠΈΡΠΎΠ²Π°Π½Π½ΡΡ
ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ². Π£ Π±ΠΎΠ»ΡΡΠΈΠ½ΡΡΠ²Π° ΠΈΠ· Π½ΠΈΡ
ΡΡ
ΠΎΠΆΠ°Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ, ΡΠ°ΠΊ ΡΡΠΎ ΠΏΡΠΈΠΌΠ΅Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ Π±ΡΠ΄Π΅Ρ ΠΏΡΠΎΡΠ΅ ΡΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ Π²ΡΡΠ΅. Π‘ΡΠ΄Π° Π²ΠΎΠΉΠ΄ΡΡ Π»ΠΈΡΡ ΡΠ°Ρ, Π·Π΅Π»Π΅Π½ΡΠΉ ΡΠ°ΡΠΈΠΊ ΠΈ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠΉ ΡΠ»Π΅ΠΌΠ΅Π½Ρ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΊΡΠ°ΡΠ½ΡΠΉ ΠΊΠ²Π°Π΄ΡΠ°Ρ.
Π Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ TweenOne, ΠΊΠΎΡΠΎΡΠΎΠΌΡ Π½ΡΠΆΠ΅Π½ PathPlugin, ΡΡΠΎΠ±Ρ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎ Π·Π°Π΄Π°ΡΡ ΡΡΠ°Π΅ΠΊΡΠΎΡΠΈΡ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΡ. Π Π°Π±ΠΎΡΠ°ΡΡ Π²ΡΠ΅ ΡΡΠΎ Π±ΡΠ΄Π΅Ρ Π»ΠΈΡΡ Π² ΡΠΎΠΌ ΡΠ»ΡΡΠ°Π΅, Π΅ΡΠ»ΠΈ ΠΏΠΎΠΌΠ΅ΡΡΠΈΡΡ
PathPlugin Π² TweenOne.plugins.
TweenOne.plugins.push(PathPlugin);
ΠΡΠ½ΠΎΠ²Π½ΡΠΌΠΈ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ°ΠΌΠΈ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ ΡΠ²Π»ΡΡΡΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠ΅:
- duration β Π²ΡΠ΅ΠΌΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ Π² ΠΌΡ;
- ease β ΠΏΠ»Π°Π²Π½ΠΎΡΡΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ;
- yoyo β ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΡ Π²ΠΏΠ΅ΡΡΠ΄ ΠΈ Π½Π°Π·Π°Π΄ Ρ ΠΏΡΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΏΠΎΠ²ΡΠΎΡΠ΅Π½ΠΈΠΈ;
- repeat β ΠΏΠΎΠ²ΡΠΎΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ. ΠΡΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ -1 Π΄Π»Ρ Π±Π΅ΡΠΊΠΎΠ½Π΅ΡΠ½ΠΎΠΉ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ;
- p β ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΡ ΠΏΡΡΠΈ Π΄Π»Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ;
- easePath β ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΡ ΠΏΠ»Π°Π²Π½ΠΎΠ³ΠΎ ΠΏΡΡΠΈ Π΄Π»Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
ΠΠ²Π° ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΡ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ° Π²Π΅ΡΡΠΌΠ° ΡΠΏΠ΅ΡΠΈΡΠΈΡΠ½Ρ, Π½ΠΎ ΠΎ Π½ΠΈΡ Π½Π΅ ΡΡΠΎΠΈΡ Π±Π΅ΡΠΏΠΎΠΊΠΎΠΈΡΡΡΡ, Π²ΡΠ΅ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ, ΠΊΠ°ΠΊ Π½ΡΠΆΠ½ΠΎ.
const duration = 7000;
const ease = 'easeInOutSine';
const p =
'M123.5,89.5 C148,82.5 239.5,48.5 230,17.5 C220.5,-13.5 127,6 99.5,13.5 C72,21 -9.5,56.5 1.5,84.5 C12.5,112.5 99,96.5 123.5,89.5 Z';
const easePath =
'M0,100 C7.33333333,89 14.3333333,81.6666667 21,78 C25.3601456,75.6019199 29.8706084,72.9026327 33,70 C37.0478723,66.2454406 39.3980801,62.0758689 42.5,57 C48,46.5 61.5,32.5 70,28 C77.5,23.5 81.5,20 86.5,16 C89.8333333,13.3333333 94.3333333,8 100,0';
const loop = {
yoyo: true,
repeat: -1,
duration,
ease,
};
Π’Π΅ΠΏΠ΅ΡΡ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡΠΈΡΡΡΠΏΠ°ΡΡ ΠΊ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠ° Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
- redSquare ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΡΠΈΠΊΠ»Π° ΠΏΠ»ΡΡ ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΡ Y, Π΄Π»ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡ ΠΈ Π·Π°Π΄Π΅ΡΠΆΠΊΡ.
- greenBall ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΠΏΡΡΡ Ρ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ°ΠΌΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΠ° x, Ρ β Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ p. ΠΡΠΎΠΌΠ΅ ΡΠΎΠ³ΠΎ, Π΄Π»ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡ, ΠΏΠΎΠ²ΡΠΎΡ ΠΈ ΠΏΠ»Π°Π²Π½ΠΎΡΡΡ β ΡΡΠ½ΠΊΡΠΈΡ TweenOne.easing.path, Ρ ΠΊΠΎΡΠΎΡΠΎΠΉ Π΄Π²Π° ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ°.
- path β easePath.
- lengthPixel β ΠΊΡΠΈΠ²Π°Ρ, ΠΊΠΎΡΠΎΡΠ°Ρ ΡΠ°Π·Π΄Π΅Π»Π΅Π½Π° Π²ΡΠ΅Π³ΠΎ Π½Π° 400 ΡΠ΅ΠΊΡΠΈΠΉ.
- track β ΠΎΠ²Π°Π» Ρ ΠΎΡΡΠΌΠΈ, Ρ Π½Π΅Π³ΠΎ Π΅ΡΡΡ ΡΡΠΈΠ»ΠΈ ΡΠΈΠΊΠ»Π° ΠΈ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡ ΠΏΠΎΠ²ΠΎΡΠΎΡΠ°.
const animate = {
redSquare: {
...loop,
y: 15,
duration: 3000,
delay: 200,
},
greenBall: {
path: { x: p, y: p },
duration: 5000,
repeat: -1,
ease: TweenOne.easing.path(easePath, { lengthPixel: 400 }),
},
track: {
...loop,
rotate: 15,
},
};
Π’Π°ΠΊΠΆΠ΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΠΎΠ±ΡΠ°ΡΠΈΡΡ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ TweenOne. ΠΡΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ Π±ΡΠ΄ΡΡ ΠΈΠΌΠΏΠΎΡΡΠΈΡΠΎΠ²Π°Π½Ρ ΠΈΠ· rc-tween-one. TweenOne β Π±Π°Π·ΠΎΠ²ΡΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Ρ Π±Π°Π·ΠΎΠ²ΡΠΌΠΈ ΠΆΠ΅ proprs ΠΈ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΎΠ½Π½ΡΠΌΠΈ props, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΈ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΡΡ ΡΠΎΠ±ΠΎΠΉ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ. Π£ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ TweenOne β ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠ΅ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ, ΡΠ°ΠΊΠΈΠ΅, ΠΊΠ°ΠΊ redSquare, track, greenBall.
import React from 'react';
import TweenOne from 'rc-tween-one';
export default function BannerImage() {
return (
<div className="wrapper-ant-design">
<svg width="482px" height="500px" viewBox="0 0 482 500">
<defs>
<path
d="M151,55 C129.666667,62.6666667 116,74.3333333 110,90 C104,105.666667 103,118.5 107,128.5 L225.5,96 C219.833333,79 209.666667,67 195,60 C180.333333,53 165.666667,51.3333333 151,55 L137,0 L306.5,6.5 L306.5,156 L227,187.5 L61.5,191 C4.5,175 -12.6666667,147.833333 10,109.5 C32.6666667,71.1666667 75,34.6666667 137,0 L151,55 Z"
id="mask"
/>
</defs>
<g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd" transform="translate(0, 30)">
<g id="Group-13" transform="translate(0.000000, 41.000000)">
<TweenOne component="g" animation={animate.redSquare}>
<rect
stroke="#F5222D"
strokeWidth="1.6"
transform="translate(184.000000, 18.000000) rotate(8.000000) translate(-184.000000, -18.000000) "
x="176.8"
y="150.8"
width="14.4"
height="14.4"
rx="3.6"
/>
</TweenOne>
</g>
<g id="Group-14" transform="translate(150.000000, 230.000000)">
<g id="Group-22" transform="translate(62.000000, 7.000000)">
<image
id="cc4"
alt="globe"
xlinkHref="https://gw.alipayobjects.com/zos/rmsportal/FpKOqFadwoFFIZFExjaf.png"
width="151px"
height="234px"
/>
</g>
<mask id="mask-2">
<use xlinkHref="#mask" fill="white" transform="translate(-42, -33)" />
</mask>
<g mask="url(#mask-2)">
<TweenOne component="g" animation={animate.track} style={{ transformOrigin: '122.7px 58px' }}>
<g transform="translate(-16, -52)">
<g transform="translate(16, 52)">
<path
d="M83.1700911,35.9320015 C63.5256194,37.9279025 44.419492,43.1766434 25.8517088,51.6782243 C14.3939956,57.7126276 7.77167019,64.8449292 7.77167019,72.4866248 C7.77167019,94.1920145 61.1993389,111.787709 127.105708,111.787709 C193.012078,111.787709 246.439746,94.1920145 246.439746,72.4866248 C246.439746,55.2822262 212.872939,40.6598106 166.13127,35.3351955"
id="line-s"
stroke="#0D1A26"
strokeWidth="1.35"
strokeLinecap="round"
transform="translate(127.105708, 73.561453) rotate(-16.000000) translate(-127.105708, -73.561453) "
/>
</g>
<TweenOne component="g" animation={animate.greenBall}>
<image
alt="globe"
id="id2"
xlinkHref="https://gw.alipayobjects.com/zos/rmsportal/IauKICnGjGnotJBEyCRK.png"
x="16"
y="62"
width="26px"
height="26px"
/>
</TweenOne>
</g>
</TweenOne>
</g>
</g>
</g>
</svg>
</div>
);
}
ΠΠ°, Π²ΡΠ³Π»ΡΠ΄ΠΈΡ ΡΡΡΠ°ΡΠ½ΠΎΠ²Π°ΡΠΎ, Π½ΠΎ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΡΡΠΎΠ³ΠΎ ΠΌΠ΅ΡΠΎΠ΄Π° ΠΏΡΠΎΡΡΠ°.
<TweenOne component="g" animation={animate.redSquare} />
<TweenOne component="g" animation={animate.track} />
<TweenOne component="g" animation={animate.greenBall} />
Π’ΡΠ΅Π±ΡΠ΅ΡΡΡ Π²ΡΠ΅Π³ΠΎ Π»ΠΈΡΡ ΠΎΠΏΠΈΡΠ°ΡΡ ΠΏΡΠ°Π²ΠΈΠ»Π° Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ ΠΈ ΠΏΠ΅ΡΠ΅Π½Π΅ΡΡΠΈ ΠΈΡ Π² ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ TweenOne.
ΠΠ»Ρ Π΄ΠΎΡΡΠΈΠΆΠ΅Π½ΠΈΡ ΡΠ°Π·Π½ΡΡ ΡΠ΅Π»Π΅ΠΉ Π½ΡΠΆΠ½Ρ ΡΠ°Π·Π½ΡΠ΅ ΠΏΠΎΠ΄Ρ ΠΎΠ΄Ρ. Π ΡΡΠΎΠΉ ΡΡΠ°ΡΡΠ΅ Π±ΡΠ»ΠΈ ΡΠ°ΡΡΠΌΠΎΡΡΠ΅Π½Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠ΅ΡΠ΅Π½ΠΈΠΉ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π² Π±ΠΎΠ»ΡΡΠΎΠΌ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π΅ ΠΏΡΠΎΠ΅ΠΊΡΠ°. ΠΠ°ΡΠ΅ Π΄Π΅Π»ΠΎ β Π²ΡΠ±ΡΠ°ΡΡ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΡΡΠ΅Π΅.
Skillbox ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅Ρ:
- ΠΠ²ΡΡ Π»Π΅ΡΠ½ΠΈΠΉ ΠΏΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΊΡΡΡ
Β«Π― β Π²Π΅Π±-ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊ PROΒ» .- ΠΠ½Π»Π°ΠΉΠ½-ΠΊΡΡΡ
Β«Π‘#-ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊ Ρ Π½ΡΠ»ΡΒ» .- ΠΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΉ Π³ΠΎΠ΄ΠΎΠ²ΠΎΠΉ ΠΊΡΡΡ
Β«PHP-ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊ Ρ 0 Π΄ΠΎ PROΒ» .
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com