{"id":368887,"date":"2024-05-21T03:51:43","date_gmt":"2024-05-21T03:51:43","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=368887"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=368887","title":{"rendered":"<span>\u041f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u043e\u0442\u00a0We\u00a0Wizards: \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0432\u0430\u0441 \u0436\u0434\u0443\u0442 \u0443\u0441\u043f\u0435\u0445 \u0432\u00a0\u0434\u0435\u043b\u0430\u0445 \u0438\u00a0\u043d\u043e\u0432\u044b\u0435 \u0441\u043a\u0438\u043b\u043b\u044b<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412\u043c\u0435\u0441\u0442\u0435 \u0441\u00a0\u0414\u0430\u043d\u0438\u0438\u043b\u043e\u043c \u0421\u0430\u0440\u0430\u0431\u044c\u0435\u0432\u044b\u043c\u00a0(\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a We\u00a0Wizards) \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0438\u0441, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0437\u0430\u043a\u0440\u044b\u0442\u044b\u0445 \u043a\u0430\u0440\u0442 \u0442\u0430\u0440\u043e \u0441\u00a0\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u0441\u043a\u0440\u044b\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043a\u0430\u0440\u0442\u044b.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b06\/344\/41a\/b0634441a4e377bdea0418e7d421fc1c.png\" width=\"2000\" height=\"962\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b06\/344\/41a\/b0634441a4e377bdea0418e7d421fc1c.png\"\/><\/figure>\n<p><strong>\u0420\u0430\u0437\u0434\u0435\u043b\u0438\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430\u00a0\u0434\u0432\u0430 \u043a\u043b\u0430\u0441\u0441\u0430:<\/strong><\/p>\n<ul>\n<li>\n<p>\u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 (\u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e\u00a0TarotController);<\/p>\n<\/li>\n<li>\n<p>\u043a\u043b\u0430\u0441\u0441 \u0435\u0434\u0438\u043d\u0438\u0447\u043d\u043e\u0439 \u043a\u0430\u0440\u0442\u044b (TarotCard).<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u043f\u043e\u043a\u0430\u0437 \u0438 \u0441\u043a\u0440\u044b\u0442\u0438\u0435 \u043a\u0430\u0440\u0442, \u0442\u0430\u043a \u0436\u0435 \u0432 \u043d\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u043a\u0440\u0443\u0442\u0438\u0442\u044c\u0441\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u0430\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>requestAnimationFrame<\/code>. \u0412 \u043a\u0430\u0436\u0434\u043e\u043c \u0446\u0438\u043a\u043b\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 update \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 <code>TarotCard<\/code>(\u043e\u0431 \u044d\u0442\u043e\u043c \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435).<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443, \u0433\u0434\u0435 \u043f\u043e\u043a\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0441 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c <code>type=\u201dmodule\u201d<\/code> \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u043e\u0432.<\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u0441 \u043a\u043b\u0430\u0441\u0441\u043e\u043c container, \u0432\u043d\u0443\u0442\u0440\u044c \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u043b\u043e\u0436\u0438\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442 c \u043a\u043b\u0430\u0441\u0441\u043e\u043c cards-container \u0434\u043b\u044f \u0432\u0441\u0442\u0432\u043a\u0438 \u0441\u0430\u043c\u0438\u0445 \u043a\u0430\u0440\u0442 \u0438 \u043a\u043d\u043e\u043f\u043a\u0443 \u0441 \u043a\u043b\u0430\u0441\u0441\u043e\u043c reset \u0434\u043b\u044f \u0441\u0431\u0440\u043e\u0441\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u044b\u0445 \u043a\u0430\u0440\u0442.<\/p>\n<p>\u0417\u0430\u0440\u0430\u043d\u0435\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0435\u043c\u043f\u043b\u0435\u0439\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 <code>TarotCard<\/code>:<\/p>\n<pre><code class=\"xml\">\/&lt;!DOCTYPE html> &lt;html lang=\"en\"> &lt;head>   &lt;meta charset=\"UTF-8\">   &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">   &lt;title>Animatied tarot&lt;\/title> &lt;\/head> &lt;body>   &lt;div class=\"container\">     &lt;div class=\"cards-container\">&lt;\/div>     &lt;button class=\"reset\">RESET&lt;\/button>   &lt;\/div>    &lt;template id=\"card\">     &lt;div class=\"card\">&lt;\/div>   &lt;\/template>    &lt;script type=\"module\" src=\".\/js\/index.js\">&lt;\/script> &lt;\/body> &lt;\/html><\/code><\/pre>\n<p>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u201c\u043d\u0430 \u043e\u0449\u0443\u043f\u044c\u201d \u043a\u043e\u0434 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u043f\u043e\u043a\u0430 \u0431\u0435\u0437 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u043b\u043e\u0433\u0438\u043a\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u044f, \u043d\u0435 \u0437\u0430\u043f\u0443\u0442\u0430\u0435\u043c\u0441\u044f.<\/p>\n<pre><code class=\"javascript\">import Card from \".\/TarotCard.js\"; import cardsData from '..\/data.js';  export default class TarotController {    \/**    * \u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u0440\u0435\u0437\u043c\u0435\u0442\u043a\u0438 \u043a\u0430\u0440\u0442    * @type {HTMLElement}    *\/   container;    \/**    * \u041c\u0430\u0441\u0441\u0438\u0432 \u0441 \u0442\u0435\u043a\u0443\u0449\u0438\u043c\u0438 \u043a\u0430\u0440\u0442\u0430\u043c\u0438    * @type {TarotCard[]}    *\/   cards = [];    constructor() {     this.container = document.querySelector('.cards-container');     this.setCards();     this.loop();   }    \/**    * \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u043a\u0430\u0440\u0442    * \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435    *    * @param {number} amount - \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u0430\u0440\u0442    *\/   async setCards(amount = 5) {     this.reset().then(() => {       const shuffledCards = this.getShuffledCards();       for (let i = 0; i &lt; amount; i ++) {         if (!shuffledCards[i]) {           return;         }         this.cards.push(new TarotCard(shuffledCards[i], i, amount, this));       }     });   }  \/**    * \u041c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043a\u0430\u0440\u0442    *\/   loop() {     this.cards.forEach(card => card.update());     requestAnimationFrame(this.loop.bind(this));   }    \/**    * \u0421\u043f\u0440\u044f\u0442\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043a\u0430\u0440\u0442\u044b \u0438 \u043e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440     * \u0441 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u043e\u0439    *\/   reset() {     return new Promise((resolve) => {       if (!this.cards.length) {         resolve(true);         return;       }        this.cards.forEach(card => card.fadeOut());        setTimeout(() => {         this.cards = [];         this.container.innerHTML = '';         resolve(true);       }, 800);     });   }    \/**    * \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u0448\u0430\u043d\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u043a\u0430\u0440\u0442\u0430\u043c\u0438    * @return {Object} \u041f\u0435\u0440\u0435\u043c\u0435\u0448\u0430\u043d\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u043a\u0430\u0440\u0442\u0430\u043c\u0438    *\/   getShuffledCards() {     return cardsData       .map(val => ({ val, sort: Math.random() }))       .sort((a, b) => a.sort > b.sort ? 1 : -1)       .map(({ val }) => val);   } }<\/code><\/pre>\n<p>\u0421\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u0437\u0430\u0434\u0430\u0442\u044c \u043d\u0430\u0431\u043e\u0440 \u043a\u0430\u0440\u0442 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>TarotController.setCards<\/code> \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u0435\u0442\u043e\u0434 \u044d\u0442\u043e\u0433\u043e \u0436\u0435 \u043a\u043b\u0430\u0441\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041c\u0435\u0442\u043e\u0434 <code>TarotController.reset<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0440\u043e\u043c\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0437\u043e\u043b\u0432\u0438\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443, \u0435\u0441\u043b\u0438 \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u043a\u0430\u0440\u0442\u0430\u043c\u0438 <code>TarotController.\u0441ards<\/code>  \u043f\u0443\u0441\u0442\u043e\u0439, \u0432 \u0438\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u043f\u0440\u044f\u0447\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u043a\u0430\u0440\u0442\u044b, \u0436\u0434\u0435\u043c \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0438 \u0447\u0438\u0441\u0442\u0438\u043c \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443 \u0438 \u043c\u0430\u0441\u0441\u0438\u0432 <code>TarotController.\u0441ards<\/code>.<\/p>\n<p>\u0412 \u043c\u0435\u0442\u043e\u0434\u0435 <code>TarotController.setCards<\/code> \u043f\u043e\u0441\u043b\u0435 \u0440\u0435\u0437\u043e\u043b\u0432\u0430 \u043f\u0440\u043e\u043c\u0438\u0441\u0430 <code>reset<\/code> \u043f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u043c\u044b \u043f\u0435\u0440\u0435\u043c\u0435\u0448\u0438\u0432\u0430\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u043a\u0430\u0440\u0442\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043d\u0430 2 \u0441\u0442\u0440\u043e\u043a\u0435 \u0444\u0430\u0439\u043b\u0430 (<code>import cardsData from '..\/data.js';<\/code>). \u0417\u0430\u0442\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 for \u0438\u0442\u0435\u0440\u0438\u0440\u0443\u0435\u043c\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437 \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 <code>TarotCard<\/code>, \u043a\u0443\u0434\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043a\u0430\u0440\u0442\u044b (\u043f\u043e\u043a\u0430 \u0431\u0435\u0437 \u0440\u0430\u0437\u043d\u0438\u0446\u044b, \u0447\u0442\u043e \u044d\u0442\u043e \u0431\u0443\u0434\u0443\u0442 \u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0435), \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0438\u043d\u0434\u0435\u043a\u0441 \u043a\u0430\u0440\u0442\u044b, \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b-\u0432\u043e \u043a\u0430\u0440\u0442 \u0438 \u0441\u0430\u043c \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u0447\u0442\u043e\u0431\u044b \u0443 \u043a\u0430\u0440\u0442\u044b \u0431\u044b\u043b \u043a \u043d\u0435\u043c\u0443 \u0434\u043e\u0441\u0442\u0443\u043f.<\/p>\n<p><strong>\u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0435\u043c \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c\u0443 \u2014 \u043f\u0438\u0448\u0435\u043c \u043a\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430 TarotCard \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0432\u0441\u0435 \u0437\u0430\u0434\u0443\u043c\u0430\u043d\u043d\u044b\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0430 \u0438\u043c\u0435\u043d\u043d\u043e:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438 (\u0432\u044b\u043f\u043b\u044b\u0432\u0430\u043d\u0438\u0435 \u0438\u0437 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043a\u0438);<\/p>\n<\/li>\n<li>\n<p>\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u0441\u043a\u0440\u044b\u0442\u0438\u044f \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438 (\u0441\u043a\u0440\u044b\u0442\u0438\u0435 \u043a\u0430\u0440\u0442\u044b \u0437\u0430 \u043d\u0438\u0436\u043d\u044e\u044e \u0433\u0440\u0430\u043d\u0438\u0446\u0443 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b);<\/p>\n<\/li>\n<li>\n<p>\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u043f\u043e \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u044e \u043d\u0430 \u043a\u0430\u0440\u0442\u0443 (\u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043f\u043e \u043e\u0441\u0438 Z, \u0431\u043b\u0438\u0436\u0435 \u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e);<\/p>\n<\/li>\n<li>\n<p>\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f (\u201d\u0440\u0430\u0437\u0432\u043e\u0440\u043e\u0442\u0430\u201d) \u043a\u0430\u0440\u0442\u044b \u043f\u043e \u043a\u043b\u0438\u043a\u0443.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u043d\u0435\u0440\u0446\u0438\u0438:<\/p>\n<p><code>position += (targetPosition - position) * coeff;<\/code>.<\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f position \u043a\u0430\u0436\u0434\u044b\u0439 \u0446\u0438\u043a\u043b \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0430\u0442\u044c\u0441\u044f \u043a \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043d\u0430 \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u0440\u0430\u0432\u043d\u043e\u0435 \u0440\u0430\u0437\u043d\u0438\u0446\u0435 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u043d\u043e\u0439 \u043d\u0430 \u043a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438.<\/p>\n<p>\u041f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 <code>TarotCard<\/code>. \u0417\u0430\u043e\u0447\u043d\u043e \u043c\u044b \u0443\u0436\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 \u043a\u0430\u043a\u0438\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b:<\/p>\n<pre><code class=\"javascript\">import TarotController from \".\/TarotController.js\";  export default class TarotCard {    \/**    * @type {TarotController}    *\/   controller;      \/**    *     * @param {*} data     * @param {number} index - \u0418\u043d\u0434\u0435\u043a\u0441 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043a\u0430\u0440\u0442\u044b    * @param {number} amount - \u041e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b-\u0432\u043e \u043a\u0430\u0440\u0442    * @param {TarotController} controller     *\/   constructor(data, index, amount, controller) {     this.controller = controller;   }    fadeOut() {}    fadeIn() {}    update() {} }<\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>fadeOut<\/code> \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u043a\u0430\u0440\u0442\u0443 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>reset<\/code> \u0443 \u043a\u043b\u0430\u0441\u0441\u0430 <code>TarotController<\/code>. \u0417\u0430\u043e\u0434\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>fadeIn<\/code> \u0434\u043b\u044f \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u0430\u0440\u0442\u044b.<\/p>\n<p>\u041c\u0435\u0442\u043e\u0434 update \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u0446\u0438\u043a\u043b \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0432 <code>TarotController<\/code>, \u0442\u0443\u0442 \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0438 \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u044b \u043a\u0430\u0440\u0442\u044b.<\/p>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043a\u0430\u043a\u0438\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0443 \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u0430\u0440\u0442\u044b \u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u043b\u044f \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 TarotCard:<\/p>\n<pre><code class=\"javascript\">export default class TarotCard {  \/**    * @type {TarotController}    *\/   controller;  isFadeIn = false; isFadeOut = false; isHovered = false; isRevealed = false;    ... }<\/code><\/pre>\n<p>\u0421\u0440\u0430\u0437\u0443 \u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0432 \u043d\u0430\u0448\u0438\u0445 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u0430\u0445:<\/p>\n<pre><code class=\"javascript\">fadeOut() {   this.isFadeIn = false;   this.isFadeOut = true; }  fadeIn() {   this.isFadeIn = true;   this.isFadeOut = false;    }<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0441\u0434\u0435\u043b\u0430\u0442\u044c HTML-\u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u0447\u0442\u043e\u0431\u044b \u0443\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u00a0TarotCard.createElement, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u00a0\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435. \u0412\u00a0\u043d\u0435\u043c \u043c\u044b\u00a0\u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043d\u0430\u0448 template\u00a0#card, \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u0438\u00a0\u0432\u0441\u0442\u0430\u0432\u0438\u043c \u0432\u00a0\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u043f\u043e\u043a\u0430 \u0431\u0435\u0437 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"javascript\">createElement() {     const clone = document.querySelector('#card').content.cloneNode(true);     this.element = clone.querySelector('.card');     this.controller.container.appendChild(this.element); \/**      * TODO: \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u043c\u0438      *\/   }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 <code>TarotCard<\/code> \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430.<\/p>\n<p>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0441\u0442\u0438\u043b\u0438 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f:<\/p>\n<pre><code class=\"css\">* {   margin: 0;   padding: 0;   box-sizing: border-box; }  .cards-container {   width: 100%;   height: 100vh;   display: flex;   justify-content: center;   align-items: center;   gap: 2rem;   perspective: 1000px;   overflow: hidden; }  .card {   min-width: 10rem;   aspect-ratio: 9\/16;   background-color: red;   border-radius: 4px;   will-change: transform;   position: relative; }  .reset {   z-index: 2;   cursor: pointer;   position: absolute;   left: 50%;   bottom: 2rem;   transform: translateX(-50%);   padding: 1rem 2rem; }<\/code><\/pre>\n<p>\u041f\u043e\u043a\u0430 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e, \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 <code>TarotController<\/code>. \u0421\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u043e\u0432\u0435\u0441\u0438\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u2014 click-\u043a\u043d\u043e\u043f\u043a\u0443:<\/p>\n<pre><code class=\"javascript\">import TarotController from \".\/modules\/TarotController.js\";  const initTarot = () => {      const tarot = new TarotController();   const btn = document.querySelector('.reset');    btn.addEventListener('click', () => {     tarot.setCards();   }); };  initTarot();<\/code><\/pre>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ac3\/97f\/bbb\/ac397fbbb3b32548722e559ba6b80e16.png\" width=\"2000\" height=\"973\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ac3\/97f\/bbb\/ac397fbbb3b32548722e559ba6b80e16.png\"\/><\/figure>\n<p><strong>\u041e\u0442\u043b\u0438\u0447\u043d\u043e! \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439.<\/strong><\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c, \u043a\u0430\u043a\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0431\u0443\u0434\u0435\u043c \u0430\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041f\u043e \u0437\u0430\u0434\u0443\u043c\u043a\u0435  \u043a\u0430\u0440\u0442\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f \u0432 \u0442\u0440\u0435\u0445 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u0445 \u0438 \u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u0432\u043e\u043a\u0440\u0443\u0433 \u0434\u0432\u0443\u0445 \u043e\u0441\u0435\u0439: &#8212; X \u0438 Y. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c translate3d \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0438 rotateX \u0438 rotateY \u0434\u043b\u044f \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u043e\u0432.<\/p>\n<p>\u041e\u0431\u043e\u0437\u043d\u0430\u0447\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u043b\u044f:<\/p>\n<ul>\n<li>\n<p>\u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0443\u044e (\u0434\u0435\u0444\u043e\u043b\u0442\u043d\u0443\u044e) \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043a\u0430\u043a <code>pos = {x: 0, y: 0, z: 0}<\/code><\/p>\n<\/li>\n<li>\n<p>\u0446\u0435\u043b\u0435\u0432\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c <code>targetPos = {x: 0, y: 0, z: 0}<\/code><\/p>\n<\/li>\n<li>\n<p>\u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a\u0430\u043a <code>rotate = {x: 0, y: 0}<\/code><\/p>\n<\/li>\n<li>\n<p>\u0446\u0435\u043b\u0435\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c <code>targetRotate = {x: 0, y: 0, z: 0}<\/code><\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"javascript\">rotate = {   x: 0,    y: 0, };  pos = {   x: 0,   y: 0,   z: 0, };  targetRotate = {   x: 0,   y: 0, };  targetPos = {   x: 0,   y: 0,   z: 0, };<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0440\u0430\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442\u00a0\u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u043a\u0430\u0440\u0442\u044b \u0438\u00a0\u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043a\u0430\u0440\u0442. \u041f\u043e\u00a0\u0437\u0430\u0434\u0443\u043c\u043a\u0435 \u043a\u0430\u0440\u0442\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u0443\u043a\u0440\u0443\u0433\u043e\u043c, \u0430\u00a0\u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u043a\u0440\u0430\u0439\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430 \u043f\u043e\u00a0\u043e\u0441\u0438\u00a0Y \u0438\u00a0\u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043f\u043e\u00a0\u043e\u0441\u0438\u00a0Z.<\/p>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0443\u0433\u043e\u043b \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u043e\u0442\u00a030\u00b0\u00a0\u0434\u043e \u221230\u00b0, \u0430\u00a0\u043f\u043e\u0437\u0438\u0446\u0438\u044f \u043f\u043e\u00a0\u043e\u0441\u0438\u00a0Z \u043e\u0442\u00a06\u00a0\u0434\u043e\u00a00\u00a0\u0438\u00a0\u043e\u0431\u0440\u0430\u0442\u043d\u043e.<\/p>\n<p>\u0422\u0443\u0442 \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043b\u0438\u043d\u0435\u0439\u043d\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u0438, \u0432\u044b\u0434\u0435\u043b\u0438\u043c \u0435\u0435\u00a0\u0432\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">interpolation(value, min, max, newMin, newMax) { let newValue = ( (value-min) \/ (max-min) ) * (newMax-newMin) + newMin; return newValue; }<\/code><\/pre>\n<p>\u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 \u0447\u0438\u0441\u043b\u043e, \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u043e\u0435 \u0432 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0435 \u043e\u0442 min \u0434\u043e max, \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0435 \u043e\u0442 <code>newMin<\/code> \u0434\u043e <code>newMax<\/code>. <\/p>\n<p>\u0420\u0430\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u043a\u0430\u0440\u0442\u044b \u0438 \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b-\u0432\u0430 \u043a\u0430\u0440\u0442, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0442 -1 \u0434\u043e 1.<\/p>\n<p>\u0418\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c index \u043a\u0430\u0440\u0442\u044b \u043c\u0435\u0436\u0434\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 0 \u0438 \u043a\u043e\u043b-\u0432\u043e \u043a\u0430\u0440\u0442 &#8212; 1 (\u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 index \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430). \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0438\u043c \u043a\u0430\u043a <code>basicCoeff<\/code> :<\/p>\n<pre><code class=\"javascript\">const basicCoeff = interpolation(index, 0, amount -1, -1, 1);<\/code><\/pre>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0435\u0441\u043b\u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0443\u0433\u043e\u043b \u043e\u0442 30<strong>\u00b0<\/strong> \u0434\u043e -30<strong>\u00b0,<\/strong> \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 (\u043e\u0442 -1 \u0434\u043e 1) \u0443\u043c\u043d\u043e\u0436\u0438\u043c \u043d\u0430 -30, \u0430 \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u043c\u043d\u043e\u0436\u0438\u043c \u043d\u0430 6, \u043f\u043e\u043b\u0443\u0447\u0438\u0432 \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043e\u0442 -8 \u0434\u043e 8 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043c\u043e\u0434\u0443\u043b\u044c \u044d\u0442\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u043a\u0430\u0440\u0442\u044b \u043f\u043e\u043b\u0443\u043a\u0440\u0443\u0433\u043e\u043c, \u0432 \u044d\u0442\u043e\u043c \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043a\u043e\u0441\u0438\u043d\u0443\u0441\u0430:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/05a\/1d8\/f74\/05a1d8f747440ebffd7456de11297d4f.png\" width=\"810\" height=\"368\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/05a\/1d8\/f74\/05a1d8f747440ebffd7456de11297d4f.png\"\/><\/figure>\n<p>\u041d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u043e\u0442\u0440\u0435\u0437\u043e\u043a \u043e\u0442 -PI\/2 \u0434\u043e\u00a0PI\/2. \u0418\u00a0\u0442\u0430\u043a \u043a\u0430\u043a \u0443\u00a0\u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u043a\u043e\u0435\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f (\u043e\u0442 \u22121 \u0434\u043e\u00a01), \u0442\u043e\u00a0\u043a\u043e\u0441\u0438\u043d\u0443\u0441 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043a\u0430\u0442\u044c \u043e\u0442\u00a0Math.PI * 0.5 * basicCoeff. \u041d\u043e\u00a0\u043f\u043e\u043a\u0430-\u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0430\u043c \u043d\u0435\u00a0\u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442, \u0442\u0430\u043a \u043a\u0430\u043a \u043a\u043e\u0441\u0438\u043d\u0443\u0441 \u043e\u0442\u00a00\u00a0\u0440\u0430\u0432\u0435\u043d 1. \u0412\u044b\u0447\u0442\u0435\u043c \u0438\u0437\u00a0\u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0435\u0434\u043d\u0438\u0446\u0443 \u0438\u00a0\u0438\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u00a01\u00a0\u0434\u043e\u00a00\u00a0\u0438\u00a0\u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043a\u00a01.<\/p>\n<pre><code class=\"javascript\">const cosCoeff = -(Math.cos(basicCoeff * Math.PI * 0.5) - 1).toFixed(2);<\/code><\/pre>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043c\u0435\u0442\u043e\u0434, \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e\u00a0TarotCard.calculateProps\u00a0\u0438 \u0441\u0440\u0430\u0437\u0443 \u0443\u0447\u0442\u0435\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0435 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u00a0TarotCard.isFadeIn\u00a0(\u043a\u0430\u0440\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0441\u0432\u0435\u0440\u0445\u0443, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e Y):<\/p>\n<pre><code class=\"javascript\">\/**  *   * @param {number} index   * @param {number} amount   *\/ calculateProps(index, amount) {   const basicCoeff = this.interpolation(index, 0, amount - 1, -1, 1);   const cosCoeff = -(Math.cos(basicCoeff * Math.PI * 0.5) - 1).toFixed(2);    \/\/ Calculate rotation on Y-axis   this.rotate.y = -(basicCoeff * 30).toFixed(2);   \/\/ Calculate position on Z-axis   this.pos.z = cosCoeff * 8;    if (this.isFadeIn) {     this.pos.y = -50;     this.targetPos.y = -50;   } }<\/code><\/pre>\n<p>\u0412\u044b\u0437\u043e\u0432\u0435\u043c \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c:<\/p>\n<pre><code class=\"javascript\">\/**    *     * @param {*} data     * @param {number} index     * @param {number} amount     * @param {TarotController} controller     *\/   constructor(data, index, amount, controller) {     this.controller = controller;     this.fadeIn();     this.calculateProps(index, amount);     this.createElement();  console.log('position', this.pos);     console.log('rotation', this.rotate);   }<\/code><\/pre>\n<p>\u0421\u0440\u0430\u0437\u0443 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0438\u043c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u00a0TarotCard.fadeIn, \u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0443\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c. \u0412 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/aad\/b1a\/051\/aadb1a051635425b4c584ce868b3b76f.png\" width=\"630\" height=\"502\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/aad\/b1a\/051\/aadb1a051635425b4c584ce868b3b76f.png\"\/><\/figure>\n<p><em>\u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0432\u0441\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e!<\/em><\/p>\n<p>\u043e\u043f\u043e\u043b\u043d\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u00a0<code>TarotCard.fadeIn<\/code>\u00a0\u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0430\u043c\u0438\u043c \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435\u043c, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e, \u043f\u043e\u0441\u043b\u0435 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b Y \u043d\u0430 0:<\/p>\n<pre><code class=\"javascript\">fadeIn() {     this.isFadeIn = true;     this.isFadeOut = false;      setTimeout(() => {       this.isFadeIn = false;       this.pos.y = 0;     }, 50);   }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u043f\u043b\u0430\u0432\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u043f\u043e\u043b\u044f\u00a0<code>targetPos<\/code>\u00a0\u0438\u00a0<code>targetRotate<\/code>\u00a0\u0432\u00a0\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442\u00a0\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u041f\u0440\u0438 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u044d\u0442\u0438 \u043f\u043e\u043b\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u0442\u0440\u0435\u043c\u0438\u0442\u044c\u0441\u044f \u0432\u00a0\u0441\u0442\u043e\u0440\u043e\u043d\u0443 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439.<\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432\u00a0\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442\u00a0\u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043a\u0430\u0440\u0442\u044b. \u041f\u043e\u00a0\u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u044d\u0442\u0430\u043f\u0443 \u043e\u0441\u0442\u0430\u0432\u043b\u044e \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u0432\u00a0\u043a\u043e\u0434\u0435:<\/p>\n<pre><code class=\"javascript\">calculateTargetPosition() { \/\/ \u0421\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u0411\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435   const output = { ...this.pos };  \/\/ \u0412 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0434\u0432\u0438\u043d\u0435\u043c \u043a\u0430\u0440\u0442\u0443 \u043d\u0430\u0432\u0435\u0440\u0445 \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043d\u0430\u0437\u0430\u0434,   \/\/ \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u043a\u0430\u0440\u0442\u044b \u043f\u043e\u044f\u0432\u043b\u044f\u043b\u0438\u0441\u044c \u0438\u0437 \u043e\u0434\u043d\u043e\u0439 \u043f\u043b\u043e\u0441\u043a\u043e\u0441\u0442\u0438   if (this.isFadeIn) {     output.y = -50;     output.z = 0;   }  \/\/ \u0412 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u0441\u043a\u0440\u044b\u0442\u0438\u044f \u0441\u043f\u0440\u044f\u0447\u0435\u043c \u043a\u0430\u0440\u0442\u0443 \u0432\u043d\u0438\u0437 \u0438 \u0442\u0430\u043a \u0436\u0435 \u043e\u0442\u043e\u0434\u0432\u0438\u043d\u0435\u043c   \/\/ \u0432 \u043e\u0434\u043d\u0443 \u043f\u043b\u043e\u0441\u043a\u043e\u0441\u0442\u044c   if (this.isFadeOut) {     output.y = 50;     output.z = 0;   }  \/\/ \u0415\u0441\u043b\u0438 \u043d\u0430\u0432\u0435\u043b\u0438 \u043a\u0443\u0440\u0441\u043e\u0440 \u043d\u0430 \u043a\u0430\u0440\u0442\u0443, \u0442\u043e \u043f\u043e\u0434\u0432\u0438\u043d\u0435\u043c \u0435\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0431\u043b\u0438\u0436\u0435 \u043a \u043d\u0430\u043c   if (this.isHovered) {     output.z = 10;   } \/\/ \u0412\u0435\u0440\u043d\u0435\u043c \u043d\u043e\u0432\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b   return output; }<\/code><\/pre>\n<p>\u041f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434, \u0440\u0430\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a\u0430\u0440\u0442\u044b:<\/p>\n<pre><code class=\"javascript\">calculateTargetRotate() { \/\/ \u0421\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u0411\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435   const output = { ...this.rotate };  \/\/ \u0415\u0441\u043b\u0438 \u043d\u0430\u0432\u0435\u043b\u0438 \u043a\u0443\u0440\u0441\u043e\u0440 \u043d\u0430 \u043a\u0430\u0440\u0442\u0443 \u0438 \u043e\u043d\u0430 \u0435\u0449\u0435 \u0441\u043a\u0440\u044b\u0442\u0430,    \/\/ \u0442\u043e \u043f\u043e\u0432\u0435\u0440\u043d\u0435\u043c \u0435\u0435 \u043f\u0435\u0440\u043f\u0435\u043d\u0434\u0438\u043a\u0443\u043b\u044f\u0440\u043d\u043e \u044d\u043a\u0440\u0430\u043d\u0443   if (this.isHovered &amp;&amp; !this.isRevealed) {     output.y = 0;   } \/\/ \u0415\u0441\u043b\u0438 \u043d\u0430\u0432\u0435\u043b\u0438 \u043a\u0443\u0440\u0441\u043e\u0440 \u043d\u0430 \u043a\u0430\u0440\u0442\u0443 \u0438 \u043e\u043d\u0430 \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u0430,    \/\/ \u0442\u043e \u043f\u043e\u0432\u0435\u0440\u043d\u0435\u043c \u0435\u0435 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043f\u0435\u0440\u043f\u0435\u043d\u0434\u0438\u043a\u0443\u043b\u044f\u0440\u043d\u043e \u044d\u043a\u0440\u0430\u043d\u0443   if (this.isRevealed &amp;&amp; this.isHovered) {     output.y = 180;   } \/\/ \u0415\u0441\u043b\u0438 \u043a\u0430\u0440\u0442\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u0430, \u0442\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0435\u043c \u0435\u0435 \u043d\u0430 180 \u0433\u0440\u0430\u0434\u0443\u0441\u043e\u0432   if (this.isRevealed &amp;&amp; !this.isHovered) {     output.y = this.rotate.y + 180;   } \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043d\u0430\u043a\u043b\u043e\u043d \u043f\u043e \u043e\u0441\u0438 X \u0438 \u0441\u0431\u0440\u043e\u0441\u0438\u043c \u043f\u043e\u0432\u043e\u0440\u043e\u0442 \u043f\u043e \u043e\u0441\u0438 Y    \/\/ \u043a\u043e\u0433\u0434\u0430 \u043a\u0430\u0440\u0442\u0430 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u043b\u0438 \u0438\u0441\u0447\u0435\u0437\u0430\u0435\u0442   if (this.isFadeIn || this.isFadeOut) {     output.y = 0;     output.x = this.isFadeIn ? 15 : -15;   }   \/\/ \u0412\u0435\u0440\u043d\u0435\u043c \u043d\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f   return output; }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u00a0<code>targetRotate<\/code>\u00a0\u0438\u00a0<code>targetPos<\/code>\u00a0\u0432\u00a0\u0441\u0442\u043e\u0440\u043e\u043d\u0443 \u043d\u043e\u0432\u044b\u0445 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442. \u041a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044e \u044d\u0442\u043e\u0439 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u044f\u00a0\u0443\u0436\u0435 \u043e\u043f\u0438\u0441\u0430\u043b \u0432\u044b\u0448\u0435, \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c:<\/p>\n<pre><code class=\"javascript\">const rotate = this.calculateTargetRotate(); \/\/ 0.1 - \u043a\u043e\u0435\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u043f\u0440\u043e\u0449\u0435 \u0433\u043e\u0432\u043e\u0440\u044f - \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 this.targetRotate.y += (rotate.y - this.targetRotate.y) * 0.1;<\/code><\/pre>\n<p>\u041e\u0431\u043e\u0431\u0449\u0438\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0435\u0439, \u0431\u0443\u0434\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u00a0\u0446\u0438\u043a\u043b\u0435 \u043f\u043e\u00a0\u043a\u043b\u044e\u0447\u0430\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438\u00a0\u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0443\u0435\u043c\u00a0\u0438\u0445, \u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u043f\u043e\u00a02\u00a0\u0446\u0438\u0444\u0440\u044b \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u044f\u0442\u043e\u0439:<\/p>\n<pre><code class=\"javascript\">update() {     const rotate = this.calculateTargetRotate();     const pos = this.calculateTargetPosition();      Object.keys(pos).forEach(key => {       this.targetPos[key] += (pos[key] - this.targetPos[key]) * 0.1; this.targetPos[key] = +(this.targetPos[key].toFixed(2));     });      Object.keys(rotate).forEach(key => {       this.targetRotate[key] += (rotate[key] - this.targetRotate[key]) * 0.1; this.targetRotate[key] = +(this.targetRotate[key].toFixed(2));     });   }<\/code><\/pre>\n<p>\u0415\u0449\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u00a0\u0431\u0443\u0434\u0435\u043c \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438, \u0430\u00a0\u043f\u043e\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439\u00a0<code>isHovered<\/code>\u00a0\u0438\u00a0<code>isRevealed<\/code>. \u041f\u043e\u0432\u0435\u0441\u0438\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043d\u0430\u00a0\u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 \u0438\u00a0\u0432\u044b\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0430\u043c\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430:<\/p>\n<pre><code class=\"javascript\">addListeners() {   this.element.addEventListener('mousemove', () => {     this.isHovered = true;   });    this.element.addEventListener('mouseleave', () => {     this.isHovered = false;   }); \/\/ \u0411\u0443\u0434\u0435\u043c \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0438 \u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u0440\u0442\u0443 \u043f\u043e \u043a\u043b\u0438\u043a\u0443 \u043d\u0430 \u043d\u0435\u0435   this.element.addEventListener('click', () => {     this.isRevealed = !this.isRevealed;   }); }<\/code><\/pre>\n<pre><code class=\"javascript\">\/**  *   * @param {*} data   * @param {number} index   * @param {number} amount   * @param {TarotController} controller   *\/ constructor(data, index, amount, controller) {   this.controller = controller;   this.fadeIn();   this.calculateProps(index, amount);   this.createElement();   this.addListeners(); }<\/code><\/pre>\n<p>\u0412\u0441\u0435 \u043f\u0440\u0438\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u044b, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0441\u043e\u00a0\u0441\u0442\u0438\u043b\u044f\u043c\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u00a0<code>TarotCard.setStyles<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u00a0\u043c\u0435\u0442\u043e\u0434\u0435 update \u043f\u043e\u0441\u043b\u0435 \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442:<\/p>\n<pre><code class=\"javascript\">setStyles() {     if (!this.element) {       return;     }     this.element.style.transform = `translate3d(${this.targetPos.x}rem, ${this.targetPos.y}rem, ${this.targetPos.z}rem)       rotateX(${this.targetRotate.x}deg) rotateY(${this.targetRotate.y}deg)`;   }<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0442\u0438\u043b\u0438 \u043d\u0430\u0448\u0438\u043c \u043a\u0430\u0440\u0442\u0430\u043c \u0438\u00a0\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/58b\/eeb\/76f\/58beeb76f296beb9710fc562c5f344d8.gif\" width=\"1920\" height=\"930\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/58b\/eeb\/76f\/58beeb76f296beb9710fc562c5f344d8.gif\"\/><\/figure>\n<p><strong>\u0412\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u043d\u0430\u0432\u0435\u0441\u0442\u0438 CSS-\u043c\u0438\u0448\u0443\u0440\u044b.<\/strong><\/p>\n<p>\u0414\u043e\u00a0\u0441\u0438\u0445 \u043f\u043e\u0440 \u043c\u044b\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0432\u00a0\u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u0430\u0441\u0441\u0438\u0432 \u0441\u00a0\u043f\u0443\u0441\u0442\u044b\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438. \u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u043c \u0435\u0433\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438. \u0412\u00a0\u044d\u0442\u043e\u043c \u043c\u0430\u0441\u0441\u0438\u0432\u0435 \u0431\u0443\u0434\u0443\u0442 \u043b\u0435\u0436\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0441\u00a0\u043f\u043e\u043b\u044f\u043c\u0438\u00a0<code>title<\/code>\u00a0\u0438\u00a0<code>img<\/code>, \u0432\u00a0\u043f\u0435\u0440\u0432\u043e\u043c \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u0440\u0442\u044b, \u0430\u00a0\u0432\u043e\u00a0\u0432\u0442\u043e\u0440\u043e\u043c\u00a0\u2014 \u043f\u0443\u0442\u044c \u0434\u043e\u00a0\u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043a\u0430\u0440\u0442\u044b.<\/p>\n<p>\u041c\u044b\u00a0\u0443\u0436\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u00a0\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u00a0<code>TarotCard<\/code>, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043c\u00a0\u0438\u0445:<\/p>\n<pre><code class=\"javascript\">export default class TarotCard { ... title = '';   img = ''; ...  \/**    *     * @param {*} data     * @param {number} index     * @param {number} amount     * @param {TarotController} controller     *\/   constructor(data, index, amount, controller) {     this.controller = controller;      this.title = data?.title;     this.img = data?.img;      this.fadeIn();     this.calculateProps(index, amount);     this.createElement();     this.addListeners();   } ... }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u00a0\u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0440\u0443\u0431\u0430\u0448\u043a\u0438 \u043a\u0430\u0440\u0442\u044b \u0438\u00a0\u0434\u043b\u044f \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code>&lt;template id=\"card\">   &lt;div class=\"card\">     &lt;div class=\"card__back\">&lt;\/div>     &lt;div class=\"card__front\">&lt;\/div>   &lt;\/div> &lt;\/template><\/code><\/pre>\n<p>\u0418 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0438\u043b\u0438:<\/p>\n<pre><code class=\"css\">.card {   min-width: 10rem;   aspect-ratio: 9\/16;   border-radius: 4px;   will-change: transform;   position: relative;   transform-style: preserve-3d; }  .card__back, .card__front {   position: absolute;   left: 0;   top: 0;   width: 100%;   height: 100%;   border-radius: 4px;   backface-visibility: hidden; }  .card__back {   background-image: url('.\/img\/back.jpg');   background-size: cover;   background-position: center;   background-repeat: no-repeat; }  .card__front {   transform: rotateY(-180deg) translateZ(1px);   background-size: cover;   background-position: center;   background-repeat: no-repeat; }<\/code><\/pre>\n<p>\u0421\u043a\u0430\u0447\u0430\u0435\u043c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0442\u0430\u0440\u043e \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438:<\/p>\n<pre><code class=\"css\">export default [   {     title: '\u0448\u0443\u0442',     img: '.\/img\/cards\/1.jpg',   },   {     title: '\u043c\u0430\u0433',     img: '.\/img\/cards\/2.jpg',   },   {     title: '\u0436\u0440\u0438\u0446\u0430',     img: '.\/img\/cards\/3.jpg',   },   {     title: '\u0438\u043c\u043f\u0435\u0440\u0430\u0442\u0440\u0438\u0446\u0430',     img: '.\/img\/cards\/4.jpg',   },   \/\/ \u0438 \u0442\u0434 ]<\/code><\/pre>\n<p>\u0412\u00a0\u043c\u0435\u0442\u043e\u0434\u0435, \u0433\u0434\u0435 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u0432\u00a0\u043a\u0430\u0440\u0442\u0443: <\/p>\n<pre><code class=\"javascript\">createElement() {     const clone = document.querySelector('#card').content.cloneNode(true);     this.element = clone.querySelector('.card');     this.controller.container.appendChild(this.element);      const cardFront = this.element.querySelector('.card__front');     cardFront.style.backgroundImage = `url(${this.img})`;   }<\/code><\/pre>\n<p>\u0421\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c:<\/p>\n<div class=\"embed_link\">\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;undefined&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>Vimeo<\/span><\/div>\n<p><a href=\"https:\/\/vimeo.com\/manage\/videos\/915155768\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed__caption-link\">vimeo.com<\/a><\/div>\n<\/div>\n<p><strong>\u041c\u043d\u0435 \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0435\u0449\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e \u043d\u0430\u00a0mousemove, \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0440\u0442\u0430 \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u043b\u0430 \u043d\u0430\u00a0\u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043c\u044b\u0448\u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430\u043c\u0438.\u00a0<\/strong>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 \u0432\u00a0\u043a\u043b\u0430\u0441\u0441\u0435\u00a0<code>Card<\/code>\u00a0\u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u043c\u044b\u0448\u0438 \u0438\u00a0\u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e\u00a0<code>mousePos<\/code>, \u043f\u043e\u00a0\u0434\u0435\u0444\u043e\u043b\u0442\u0443 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0443\u043b\u0435\u0432\u044b\u043c\u0438\u00a0<code>{x: 0, y: 0}<\/code>.<\/p>\n<p>\u0412\u00a0\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f mousemove \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">const rect = this.element.getBoundingClientRect(); this.mousePos.x = this.interpolation(e.clientX - rect.left, 0, rect.width, -1, 1); this.mousePos.y = this.interpolation(e.clientY - rect.top, 0, rect.height, -1, 1);<\/code><\/pre>\n<p>\u0422\u0443\u0442 \u043c\u044b\u00a0\u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u0438\u0440\u0443\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043c\u044b\u0448\u0438 \u0432\u00a0\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0435 \u043e\u0442 \u22121 \u0434\u043e\u00a01\u00a0\u0438\u00a0\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0432\u00a0\u043f\u043e\u043b\u0435\u00a0<code>mousePos<\/code>.<\/p>\n<p>\u0412\u00a0\u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434\u00a0<code>TarotCard.calculateTargetRotate<\/code>\u00a0\u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430 \u043f\u043e\u00a0\u0434\u0432\u0443\u043c \u043e\u0441\u044f\u043c, \u0435\u0441\u043b\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u00a0<code>isHovered<\/code>.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"javascript\">calculateTargetRotate() {   const output = { ...this.rotate };    if (this.isHovered &amp;&amp; !this.isRevealed) {     output.y = this.mousePos.x * 10;     output.x = -this.mousePos.y * 10;   }    if (this.isRevealed &amp;&amp; this.isHovered) {     output.y = this.mousePos.x * 10 + 180;     output.x = -this.mousePos.y * 10;   }    if (this.isRevealed &amp;&amp; !this.isHovered) {     output.y = this.rotate.y + 180;   }    if (this.isFadeIn || this.isFadeOut) {     output.y = 0;     output.x = this.isFadeIn ? 15 : -15;   }    return output; }<\/code><\/pre>\n<p><strong>\u041f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0431\u043e\u0447\u043d\u044b\u0445 \u0441\u0442\u0438\u043b\u0435\u0439 \u0434\u043b\u044f \u043a\u0440\u0430\u0441\u043e\u0442\u044b, \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u043d\u044b\u0439 \u0432\u0438\u0434.<\/strong><\/p>\n<p>\u0422\u0443\u0442 \u043d\u0435\u0442 \u0436\u0435\u0441\u0442\u043a\u043e\u0439 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 \u043a\u00a0\u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044e, \u0438\u00a0\u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u0442\u0443\u00a0\u0436\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u00a0\u043f\u0443\u0442\u0435\u043c WebGL.<\/p>\n<p>\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f\u00a0\u2014 \u043d\u0435\u00a0\u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b, \u0430\u00a0\u0441\u043a\u043e\u0440\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043d\u044f\u0442\u044c \u0441\u0435\u0431\u044f \u043d\u0430\u00a0\u043f\u0430\u0440\u0443 \u0447\u0430\u0441\u043e\u0432 \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0439 \u0438\u00a0\u043d\u0435\u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438.<\/p>\n<p><strong>\u041d\u0435 \u0441\u0442\u0435\u0441\u043d\u044f\u0439\u0442\u0435\u0441\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0440\u0430\u0431\u043e\u0442\u043a\u0438,\u00a0\u0432\u043e\u0442\u00a0<\/strong><a href=\"https:\/\/github.com\/Faeddur\/animated-tarot-wwzrds\" rel=\"noopener noreferrer nofollow\"><strong>\u0441\u0441\u044b\u043b\u043e\u0447\u043a\u0430 \u043d\u0430 \u0433\u0438\u0442\u0445\u0430\u0431<\/strong><\/a><strong>!<\/strong><\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/795383\/\"> https:\/\/habr.com\/ru\/articles\/795383\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412\u043c\u0435\u0441\u0442\u0435 \u0441\u00a0\u0414\u0430\u043d\u0438\u0438\u043b\u043e\u043c \u0421\u0430\u0440\u0430\u0431\u044c\u0435\u0432\u044b\u043c\u00a0(\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a We\u00a0Wizards) \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0438\u0441, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0437\u0430\u043a\u0440\u044b\u0442\u044b\u0445 \u043a\u0430\u0440\u0442 \u0442\u0430\u0440\u043e \u0441\u00a0\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u0441\u043a\u0440\u044b\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043a\u0430\u0440\u0442\u044b.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p><strong>\u0420\u0430\u0437\u0434\u0435\u043b\u0438\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430\u00a0\u0434\u0432\u0430 \u043a\u043b\u0430\u0441\u0441\u0430:<\/strong><\/p>\n<ul>\n<li>\n<p>\u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 (\u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0435\u0433\u043e\u00a0TarotController);<\/p>\n<\/li>\n<li>\n<p>\u043a\u043b\u0430\u0441\u0441 \u0435\u0434\u0438\u043d\u0438\u0447\u043d\u043e\u0439 \u043a\u0430\u0440\u0442\u044b (TarotCard).<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u043f\u043e\u043a\u0430\u0437 \u0438 \u0441\u043a\u0440\u044b\u0442\u0438\u0435 \u043a\u0430\u0440\u0442, \u0442\u0430\u043a \u0436\u0435 \u0432 \u043d\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u043a\u0440\u0443\u0442\u0438\u0442\u044c\u0441\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u0430\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>requestAnimationFrame<\/code>. \u0412 \u043a\u0430\u0436\u0434\u043e\u043c \u0446\u0438\u043a\u043b\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 update \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 <code>TarotCard<\/code>(\u043e\u0431 \u044d\u0442\u043e\u043c \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435).<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443, \u0433\u0434\u0435 \u043f\u043e\u043a\u0430 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0441 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c <code>type=\u201dmodule\u201d<\/code> \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u043e\u0432.<\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u0441 \u043a\u043b\u0430\u0441\u0441\u043e\u043c container, \u0432\u043d\u0443\u0442\u0440\u044c \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u043b\u043e\u0436\u0438\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442 c \u043a\u043b\u0430\u0441\u0441\u043e\u043c cards-container \u0434\u043b\u044f \u0432\u0441\u0442\u0432\u043a\u0438 \u0441\u0430\u043c\u0438\u0445 \u043a\u0430\u0440\u0442 \u0438 \u043a\u043d\u043e\u043f\u043a\u0443 \u0441 \u043a\u043b\u0430\u0441\u0441\u043e\u043c reset \u0434\u043b\u044f \u0441\u0431\u0440\u043e\u0441\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u044b\u0445 \u043a\u0430\u0440\u0442.<\/p>\n<p>\u0417\u0430\u0440\u0430\u043d\u0435\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0435\u043c\u043f\u043b\u0435\u0439\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 <code>TarotCard<\/code>:<\/p>\n<pre><code class=\"xml\">\/&lt;!DOCTYPE html> &lt;html lang=\"en\"> &lt;head>   &lt;meta charset=\"UTF-8\">   &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">   &lt;title>Animatied tarot&lt;\/title> &lt;\/head> &lt;body>   &lt;div class=\"container\">     &lt;div class=\"cards-container\">&lt;\/div>     &lt;button class=\"reset\">RESET&lt;\/button>   &lt;\/div>    &lt;template id=\"card\">     &lt;div class=\"card\">&lt;\/div>   &lt;\/template>    &lt;script type=\"module\" src=\".\/js\/index.js\">&lt;\/script> &lt;\/body> &lt;\/html><\/code><\/pre>\n<p>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u201c\u043d\u0430 \u043e\u0449\u0443\u043f\u044c\u201d \u043a\u043e\u0434 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u043f\u043e\u043a\u0430 \u0431\u0435\u0437 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u043b\u043e\u0433\u0438\u043a\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u044f, \u043d\u0435 \u0437\u0430\u043f\u0443\u0442\u0430\u0435\u043c\u0441\u044f.<\/p>\n<pre><code class=\"javascript\">import Card from \".\/TarotCard.js\"; import cardsData from '..\/data.js';  export default class TarotController {    \/**    * \u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u0440\u0435\u0437\u043c\u0435\u0442\u043a\u0438 \u043a\u0430\u0440\u0442    * @type {HTMLElement}    *\/   container;    \/**    * \u041c\u0430\u0441\u0441\u0438\u0432 \u0441 \u0442\u0435\u043a\u0443\u0449\u0438\u043c\u0438 \u043a\u0430\u0440\u0442\u0430\u043c\u0438    * @type {TarotCard[]}    *\/   cards = [];    constructor() {     this.container = document.querySelector('.cards-container');     this.setCards();     this.loop();   }    \/**    * \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u043a\u0430\u0440\u0442    * \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435    *    * @param {number} amount - \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u0430\u0440\u0442    *\/   async setCards(amount = 5) {     this.reset().then(() => {       const shuffledCards = this.getShuffledCards();       for (let i = 0; i &lt; amount; i ++) {         if (!shuffledCards[i]) {           return;         }         this.cards.push(new TarotCard(shuffledCards[i], i, amount, this));       }     });   }  \/**    * \u041c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043a\u0430\u0440\u0442    *\/   loop() {     this.cards.forEach(card => card.update());     requestAnimationFrame(this.loop.bind(this));   }    \/**    * \u0421\u043f\u0440\u044f\u0442\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043a\u0430\u0440\u0442\u044b \u0438 \u043e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440     * \u0441 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u043e\u0439    *\/   reset() {     return new Promise((resolve) => {       if (!this.cards.length) {         resolve(true);         return;       }        this.cards.forEach(card => card.fadeOut());        setTimeout(() => {         this.cards = [];         this.container.innerHTML = '';         resolve(true);       }, 800);     });   }    \/**    * \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u0448\u0430\u043d\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u043a\u0430\u0440\u0442\u0430\u043c\u0438    * @return {Object} \u041f\u0435\u0440\u0435\u043c\u0435\u0448\u0430\u043d\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u043a\u0430\u0440\u0442\u0430\u043c\u0438    *\/   getShuffledCards() {     return cardsData       .map(val => ({ val, sort: Math.random() }))       .sort((a, b) => a.sort > b.sort ? 1 : -1)       .map(({ val }) => val);   } }<\/code><\/pre>\n<p>\u0421\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u0437\u0430\u0434\u0430\u0442\u044c \u043d\u0430\u0431\u043e\u0440 \u043a\u0430\u0440\u0442 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>TarotController.setCards<\/code> \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u0435\u0442\u043e\u0434 \u044d\u0442\u043e\u0433\u043e \u0436\u0435 \u043a\u043b\u0430\u0441\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041c\u0435\u0442\u043e\u0434 <code>TarotController.reset<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0440\u043e\u043c\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0437\u043e\u043b\u0432\u0438\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443, \u0435\u0441\u043b\u0438 \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u043a\u0430\u0440\u0442\u0430\u043c\u0438 <code>TarotController.\u0441ards<\/code>  \u043f\u0443\u0441\u0442\u043e\u0439, \u0432 \u0438\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u043f\u0440\u044f\u0447\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u043a\u0430\u0440\u0442\u044b, \u0436\u0434\u0435\u043c \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0438 \u0447\u0438\u0441\u0442\u0438\u043c \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443 \u0438 \u043c\u0430\u0441\u0441\u0438\u0432 <code>TarotController.\u0441ards<\/code>.<\/p>\n<p>\u0412 \u043c\u0435\u0442\u043e\u0434\u0435 <code>TarotController.setCards<\/code> \u043f\u043e\u0441\u043b\u0435 \u0440\u0435\u0437\u043e\u043b\u0432\u0430 \u043f\u0440\u043e\u043c\u0438\u0441\u0430 <code>reset<\/code> \u043f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u043c\u044b \u043f\u0435\u0440\u0435\u043c\u0435\u0448\u0438\u0432\u0430\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u043a\u0430\u0440\u0442\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043d\u0430 2 \u0441\u0442\u0440\u043e\u043a\u0435 \u0444\u0430\u0439\u043b\u0430 (<code>import cardsData from '..\/data.js';<\/code>). \u0417\u0430\u0442\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 for \u0438\u0442\u0435\u0440\u0438\u0440\u0443\u0435\u043c\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437 \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 <code>TarotCard<\/code>, \u043a\u0443\u0434\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043a\u0430\u0440\u0442\u044b (\u043f\u043e\u043a\u0430 \u0431\u0435\u0437 \u0440\u0430\u0437\u043d\u0438\u0446\u044b, \u0447\u0442\u043e \u044d\u0442\u043e \u0431\u0443\u0434\u0443\u0442 \u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0435), \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0438\u043d\u0434\u0435\u043a\u0441 \u043a\u0430\u0440\u0442\u044b, \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b-\u0432\u043e \u043a\u0430\u0440\u0442 \u0438 \u0441\u0430\u043c \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u0447\u0442\u043e\u0431\u044b \u0443 \u043a\u0430\u0440\u0442\u044b \u0431\u044b\u043b \u043a \u043d\u0435\u043c\u0443 \u0434\u043e\u0441\u0442\u0443\u043f.<\/p>\n<p><strong>\u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0435\u043c \u043a \u0441\u0430\u043c\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u043c\u0443 \u2014 \u043f\u0438\u0448\u0435\u043c \u043a\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430 TarotCard \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0432\u0441\u0435 \u0437\u0430\u0434\u0443\u043c\u0430\u043d\u043d\u044b\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0430 \u0438\u043c\u0435\u043d\u043d\u043e:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438 (\u0432\u044b\u043f\u043b\u044b\u0432\u0430\u043d\u0438\u0435 \u0438\u0437 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043a\u0438);<\/p>\n<\/li>\n<li>\n<p>\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u0441\u043a\u0440\u044b\u0442\u0438\u044f \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438 (\u0441\u043a\u0440\u044b\u0442\u0438\u0435 \u043a\u0430\u0440\u0442\u044b \u0437\u0430 \u043d\u0438\u0436\u043d\u044e\u044e \u0433\u0440\u0430\u043d\u0438\u0446\u0443 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b);<\/p>\n<\/li>\n<li>\n<p>\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u043f\u043e \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u044e \u043d\u0430 \u043a\u0430\u0440\u0442\u0443 (\u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043f\u043e \u043e\u0441\u0438 Z, \u0431\u043b\u0438\u0436\u0435 \u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e);<\/p>\n<\/li>\n<li>\n<p>\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f (\u201d\u0440\u0430\u0437\u0432\u043e\u0440\u043e\u0442\u0430\u201d) \u043a\u0430\u0440\u0442\u044b \u043f\u043e \u043a\u043b\u0438\u043a\u0443.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u043d\u0435\u0440\u0446\u0438\u0438:<\/p>\n<p><code>position += (targetPosition - position) * coeff;<\/code>.<\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f position \u043a\u0430\u0436\u0434\u044b\u0439 \u0446\u0438\u043a\u043b \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0430\u0442\u044c\u0441\u044f \u043a \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043d\u0430 \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u0440\u0430\u0432\u043d\u043e\u0435 \u0440\u0430\u0437\u043d\u0438\u0446\u0435 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u043d\u043e\u0439 \u043d\u0430 \u043a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438.<\/p>\n<p>\u041f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 <code>TarotCard<\/code>. \u0417\u0430\u043e\u0447\u043d\u043e \u043c\u044b \u0443\u0436\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 \u043a\u0430\u043a\u0438\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b:<\/p>\n<pre><code class=\"javascript\">import TarotController from \".\/TarotController.js\";  export default class TarotCard {    \/**    * @type {TarotController}    *\/   controller;      \/**    *     * @param {*} data     * @param {number} index - \u0418\u043d\u0434\u0435\u043a\u0441 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043a\u0430\u0440\u0442\u044b    * @param {number} amount - \u041e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b-\u0432\u043e \u043a\u0430\u0440\u0442    * @param {TarotController} controller     *\/   constructor(data, index, amount, controller) {     this.controller = controller;   }    fadeOut() {}    fadeIn() {}    update() {} }<\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>fadeOut<\/code> \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u043a\u0430\u0440\u0442\u0443 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>reset<\/code> \u0443 \u043a\u043b\u0430\u0441\u0441\u0430 <code>TarotController<\/code>. \u0417\u0430\u043e\u0434\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>fadeIn<\/code> \u0434\u043b\u044f \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u0430\u0440\u0442\u044b.<\/p>\n<p>\u041c\u0435\u0442\u043e\u0434 update \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0439 \u0446\u0438\u043a\u043b \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0432 <code>TarotController<\/code>, \u0442\u0443\u0442 \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0438 \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u044b \u043a\u0430\u0440\u0442\u044b.<\/p>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043a\u0430\u043a\u0438\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0443 \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u0430\u0440\u0442\u044b \u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u043b\u044f \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 TarotCard:<\/p>\n<pre><code class=\"javascript\">export default class TarotCard {  \/**    * @type {TarotController}    *\/   controller;  isFadeIn = false; isFadeOut = false; isHovered = false; isRevealed = false;    ... }<\/code><\/pre>\n<p>\u0421\u0440\u0430\u0437\u0443 \u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0432 \u043d\u0430\u0448\u0438\u0445 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u0430\u0445:<\/p>\n<pre><code class=\"javascript\">fadeOut() {   this.isFadeIn = false;   this.isFadeOut = true; }  fadeIn() {   this.isFadeIn = true;   this.isFadeOut = false;    }<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0441\u0434\u0435\u043b\u0430\u0442\u044c HTML-\u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u0447\u0442\u043e\u0431\u044b \u0443\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u00a0TarotCard.createElement, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u00a0\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435. \u0412\u00a0\u043d\u0435\u043c \u043c\u044b\u00a0\u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043d\u0430\u0448 template\u00a0#card, \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u0438\u00a0\u0432\u0441\u0442\u0430\u0432\u0438\u043c \u0432\u00a0\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u043f\u043e\u043a\u0430 \u0431\u0435\u0437 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"javascript\">createElement() {     const clone = document.querySelector('#card').content.cloneNode(true);     this.element = clone.querySelector('.card');     this.controller.container.appendChild(this.element); \/**      * TODO: \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u043c\u0438      *\/   }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 <code>TarotCard<\/code> \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430.<\/p>\n<p>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0441\u0442\u0438\u043b\u0438 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f:<\/p>\n<pre><code class=\"css\">* {   margin: 0;   padding: 0;   box-sizing: border-box; }  .cards-container {   width: 100%;   height: 100vh;   display: flex;   justify-content: center;   align-items: center;   gap: 2rem;   perspective: 1000px;   overflow: hidden; }  .card {   min-width: 10rem;   aspect-ratio: 9\/16;   background-color: red;   border-radius: 4px;   will-change: transform;   position: relative; }  .reset {   z-index: 2;   cursor: pointer;   position: absolute;   left: 50%;   bottom: 2rem;   transform: translateX(-50%);   padding: 1rem 2rem; }<\/code><\/pre>\n<p>\u041f\u043e\u043a\u0430 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e, \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 <code>TarotController<\/code>. \u0421\u0440\u0430\u0437\u0443 \u0436\u0435 \u043f\u043e\u0432\u0435\u0441\u0438\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u2014 click-\u043a\u043d\u043e\u043f\u043a\u0443:<\/p>\n<pre><code class=\"javascript\">import TarotController from \".\/modules\/TarotController.js\";  const initTarot = () => {      const tarot = new TarotController();   const btn = document.querySelector('.reset');    btn.addEventListener('click', () => {     tarot.setCards();   }); };  initTarot();<\/code><\/pre>\n<p>\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p><strong>\u041e\u0442\u043b\u0438\u0447\u043d\u043e! \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0439.<\/strong><\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c, \u043a\u0430\u043a\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0431\u0443\u0434\u0435\u043c \u0430\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041f\u043e \u0437\u0430\u0434\u0443\u043c\u043a\u0435  \u043a\u0430\u0440\u0442\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f \u0432 \u0442\u0440\u0435\u0445 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u0445 \u0438 \u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u0432\u043e\u043a\u0440\u0443\u0433 \u0434\u0432\u0443\u0445 \u043e\u0441\u0435\u0439: &#8212; X \u0438 Y. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c translate3d \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0438 rotateX \u0438 rotateY \u0434\u043b\u044f \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u043e\u0432.<\/p>\n<p>\u041e\u0431\u043e\u0437\u043d\u0430\u0447\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u043b\u044f:<\/p>\n<ul>\n<li>\n<p>\u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0443\u044e (\u0434\u0435\u0444\u043e\u043b\u0442\u043d\u0443\u044e) \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043a\u0430\u043a <code>pos = {x: 0, y: 0, z: 0}<\/code><\/p>\n<\/li>\n<li>\n<p>\u0446\u0435\u043b\u0435\u0432\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c <code>targetPos = {x: 0, y: 0, z: 0}<\/code><\/p>\n<\/li>\n<li>\n<p>\u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043a\u0430\u043a <code>rotate = {x: 0, y: 0}<\/code><\/p>\n<\/li>\n<li>\n<p>\u0446\u0435\u043b\u0435\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c <code>targetRotate = {x: 0, y: 0, z: 0}<\/code><\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"javascript\">rotate = {   x: 0,    y: 0, };  pos = {   x: 0,   y: 0,   z: 0, };  targetRotate = {   x: 0,   y: 0, };  targetPos = {   x: 0,   y: 0,   z: 0, };<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0440\u0430\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442\u00a0\u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u043a\u0430\u0440\u0442\u044b \u0438\u00a0\u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043a\u0430\u0440\u0442. \u041f\u043e\u00a0\u0437\u0430\u0434\u0443\u043c\u043a\u0435 \u043a\u0430\u0440\u0442\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u0443\u043a\u0440\u0443\u0433\u043e\u043c, \u0430\u00a0\u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u043a\u0440\u0430\u0439\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430 \u043f\u043e\u00a0\u043e\u0441\u0438\u00a0Y \u0438\u00a0\u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043f\u043e\u00a0\u043e\u0441\u0438\u00a0Z.<\/p>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u0443\u0433\u043e\u043b \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u043e\u0442\u00a030\u00b0\u00a0\u0434\u043e \u221230\u00b0, \u0430\u00a0\u043f\u043e\u0437\u0438\u0446\u0438\u044f \u043f\u043e\u00a0\u043e\u0441\u0438\u00a0Z \u043e\u0442\u00a06\u00a0\u0434\u043e\u00a00\u00a0\u0438\u00a0\u043e\u0431\u0440\u0430\u0442\u043d\u043e.<\/p>\n<p>\u0422\u0443\u0442 \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043b\u0438\u043d\u0435\u0439\u043d\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u0438, \u0432\u044b\u0434\u0435\u043b\u0438\u043c \u0435\u0435\u00a0\u0432\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">interpolation(value, min, max, newMin, newMax) { let newValue = ( (value-min) \/ (max-min) ) * (newMax-newMin) + newMin; return newValue; }<\/code><\/pre>\n<p>\u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 \u0447\u0438\u0441\u043b\u043e, \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u043e\u0435 \u0432 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0435 \u043e\u0442 min \u0434\u043e max, \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0435 \u043e\u0442 <code>newMin<\/code> \u0434\u043e <code>newMax<\/code>. <\/p>\n<p>\u0420\u0430\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u043a\u0430\u0440\u0442\u044b \u0438 \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b-\u0432\u0430 \u043a\u0430\u0440\u0442, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0442 -1 \u0434\u043e 1.<\/p>\n<p>\u0418\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c index \u043a\u0430\u0440\u0442\u044b \u043c\u0435\u0436\u0434\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 0 \u0438 \u043a\u043e\u043b-\u0432\u043e \u043a\u0430\u0440\u0442 &#8212; 1 (\u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 index \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430). \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0438\u043c \u043a\u0430\u043a <code>basicCoeff<\/code> :<\/p>\n<pre><code class=\"javascript\">const basicCoeff = interpolation(index, 0, amount -1, -1, 1);<\/code><\/pre>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0435\u0441\u043b\u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0443\u0433\u043e\u043b \u043e\u0442 30<strong>\u00b0<\/strong> \u0434\u043e -30<strong>\u00b0,<\/strong> \u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 (\u043e\u0442 -1 \u0434\u043e 1) \u0443\u043c\u043d\u043e\u0436\u0438\u043c \u043d\u0430 -30, \u0430 \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u043c\u043d\u043e\u0436\u0438\u043c \u043d\u0430 6, \u043f\u043e\u043b\u0443\u0447\u0438\u0432 \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043e\u0442 -8 \u0434\u043e 8 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043c\u043e\u0434\u0443\u043b\u044c \u044d\u0442\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u043a\u0430\u0440\u0442\u044b \u043f\u043e\u043b\u0443\u043a\u0440\u0443\u0433\u043e\u043c, \u0432 \u044d\u0442\u043e\u043c \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043a\u043e\u0441\u0438\u043d\u0443\u0441\u0430:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u043e\u0442\u0440\u0435\u0437\u043e\u043a \u043e\u0442 -PI\/2 \u0434\u043e\u00a0PI\/2. \u0418\u00a0\u0442\u0430\u043a \u043a\u0430\u043a \u0443\u00a0\u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u043a\u043e\u0435\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f (\u043e\u0442 \u22121 \u0434\u043e\u00a01), \u0442\u043e\u00a0\u043a\u043e\u0441\u0438\u043d\u0443\u0441 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043a\u0430\u0442\u044c \u043e\u0442\u00a0Math.PI *<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-368887","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/368887","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=368887"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/368887\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=368887"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=368887"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=368887"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}