{"id":300218,"date":"2020-03-16T15:01:08","date_gmt":"2020-03-16T15:01:08","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=300218"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=300218","title":{"rendered":"\u041a\u0430\u043a Smartcalls \u0441\u0442\u0430\u043b Voximplant Kit\u2019\u043e\u043c \u2013 \u0440\u0435\u0431\u0440\u0435\u043d\u0434\u0438\u043d\u0433 \u0438 \u043a\u0438\u043b\u043b\u0435\u0440-\u0444\u0438\u0447\u0438"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/company\/Voximplant\/blog\/492232\/\"><a href=\"https:\/\/habr.com\/ru\/company\/Voximplant\/blog\/492232\/\"><\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/by\/c2\/ih\/byc2ihl70ggcz-ftm-a4ziskyvo.png\"><\/div>\n<p><\/a><br \/>  \u041c\u044b \u0434\u043e\u043b\u0433\u043e \u0433\u043e\u0442\u043e\u0432\u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 Smartcalls \u2013 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u043b\u044f \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0437\u0432\u043e\u043d\u043a\u043e\u0432 \u2013 \u0438 \u0432\u043e\u0442 \u043e\u043d\u043e \u0441\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u043c \u043f\u0440\u043e UI\/UX-\u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043b\u0435\u0437\u0435\u043c \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442 \u0434\u0435\u043c\u043e-\u0440\u0435\u0436\u0438\u043c\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u0438\u0440\u0443\u0447\u0430\u043b\u0438 JointJS.<a name=\"habracut\"><\/a><\/p>\n<h2>\u0410 \u0447\u0442\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u043b\u043e\u0441\u044c?<\/h2>\n<p>  \u0418\u0437 \u0441\u0430\u043c\u043e\u0433\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e\u0433\u043e \u2013 \u043d\u043e\u0432\u043e\u0435 \u0438\u043c\u044f \u0438 \u0443\u0440\u043b, \u0430 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e Voximplant Kit \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043f\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0441\u0441\u044b\u043b\u043a\u0435 <a href=\"https:\/\/voximplant.com\/kit\/\">voximplant.com\/kit<\/a>. \u041c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0438 <a href=\"https:\/\/kit.voximplant.com\/registration\">\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438<\/a>, \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u043d\u0430 \u0442\u0430\u043a\u0430\u044f:<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/cl\/jh\/vc\/cljhvcpw84_miyo3xcr8tsamgwo.png\" alt=\"image\"><\/div>\n<p>  \u0425\u043e\u0442\u044f \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f \u043e\u0441\u0442\u0430\u043b\u0430\u0441\u044c \u043f\u0440\u0435\u0436\u043d\u0435\u0439, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0438\u043b\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430, \u0441\u0442\u0430\u0432 \u0431\u043e\u043b\u0435\u0435 user-friendly. \u0412\u0435\u0440\u0445\u043d\u0435\u0435 \u043c\u0435\u043d\u044e \u043f\u0435\u0440\u0435\u043a\u043e\u0447\u0435\u0432\u0430\u043b\u043e \u043d\u0430\u043b\u0435\u0432\u043e, \u0447\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b\u043e \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e \u043f\u043e \u0431\u043b\u043e\u043a\u0430\u043c \u0431\u043e\u043b\u0435\u0435 \u043b\u043e\u0433\u0438\u0447\u043d\u043e\u0439 \u0438 \u0443\u0434\u043e\u0431\u043d\u043e\u0439.<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/zr\/9y\/hf\/zr9yhfrpoz4qjawojzkqgdl5kpa.png\" alt=\"image\"><\/div>\n<p>  \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u0438 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0438 \u0430\u0443\u0434\u0438\u043e\u0437\u0430\u043f\u0438\u0441\u0435\u0439, \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u043d\u043e\u043c\u0435\u0440\u0430\u043c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438 \u043a\u0430\u043c\u043f\u0430\u043d\u0438\u0439 \u0441 \u043a\u0440\u0430\u0442\u043a\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u043d\u0438\u0445, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043d\u043e\u0432\u044b\u0435 \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u2013 \u0441\u0440\u0435\u0434\u043d\u044e\u044e \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0433\u043e \u0437\u0432\u043e\u043d\u043a\u0430 \u0438 \u043e\u0431\u0449\u0443\u044e \u043f\u043e\u0442\u0440\u0430\u0447\u0435\u043d\u043d\u0443\u044e \u0441\u0443\u043c\u043c\u0443.<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/kg\/yf\/12\/kgyf12bkj5jjx_cffukvfnqnk7g.png\" alt=\"image\"><\/div>\n<p>  \u0427\u0442\u043e \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0439: user-friendly \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043e\u0431\u0440\u0430\u043b\u0441\u044f \u0438 \u0434\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043f\u043e\u0447\u0442\u044b, \u0430 \u043d\u0430 \u0432\u043a\u043b\u0430\u0434\u043a\u0430\u0445 Dialogflow, SIP, Global Variables \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043f\u043e\u0438\u0441\u043a \u0438 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 \u043f\u043e ID \u0438 host&#8217;\u0430\u043c.<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/sr\/wm\/dj\/srwmdjgvejupi9urypqn1iyglzk.png\" alt=\"image\"><\/div>\n<p>   \u0412 \u043e\u0431\u0449\u0435\u043c, \u043c\u043d\u043e\u0433\u043e \u0432\u0441\u0435\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u0438 \u043a\u0440\u0443\u0442\u043e\u0433\u043e! \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c <a href=\"https:\/\/voximplant.ru\/blog\/please-meet-brand-new-version-of-smartcalls-voximplant-kit\">\u0432 \u043d\u0430\u0448\u0435\u043c \u0431\u043b\u043e\u0433\u0435<\/a>.<\/p>\n<h2>\u041d\u043e \u0441\u0430\u043c\u043e\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u2013 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440<\/h2>\n<p>  \u0414\u0435\u043c\u043e-\u0440\u0435\u0436\u0438\u043c (\u0441\u043f\u043e\u0439\u043b\u0435\u0440: \u044d\u0442\u043e \u0438 \u0435\u0441\u0442\u044c \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u043a\u0438\u043b\u043b\u0435\u0440-\u0444\u0438\u0447\u0430).<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/7m\/po\/du\/7mpoduas-ap0m6lbi-o12g9eyd0.gif\"><\/div>\n<p>  \u0420\u0435\u0430\u043b-\u0442\u0430\u0439\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f \u0441 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u043e\u0439 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u043e\u0432, \u0430 \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u2013 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0437\u0432\u043e\u043d\u043a\u0430 (Flow \u0438 Log), \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0447\u0435\u043c\u0443 \u043e\u0442\u043b\u0430\u0434\u043a\u0430 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0441\u0442\u0430\u043b\u0430 \u0435\u0449\u0435 \u043f\u0440\u043e\u0449\u0435 \u0438 \u0431\u044b\u0441\u0442\u0440\u0435\u0435.<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/_i\/vl\/0a\/_ivl0ayzlmrojpumqdf_knc99ie.png\" alt=\"image\"><\/div>\n<p>  \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0438\u0434\u0435\u043e \u0440\u0430\u0431\u043e\u0442\u044b \u0434\u0435\u043c\u043e-\u0440\u0435\u0436\u0438\u043c\u0430 \u043c\u043e\u0436\u043d\u043e <a href=\"https:\/\/www.youtube.com\/watch?v=hhYVauBwb0A\">\u0437\u0434\u0435\u0441\u044c<\/a> \u0438\u043b\u0438 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0441\u043b\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043d\u0430 <a href=\"https:\/\/kit.voximplant.com\/registration\">Voximplant Kit<\/a>.<\/p>\n<p>  \u0410 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u0441\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e, \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u043c \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435. \u041d\u043e\u0432\u044b\u0435 \u0444\u0438\u0447\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430:<\/p>\n<ul>\n<li>undo\/redo (1 \u043d\u0430 \u0440\u0438\u0441\u0443\u043d\u043a\u0435 \u043d\u0438\u0436\u0435);<\/li>\n<li>\u0433\u043e\u0440\u044f\u0447\u0438\u0435 \u043a\u043b\u0430\u0432\u0438\u0448\u0438 (2);<\/li>\n<li>\u0432\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0449\u0435\u0435 \u043c\u0435\u043d\u044e, \u0433\u0434\u0435 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u0431\u043b\u043e\u043a\u0438 \u0438 \u043b\u0438\u043d\u043a\u0438 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 \u043e\u0434\u043d\u0438\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c, \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043c\u0430\u0441\u0448\u0442\u0430\u0431, \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 miniMap, \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u043d\u0430 \u0432\u0435\u0441\u044c \u044d\u043a\u0440\u0430\u043d, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u0430\u0441\u0448\u0430\u0440\u0438\u0442\u044c \u0435\u0433\u043e (\u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u043a png) (3);<\/li>\n<li>\u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435 \u043c\u0435\u043d\u044e \u043f\u043e \u043f\u0440\u0430\u0432\u043e\u043c\u0443 \u043a\u043b\u0438\u043a\u0443 \u043c\u044b\u0448\u0438;<\/li>\n<li>\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u043b\u043e\u043a\u043e\u0432 \u2013 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f, \u043d\u043e \u0438 \u043c\u0435\u0436\u0434\u0443 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u043c\u0438 \u0438 \u0434\u0430\u0436\u0435(!) \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430\u043c\u0438;<\/li>\n<li>lock\/unlock \u0431\u043b\u043e\u043a\u0430 \u2014 \u0437\u0430\u043b\u043e\u0447\u0435\u043d\u043d\u044b\u0439 \u0431\u043b\u043e\u043a \u0434\u0432\u0438\u0433\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e, \u043d\u043e \u041d\u0415\u041b\u042c\u0417\u042f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u043e \u0438\u0437\u0431\u0435\u0436\u0430\u043d\u0438\u0435 \u043d\u0435\u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439;<\/li>\n<li>\u0441\u043c\u0435\u043d\u0430 \u0446\u0432\u0435\u0442\u043e\u0432 \u2013 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u00ab\u0440\u043e\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445\u00bb \u0431\u043b\u043e\u043a\u043e\u0432<\/li>\n<li>\u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0438\u043c\u0435\u043d\u0430\u043c \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0431\u043b\u043e\u043a\u043e\u0432;<\/li>\n<li>\u0431\u043b\u043e\u043a \u00ab\u0418\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u043c\u0435\u043d\u044e\u00bb \u2013 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043c\u0435\u043d\u044f\u0442\u044c \u043f\u043e\u0440\u0442\u044b (\u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u043e\u0442\u0432\u0435\u0442\u043e\u0432) \u043c\u0435\u0441\u0442\u0430\u043c\u0438 \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0435\u043c.<\/li>\n<\/ul>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/wp\/fw\/u4\/wpfwu4ddvz--h5gd0yqm9ipcfzs.png\" alt=\"image\"><\/div>\n<p>  <\/p>\n<h2>\u0420\u0430\u0441\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u0440\u0442\u044b<\/h2>\n<p>  \u041f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f, \u043a\u0430\u043a \u0432 \u043a\u043e\u0434\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u0431\u043b\u043e\u043a\u043e\u0432.<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/zo\/qo\/cz\/zoqoczrubc5rvxijm-cshjukoq0.png\"><\/div>\n<p>  \u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043c\u0435\u0442\u043e\u0434 \u043d\u0430\u0448\u0435\u0433\u043e HTTP API \u2013 StartScenarios \u2013 \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439. \u041e\u0431\u043b\u0430\u043a\u043e Voximplant \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f \u0438 \u043e\u0442\u0434\u0430\u0435\u0442 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0443 media_access_url. \u0421 \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0434\u0435\u0440\u0433\u0430\u0435\u0442 media_access_url \u043a\u0430\u0436\u0434\u0443\u044e \u0441\u0435\u043a\u0443\u043d\u0434\u0443, \u043f\u043e\u043b\u0443\u0447\u0430\u044f \u0432 \u043e\u0442\u0432\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u00ab\u043f\u0443\u0442\u0435\u0448\u0435\u0441\u0442\u0432\u0443\u0435\u0442\u00bb \u043f\u043e \u0431\u043b\u043e\u043a\u0430\u043c \u2013 \u043e\u043f\u0438\u0440\u0430\u044f\u0441\u044c \u043d\u0430 \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435, \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043f\u043e\u0434\u0441\u0432\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043d\u0443\u0436\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438 \u0438 \u0430\u043d\u0438\u043c\u0438\u0440\u0443\u0435\u0442 \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438.<\/p>\n<p>  \u0418\u0441\u0442\u043e\u0440\u0438\u044f \u043f\u0443\u0442\u0435\u0448\u0435\u0441\u0442\u0432\u0438\u0439 (History) \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 JSON \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438:<\/p>\n<ul>\n<li>timestamp;<\/li>\n<li>idSource \u2013 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u0431\u043b\u043e\u043a;<\/li>\n<li>idTarget \u2013 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0431\u043b\u043e\u043a;<\/li>\n<li>port \u2013 \u043f\u043e\u0440\u0442 (\u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0445\u043e\u0434\u043e\u0432 \u0438\u0437 1 \u0431\u043b\u043e\u043a\u0430).<\/li>\n<\/ul>\n<p>  <\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/wl\/qt\/ht\/wlqthtjgn0l2bnwfoqophwregpy.png\" alt=\"image\"><\/div>\n<p>  \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u044d\u0442\u0438\u0445 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0438 \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442, \u0438\u0437 \u043a\u0430\u043a\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430 \u0432 \u043a\u0430\u043a\u043e\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041a\u0430\u043a \u043e\u043d \u044d\u0442\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442? \u041a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 (\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u0431\u043b\u043e\u043a), \u0435\u043c\u0443 \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f id, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u043a\u0430\u043a idSource \/ idTarget.<\/p>\n<p>  \u0427\u0442\u043e\u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <a href=\"https:\/\/resources.jointjs.com\/demos\/pn\">JointJS<\/a>, \u043d\u043e \u043d\u0435 \u043e\u0431\u043e\u0448\u043b\u043e\u0441\u044c \u0438 \u0431\u0435\u0437 \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430.<\/p>\n<p>  \u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 selectBlock(), \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c: \u043c\u044b \u0438\u0434\u0435\u043c \u043f\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0443 \u0438\u0441\u0442\u043e\u0440\u0438\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0439 (idSource, idTarget) \u0438 \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0443\u044e \u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0438, \u0438\u0449\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438:<\/p>\n<pre><code class=\"javascript\">const link = this.editor.getTestLink(sourceCell, portId);<\/code><\/pre>\n<p>  \u0415\u0441\u043b\u0438 \u0441\u0441\u044b\u043b\u043a\u0430 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 \u0435\u0441\u0442\u044c, \u0442\u043e \u0430\u043d\u0438\u043c\u0438\u0440\u0443\u0435\u043c \u0431\u0435\u0433\u0430\u044e\u0449\u0438\u0439 \u043f\u043e \u043b\u0438\u043d\u0438\u0438 \u0441\u0432\u044f\u0437\u0438 \u0448\u0430\u0440\u0438\u043a:  <\/p>\n<pre><code class=\"javascript\">if (link) this.setLinkAnimation(link);<\/code><\/pre>\n<p>  \u041c\u0435\u0442\u043e\u0434 selectBlock() \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f this.testHistory. \u0422\u0430\u043a \u043a\u0430\u043a \u0432 this.testHistory \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u0438\u043b\u0435\u0442\u0435\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u043e\u0432, \u043c\u044b \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c selectBlock \u0440\u0430\u0437 \u0432 700 \u043c\u0441 (\u044d\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u0437\u0430\u0442\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c\u043e\u0435 \u043d\u0430 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u0431\u043b\u043e\u043a\u0430 \u043a \u0431\u043b\u043e\u043a\u0443):<\/p>\n<pre><code class=\"javascript\">setTimeout(this.selectBlock, 700);<\/code><\/pre>\n<p>  \u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043c\u0435\u0442\u043e\u0434\u044b selectTestBlock \u0438 getTestLink, \u0441\u0442\u0440\u043e\u043a\u0438 7 \u0438 10 \u2013 \u0441\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u043c \u043f\u0440\u043e \u043d\u0438\u0445 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e:<\/p>\n<div class=\"oembed\"><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/5ffed5b2bbb82d4a3eff6df3f153a1ed.js\"><\/script><\/div>\n<h3>\u0420\u0438\u0441\u0443\u0435\u043c \u0441\u0432\u044f\u0437\u044c<\/h3>\n<p>  \u041c\u0435\u0442\u043e\u0434 getTestLink() \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0432\u044f\u0437\u044c \u043c\u0435\u0436\u0434\u0443 \u0431\u043b\u043e\u043a\u0430\u043c\u0438 \u2013 \u043e\u043d \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 getConnectedLinks(), \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 JointJS, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 \u0431\u043b\u043e\u043a \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043c\u0430\u0441\u0441\u0438\u0432 \u043b\u0438\u043d\u043a\u043e\u0432. \u0412 \u043d\u0430\u0448\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u044b \u0438\u0449\u0435\u043c \u0432 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u043c \u043c\u0430\u0441\u0441\u0438\u0432\u0435 \u043b\u0438\u043d\u043a \u0441 \u043f\u043e\u0440\u0442\u043e\u043c, \u0433\u0434\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e source \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 portId:<\/p>\n<pre><code class=\"javascript\">link = this.graph.getConnectedLinks(cell, {outbound : true}).find(item =&gt; {      return item.get('source').port === portId;<\/code><\/pre>\n<p>  \u0417\u0430\u0442\u0435\u043c, \u0435\u0441\u043b\u0438 \u043b\u0438\u043d\u043a \u0435\u0441\u0442\u044c, \u0442\u043e \u043f\u043e\u0434\u0441\u0432\u0435\u0447\u0438\u0432\u0430\u0435\u043c \u0435\u0433\u043e:<\/p>\n<pre><code class=\"javascript\">return link ? (link.toFront() &amp;&amp; link) : null;<\/code><\/pre>\n<p>  \u041a\u043e\u0434 \u043c\u0435\u0442\u043e\u0434\u0430:<\/p>\n<pre><code class=\"javascript\">getTestLink(sourceCell: Cell, portId: string): Link {   let link = null;   if (sourceCell &amp;&amp; sourceCell.id) {     let cell = null;     if (sourceCell.type === 'ScenarioStart' || sourceCell.type === 'IncomingStart') {       cell = this.getStartCell()     } else {       cell = this.graph.getCell(sourceCell.id);     }     link = this.graph.getConnectedLinks(cell, {outbound : true}).find(item =&gt; {       return item.get('source').port === portId;     });   }   return link ? (link.toFront() &amp;&amp; link) : null; }  <\/code><\/pre>\n<p>  \u0410\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u0431\u0435\u0433\u0430\u044e\u0449\u0435\u0433\u043e \u0448\u0430\u0440\u0438\u043a\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 JointJS (<a href=\"https:\/\/resources.jointjs.com\/demos\/pn\">\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0434\u0435\u043c\u043e<\/a>).<\/p>\n<h3>\u041f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u043c\u0441\u044f \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0431\u043b\u043e\u043a<\/h3>\n<p>  \u041c\u0435\u0442\u043e\u0434 selectTestBlock() \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c, \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0431\u043b\u043e\u043a \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0445\u043e\u043b\u0441\u0442 \u043a \u043d\u0435\u043c\u0443. \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0446\u0435\u043d\u0442\u0440\u0430 \u0431\u043b\u043e\u043a\u0430:<\/p>\n<pre><code class=\"javascript\">const center = cell.getBBox().center();<\/code><\/pre>\n<p>  \u0417\u0430\u0442\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c setTestCell() \u0434\u043b\u044f \u043e\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u043d\u0438\u044f \u0431\u043b\u043e\u043a\u0430:<\/p>\n<pre><code class=\"javascript\">editor.tester.setTestCell(cell);<\/code><\/pre>\n<p>  \u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u0437\u0443\u043c\u0438\u043c\u0441\u044f \u043a \u0435\u0433\u043e \u0446\u0435\u043d\u0442\u0440\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 zoomToCell() (\u043e\u043d\u0430 \u0441\u0430\u043c\u0430\u044f \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f, \u043d\u043e \u043e \u043d\u0435\u0439 \u0432 \u043a\u043e\u043d\u0446\u0435):<\/p>\n<pre><code class=\"javascript\">editor.paperController.zoomToCell(center, 1, false);<\/code><\/pre>\n<p>  \u041a\u043e\u0434 \u043c\u0435\u0442\u043e\u0434\u0430:<\/p>\n<pre><code class=\"javascript\">selectTestBlock(id: string): Cell {  const cell = (id === 'ScenarioStart') ? editor.tester.getStartCell() : editor.graph.getCell(id);  if (cell) {    const center = cell.getBBox().center();    editor.tester.setTestCell(cell);    editor.paperController.zoomToCell(center, 1, false);  }  return cell; }<\/code><\/pre>\n<p>  \u041c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043e\u043a\u0440\u0430\u0448\u0438\u0432\u0430\u043d\u0438\u044f: \u043d\u0430\u0445\u043e\u0434\u0438\u043c SVG-\u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u0431\u043b\u043e\u043a\u0430 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c CSS-\u043a\u043b\u0430\u0441\u0441 .is-tested, \u0447\u0442\u043e\u0431\u044b \u0431\u043b\u043e\u043a \u0441\u0442\u0430\u043b \u0446\u0432\u0435\u0442\u043d\u044b\u043c:<\/p>\n<pre><code class=\"javascript\">setTestCell(cell: Cell): void {  const view = cell.findView(this.paper);  if (view) view.el.classList.add('is-tested'); }<\/code><\/pre>\n<p>  <\/p>\n<h3>\u041f\u043b\u0430\u0432\u043d\u044b\u0439 \u0437\u0443\u043c<\/h3>\n<p>  \u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446 zoomToCell()! \u0423 JointJS \u0435\u0441\u0442\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0445\u043e\u043b\u0441\u0442\u0430 \u043f\u043e \u043e\u0441\u044f\u043c X \u0438 Y, \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0445\u043e\u0442\u0435\u043b\u0438 \u0432\u0437\u044f\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u0435\u0433\u043e. \u041e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 transform \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 SVG-\u0442\u0435\u0433\u0430, \u043e\u043d \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u043b\u0430\u0432\u043d\u0443\u044e \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 Firefox + \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e CPU. <\/p>\n<p>  \u041c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0445\u0430\u043a \u2013 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u0441\u0432\u043e\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e zoomToCell(), \u043a\u043e\u0442\u043e\u0440\u0430\u044f, \u043f\u043e \u0441\u0443\u0442\u0438, \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u043d\u043e \u043f\u0440\u043e\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u0442 transform \u043a\u0430\u043a \u0438\u043d\u043b\u0430\u0439\u043d\u043e\u0432\u044b\u0439 CSS, \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u0440\u0435\u043d\u0434\u0435\u0440 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e GPU (\u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043a \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f WebGL). \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043a\u0440\u043e\u0441\u0441\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>  \u041d\u0430\u0448\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u0442 \u0445\u043e\u043b\u0441\u0442 \u043f\u043e X Y, \u043d\u043e \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 (\u0437\u0443\u043c) \u0437\u0430 \u0441\u0447\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f transform matrix.<\/p>\n<p>  \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u043e will-change \u043a\u043b\u0430\u0441\u0441\u0430 .animate-viewport \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443, \u0447\u0442\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c GPU, \u0430 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e transition \u0437\u0430\u0434\u0430\u0435\u0442 \u043f\u043b\u0430\u0432\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0445\u043e\u043b\u0441\u0442\u0430 \u043a \u0431\u043b\u043e\u043a\u0443:<\/p>\n<pre><code class=\"css\">.animate-viewport {  will-change: transform;  transition: transform 0.5s ease-in-out;<\/code><\/pre>\n<p>  \u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u043d\u0430\u0448\u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u043d\u0438\u0436\u0435:<\/p>\n<pre><code class=\"javascript\">public zoomToCell(center: g.Point, zoom: number, offset: boolean = true): void {    this.updateGridSize();    const currentMatrix = this.paper.layers.getAttribute('transform');    \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043d\u043e\u0432\u0443\u044e svg-\u043c\u0430\u0442\u0440\u0438\u0446\u0443, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0445\u043e\u043b\u0441\u0442 \u0432 \u0442\u043e\u0447\u043a\u0443 \u0438\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 center    \/\/ \u0438 \u0434\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u0443\u0435\u043c \u0435\u0435, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 style    const { a, b, c, d, e, f } = this.zoomMatrix(zoom, center, offset);    \/\/ \u0414\u043b\u044f FireFox \u043d\u0443\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0443\u044e \u043c\u0430\u0442\u0440\u0438\u0446\u0443, \u0438\u043d\u0430\u0447\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0439 \u0440\u044b\u0432\u043e\u043a \u0445\u043e\u043b\u0441\u0442\u0430 \u0432 \u0441\u0442\u043e\u0440\u043e\u043d\u0443    this.paper.layers.style.transform = currentMatrix;    \/\/ \u0411\u0435\u0437 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0430 FF \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0442\u043e, \u0447\u0442\u043e \u043c\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u0443\u044e \u043c\u0430\u0442\u0440\u0438\u0446\u0443, \u0438 \u0441\u043d\u043e\u0432\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0440\u044b\u0432\u043e\u043a    setTimeout(() =&gt; {      \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c CSS-\u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440 .animate-viewport, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u043e \u0441\u0432-\u0432\u043e transition;      \/\/ \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 style \u043d\u043e\u0432\u0443\u044e \u043c\u0430\u0442\u0440\u0438\u0446\u0443 \u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0432-\u0432\u0430 transition      this.paper.layers.classList.add('animate-viewport');      this.paper.layers.style.transform = `matrix(${ a }, ${ b }, ${ c }, ${ d }, ${ e }, ${ f })`;      const duration = parseFloat(getComputedStyle(this.paper.layers)['transitionDuration']) * 1000;      \/\/ \u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440 \u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 style;      \/\/ \u0434\u043b\u044f \u0445\u043e\u043b\u0441\u0442\u0430 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043c\u0430\u0442\u0440\u0438\u0446\u0443 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 joint      setTimeout(() =&gt; {        this.paper.layers.classList.remove('animate-viewport');        this.paper.layers.style.transform = null;        this.paper.matrix(newMatrix);        this.paper.trigger('paper:zoom');        this.updateGridSize();        this.paper.trigger('paper:update');      }, duration);    }, 100);  }<\/code><\/pre>\n<p>  \u041a\u0430\u043a \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0438\u043d\u043e\u0433\u0434\u0430 \u0434\u0430\u0436\u0435 \u0441\u0430\u043c\u044b\u0435 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0435 \u043b\u0438\u0431\u044b \u043d\u0430\u0434\u043e \u0434\u043e\u043f\u0438\u043b\u0438\u0432\u0430\u0442\u044c \u043d\u0430\u043f\u0438\u043b\u044c\u043d\u0438\u043a\u043e\u043c \ud83d\ude42 \u041d\u0430\u0434\u0435\u0435\u043c\u0441\u044f, \u0432\u0430\u043c \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u043b\u043e\u0441\u044c \u043a\u043e\u043f\u0430\u0442\u044c\u0441\u044f \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u044f\u0445 \u043a\u0438\u0442\u0430 (\u043a\u0430\u043a \u0431\u044b \u043a\u0440\u0438\u043f\u043e\u0432\u043e \u044d\u0442\u043e \u043d\u0438 \u0437\u0432\u0443\u0447\u0430\u043b\u043e). \u0416\u0435\u043b\u0430\u0435\u043c \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441 Voximplant Kit \u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e!<\/div>\n<p> \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\/company\/Voximplant\/blog\/492232\/\"> https:\/\/habr.com\/ru\/company\/Voximplant\/blog\/492232\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/company\/Voximplant\/blog\/492232\/\"><a href=\"https:\/\/habr.com\/ru\/company\/Voximplant\/blog\/492232\/\"><\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/by\/c2\/ih\/byc2ihl70ggcz-ftm-a4ziskyvo.png\"><\/div>\n<p><\/a><br \/>  \u041c\u044b \u0434\u043e\u043b\u0433\u043e \u0433\u043e\u0442\u043e\u0432\u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 Smartcalls \u2013 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u043b\u044f \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0437\u0432\u043e\u043d\u043a\u043e\u0432 \u2013 \u0438 \u0432\u043e\u0442 \u043e\u043d\u043e \u0441\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u043c \u043f\u0440\u043e UI\/UX-\u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043b\u0435\u0437\u0435\u043c \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442 \u0434\u0435\u043c\u043e-\u0440\u0435\u0436\u0438\u043c\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u0438\u0440\u0443\u0447\u0430\u043b\u0438 JointJS.<\/p>\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-300218","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/300218","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=300218"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/300218\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=300218"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=300218"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=300218"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}