{"id":253124,"date":"2015-03-16T11:36:02","date_gmt":"2015-03-16T07:36:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=253124"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=253124","title":{"rendered":"\u0418\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u043a\u0430\u0440\u0442\u0430 \u0442\u043e\u0440\u0433\u043e\u0432\u043e\u0433\u043e \u0446\u0435\u043d\u0442\u0440\u0430 \u043d\u0430 HTML5 canvas"},"content":{"rendered":"<br \/>\n<h4>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h4>\n<p>  \u0417\u0430\u043a\u0430\u0437\u0447\u0438\u043a\u043e\u043c \u0431\u044b\u043b\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u2013 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u043a\u0430\u0440\u0442\u0430\u0445 \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445 \u0446\u0435\u043d\u0442\u0440\u043e\u0432 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e \u043f\u043e\u0441\u0435\u0449\u0430\u0435\u043c\u043e\u0441\u0442\u0438 \u043c\u0430\u0433\u0430\u0437\u0438\u043d\u043e\u0432, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u044d\u0441\u043a\u0430\u043b\u0430\u0442\u043e\u0440\u043e\u0432, \u043b\u0438\u0444\u0442\u043e\u0432 \u0438 \u043a\u043e\u0440\u0438\u0434\u043e\u0440\u043e\u0432. \u041a\u0430\u0440\u0442\u0443 \u043d\u0443\u0436\u043d\u043e \u0443\u043c\u0435\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0447\u0430\u0442\u044c \u2014 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u0447\u043a\u0438, \u0433\u0434\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0438 \u043a\u0430\u043a\u0443\u044e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443. \u0418, \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0434\u043b\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0438\u043e\u0434\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432. \u041e\u0442\u043a\u0443\u0434\u0430 \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u0438 \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u2013 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0442\u0435\u043c\u0430, \u0437\u0430 \u0441\u043a\u043e\u0431\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>  \u0420\u0430\u0437 \u043f\u043b\u044e\u043d\u0443\u0442\u044c, \u0441\u043a\u0430\u0436\u0435\u0442\u0435 \u0432\u044b \u2013 \u0431\u0435\u0440\u0451\u043c \u0432\u0435\u043a\u0442\u043e\u0440\u043d\u0443\u044e \u043a\u0430\u0440\u0442\u0443 \u0442\u043e\u0440\u0433\u043e\u0432\u043e\u0433\u043e \u0446\u0435\u043d\u0442\u0440\u0430 \u0432 svg \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0435\u0451 \u0434\u0430\u043d\u043d\u044b\u043c\u0438. \u041a\u0440\u0430\u0441\u0438\u0432\u043e, \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e, \u0431\u044b\u0441\u0442\u0440\u043e. \u0414\u0430\u0436\u0435 \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u0430 jVectorMap.<\/p>\n<p>  \u0422\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0442 \u0432\u0435\u043a\u0442\u043e\u0440\u043d\u044b\u0445 \u043a\u0430\u0440\u0442 \u043d\u0443\u0436\u043d\u044b\u0445 \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445 \u0446\u0435\u043d\u0442\u0440\u043e\u0432 \u043d\u0435\u0442, \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438, \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0432\u043b\u0430\u0434\u0435\u043b\u044c\u0446\u0430\u043c\u0438 \u0446\u0435\u043d\u0442\u0440\u043e\u0432. \u0410\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u0440\u0430\u0437\u043d\u044b\u0435 \u043f\u043e \u0441\u0442\u0438\u043b\u0438\u0441\u0442\u0438\u043a\u0435 \u0438 \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e. \u0410 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0446\u0435\u043d\u0442\u0440\u043e\u0432 (\u043f\u043e\u0440\u044f\u0434\u043a\u0430 300) \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u0434\u0451\u0448\u0435\u0432\u043e. \u0414\u0430 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445 \u0446\u0435\u043d\u0442\u0440\u043e\u0432 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b.<\/p>\n<p>  \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u044b\u043b\u043e \u0440\u0435\u0448\u0435\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c HTML5 canvas \u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 \u043a\u0430\u0440\u0442\u044b, \u0438 \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<h4>\u0412\u044b\u0431\u043e\u0440 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430<\/h4>\n<p>  \u0420\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0441 canvas API \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e, \u043d\u043e \u0443\u0436\u0435 \u043f\u043e\u043d\u0430\u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043d\u0430 \u043a\u0443\u0447\u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b. \u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0443 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435:  <\/p>\n<ol>\n<li>\u041e\u0431\u044a\u0435\u043a\u0442\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u043e\u0432\u0435\u0440\u0445 canvas API.<\/li>\n<li>\u0421\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443.<\/li>\n<li>\u0418\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c:<br \/> \n<ul>\n<li>\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 \u043a\u0430\u0440\u0442\u044b,<\/li>\n<li>\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u043f\u043e \u043a\u0430\u0440\u0442\u0435.<\/li>\n<\/ul>\n<\/li>\n<li>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430\/\u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u0440\u0430\u0437\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432.<\/li>\n<li>\u041d\u0430\u043b\u0438\u0447\u0438\u0435 \u0434\u0435\u0442\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439.<\/li>\n<li>\u0412\u044b\u0441\u043e\u043a\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438.<\/li>\n<\/ol>\n<p>  \u041f\u043e\u0434 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u0435 \u043f\u043e\u043f\u0430\u043b\u0438 <a href=\"http:\/\/fabricjs.com\/\">fabric.js<\/a>, <a href=\"http:\/\/www.createjs.com\/EaselJS\">EaselJS<\/a>, <a href=\"http:\/\/raphaeljs.com\/\">Rapha\u00ebl<\/a>, <a href=\"http:\/\/paperjs.org\/\">Paper.js<\/a> \u0438 <a href=\"http:\/\/processingjs.org\/\">Processing.js<\/a>. <br \/>  \u0412\u0441\u0435\u043c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u0435\u0442 fabric.js. \u0423\u0447\u0438\u0442\u044b\u0432\u0430\u044f \u0438\u043c\u0435\u044e\u0449\u0438\u0439\u0441\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043e\u043f\u044b\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0438\u043c, \u0431\u044b\u043b\u043e \u0440\u0435\u0448\u0435\u043d\u043e \u0432\u0437\u044f\u0442\u044c \u0435\u0433\u043e \u0437\u0430 \u043e\u0441\u043d\u043e\u0432\u0443. \u0414\u0430\u043b\u0435\u0435 \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0430\u0441\u044c \u0432\u0435\u0440\u0441\u0438\u044f 1.4.4.<\/p>\n<p>  <a name=\"habracut\"><\/a><\/p>\n<h4>\u0425\u043e\u043b\u0441\u0442 \u0438 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0430 \u043a\u0430\u0440\u0442\u044b<\/h4>\n<p>  \u0412\u043e\u0437\u044c\u043c\u0451\u043c \u043a\u0430\u0440\u0442\u0443:<br \/>  <img decoding=\"async\" src=\"http:\/\/habrastorage.org\/getpro\/habr\/post_images\/684\/09d\/da4\/68409dda4b502e221afa0a6b9e332d8f.png\" alt=\"image\"\/><\/p>\n<p>  \u0412 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0435\u0437\u0430\u043c\u044b\u0441\u043b\u043e\u0432\u0430\u0442\u044b\u0439 \u0445\u043e\u043b\u0441\u0442:  <\/p>\n<pre><code class=\"html\">&lt;canvas id=&quot;canvas&quot; width=&quot;1000px&quot; height=&quot;400px&quot; style=&quot;border: 1px solid black&quot;&gt; <\/code><\/pre>\n<p>  \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u0438\u0437 \u043d\u0435\u0433\u043e fabric.js \u0445\u043e\u043b\u0441\u0442, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0432 \u0437\u0430\u043e\u0434\u043d\u043e \u043d\u0443\u0436\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:  <\/p>\n<pre><code class=\"javascript\">var element = $('#canvas'), \/\/ \u0435\u0449\u0451 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \tcanvas = new fabric.Canvas(element.get(0), { \t\tselection: false, \/\/ \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u0430 \u0433\u0440\u0443\u043f\u043f\u044b \t\tscale: 1, \/\/ \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u043c\u0430\u0441\u0448\u0442\u0430\u0431 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \t\trenderOnAddRemove: false, \/\/ \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u043c \u0430\u0432\u0442\u043e-\u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0443, \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043c\u0435\u0442\u043e\u043a \t\tmoveCursor: 'default', \/\/ \u0441\u0431\u0440\u043e\u0441\u0438\u043c \u043a\u0443\u0440\u0441\u043e\u0440\u044b, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043e\u0442\u0432\u043b\u0435\u043a\u0430\u043b\u0438 \t\thoverCursor: 'default' \t}); <\/code><\/pre>\n<h4>\u041c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043f\u043e \u043a\u0430\u0440\u0442\u0435<\/h4>\n<p>  \u0420\u0430\u0437\u043c\u0435\u0440 \u043a\u0430\u0440\u0442 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a\u043e\u0439 \u0443\u0433\u043e\u0434\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u043d\u0435\u0439, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043c\u044b\u0448\u044c. \u041f\u043e \u0441\u0443\u0442\u0438 \u0442\u0430\u043a\u0438\u0435 \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0438 \u044d\u0442\u043e \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0432\u0441\u0435\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043d\u0430 \u043a\u0430\u0440\u0442\u0435, \u0442\u043e \u0435\u0441\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u0438.<br \/>  \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435:  <\/p>\n<pre><code class=\"javascript\">var baseWidth = 0, \/\/ \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u0448\u0438\u0440\u0438\u043d\u0430 \tbaseHeight= 0, \/\/ \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u0432\u044b\u0441\u043e\u0442\u0430 \tbaseScale = 1, \/\/ \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0430\u0441\u0448\u0442\u0430\u0431 \t \twidth = 0, \/\/ \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0448\u0438\u0440\u0438\u043d\u0430 \theight = 0, \/\/ \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0432\u044b\u0441\u043e\u0442\u0430 \ttransX = 0, \/\/ \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043f\u043e \u043e\u0441\u0438 x \ttransY = 0, \/\/ \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043f\u043e \u043e\u0441\u0438 y \tscale = 1; \/\/ \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u0430\u0441\u0448\u0442\u0430\u0431 \u0432 \u0446\u0435\u043b\u043e\u043c <\/code><\/pre>\n<p>  \u041f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043d\u0430 \u0445\u043e\u043b\u0441\u0442\u0435 \u0431\u0443\u0434\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:  <\/p>\n<pre><code class=\"javascript\">var applyTransform = function () { \tvar maxTransX, \t\tmaxTransY, \t\tminTransX, \t\tminTransY, \t\tgroup;  \t\/\/ \u0420\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043f\u043e\u0440\u043e\u0433\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u043f\u043e \u043e\u0441\u0438 x \tif (baseWidth * scale &lt;= width) { \t\t\/\/ \u041a\u0430\u0440\u0442\u0430 \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0445\u043e\u043b\u0441\u0442 \t\tmaxTransX = (width - baseWidth * scale) \/ (2 * scale); \t\tminTransX = (width - baseWidth * scale) \/ (2 * scale); \t} else { \t\t\/\/ \u041d\u0435 \u0432\u043b\u0430\u0437\u0438\u0442 \t\tmaxTransX = 0; \t\tminTransX = (width - baseWidth * scale) \/ scale; \t} \t\/\/ \u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u043c \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u043e\u0433\u043e\u0432\u044b\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \tif (transX &gt; maxTransX) { \t\ttransX = maxTransX; \t} else if (transX &lt; minTransX) { \t\ttransX = minTransX; \t}  \t\/\/ \u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0434\u043b\u044f \u043e\u0441\u0438 y \tif (baseHeight * scale &lt;= height) { \t\tmaxTransY = (height - baseHeight * scale) \/ (2 * scale); \t\tminTransY = (height - baseHeight * scale) \/ (2 * scale); \t} else { \t\tmaxTransY = 0; \t\tminTransY = (height - baseHeight * scale) \/ scale; \t} \tif (transY &gt; maxTransY) { \t\ttransY = maxTransY; \t} else if (transY &lt; minTransY) { \t\ttransY = minTransY; \t}  \t\/\/ \u0421\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0430 \u0445\u043e\u043b\u0441\u0442\u0435 \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \tgroup = new fabric.Group(canvas.getObjects()); \tgroup.scaleX = scale \/ canvas.scale; \tgroup.scaleY = scale \/ canvas.scale; \tgroup.left = group.getWidth() \/ 2 + transX * scale; \tgroup.top = group.getHeight() \/ 2 + transY * scale; \tgroup.destroy();  \t\/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u043c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0430\u0441\u0448\u0442\u0430\u0431 \u043d\u0430 \u0445\u043e\u043b\u0441\u0442\u0435 \tcanvas.scale = scale;  \t\/\/ \u041e\u0442\u0440\u0438\u0441\u0443\u0435\u043c \u0445\u043e\u043b\u0441\u0442 \u0441 \u0438\u0437\u043c\u0435\u043d\u0451\u043d\u043d\u044b\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \tcanvas.renderAll(); }; <\/code><\/pre>\n<p>  \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 \u0431\u0443\u0434\u0435\u043c \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u043c\u0430\u0441\u0448\u0442\u0430\u0431:  <\/p>\n<pre><code class=\"javascript\">var setScale = function (scaleToSet, anchorX, anchorY) { \tvar zoomMax = 5, \/\/ \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e 5-\u0442\u0438 \u043a\u0440\u0430\u0442\u043d\u043e\u0435 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \t\tzoomMin =  1, \/\/ \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 - \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \t\tzoomStep; \/\/ \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0430 \t\t \t\/\/ \u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u043c \u043c\u0430\u0441\u0448\u0442\u0430\u0431, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \tif (scaleToSet &gt; zoomMax * baseScale) { \t\tscaleToSet = zoomMax * baseScale; \t} else if (scaleToSet &lt; zoomMin * baseScale) { \t\tscaleToSet = zoomMin * baseScale; \t}  \t\/\/ \u0426\u0435\u043d\u0442\u0440 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f - \u0442\u043e\u0447\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u043e\u0441\u0442\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043c\u0435\u0441\u0442\u0435. \t\/\/ \u0417\u0430\u0434\u0430\u0451\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 anchorX \u0438 anchorY. \t\/\/ \u041f\u043e \u0441\u0443\u0442\u0438 \u044d\u0442\u043e \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u043a\u0443\u0440\u0441\u043e\u0440\u0430 \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \tif (typeof anchorX != 'undefined' && typeof anchorY != 'undefined') { \t\tzoomStep = scaleToSet \/ scale; \t\t\/\/ \u0420\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u0435\u043c, \u043d\u0430 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \t\t\/\/ \u0447\u0442\u043e\u0431\u044b \u0446\u0435\u043d\u0442\u0440 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u043d\u0430 \u043c\u0435\u0441\u0442\u0435. \t\ttransX -= (zoomStep - 1) \/ scaleToSet * anchorX; \t\ttransY -= (zoomStep - 1) \/ scaleToSet * anchorY; \t}  \tscale = scaleToSet;\t \tapplyTransform(); }; <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043c\u044b\u0448\u0438:  <\/p>\n<pre><code class=\"javascript\">var bindContainerEvents= function () { \tvar mouseDown = false, \t\toldPageX, \t\toldPageY, \t\tcontainer = $(canvas.wrapperEl);  \tcontainer.mousemove(function (e) { \t\t\/\/ \u041d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \t\tif (mouseDown) { \t\t\t\/\/ \u0420\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0430 \t\t\ttransX -= (oldPageX - e.pageX) \/ scale; \t\t\ttransY -= (oldPageY - e.pageY) \/ scale;  \t\t\tapplyTransform();  \t\t\toldPageX = e.pageX; \t\t\toldPageY = e.pageY; \t\t\treturn false; \t\t} \t}).mousedown(function (e) { \t\t\/\/ \u0417\u0430\u043f\u043e\u043c\u043d\u0438\u043c \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u043f\u043e \u043a\u0430\u0440\u0442\u0435 \t\tmouseDown = true; \t\toldPageX = e.pageX; \t\toldPageY = e.pageY; \t\treturn false; \t});  \t$('body').mouseup(function () { \t\tmouseDown = false; \t});  \t\/\/ \u041c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043b\u0435\u0441\u043e\u043c \u043c\u044b\u0448\u0438 \tcontainer.mousewheel(function (event, delta, deltaX, deltaY) { \t\tvar offset = element.offset(), \/\/ \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0445\u043e\u043b\u0441\u0442\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \t\t\tcenterX = event.pageX - offset.left, \/\/ \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430 x \u0446\u0435\u043d\u0442\u0440\u0430 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \t\t\tcenterY = event.pageY - offset.top, \/\/ \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430 y \u0446\u0435\u043d\u0442\u0440\u0430 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \t\t\tzoomStep = Math.pow(1.3, deltaY); \/\/ \u0448\u0430\u0433 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.  \t\tsetScale(scale * zoomStep, centerX, centerY); \t\t \t\t\/\/ \u041e\u0442\u043a\u043b\u044e\u0447\u0438\u043c \u0441\u043a\u0440\u043e\u043b\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \t\tevent.preventDefault(); \t}); }; <\/code><\/pre>\n<p>  \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 <a href=\"http:\/\/plugins.jquery.com\/mousewheel\/\">jQuery Mousewheel<\/a> \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0438 \u043a\u043e\u043b\u0435\u0441\u0430 \u043c\u044b\u0448\u0438.<br \/>  \u041a\u0440\u043e\u043c\u0435 \u044d\u0442\u043e\u0433\u043e, \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 touch \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u043e\u0431\u044b\u0442\u0438\u0439. \u0422\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u044b\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u043f\u0440\u0438\u043a\u043e\u0441\u043d\u043e\u0432\u0435\u043d\u0438\u0439 \u00ab\u0441\u0434\u0432\u0438\u043d\u0443\u0442\u044c\u00bb (\u043e\u0434\u043d\u043e\u043f\u0430\u043b\u044c\u0446\u0435\u0432\u043e\u0435 \u043a\u0430\u0441\u0430\u043d\u0438\u0435), \u00ab\u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c\u00bb \u0438 \u00ab\u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c\u00bb (\u0434\u0432\u0443\u043f\u0430\u043b\u044c\u0446\u0435\u0432\u044b\u0435 \u043a\u0430\u0441\u0430\u043d\u0438\u044f) \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0434\u043e\u0432\u0430\u0442\u044c \u0432\u043b\u0430\u0434\u0435\u043b\u044c\u0446\u0435\u0432 \u0442\u0430\u043a\u0438\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432.  <\/p>\n<pre><code class=\"javascript\">var bindContainerTouchEvents = function () { \tvar touchStartScale, \t\ttouchStartDistance,  \t\tcontainer = $(canvas.wrapperEl), \t\ttouchX, \t\ttouchY, \t\tcenterTouchX, \t\tcenterTouchY, \t\tlastTouchesLength, \t\thandleTouchEvent = function (e) { \t\t\tvar touches = e.originalEvent.touches, \t\t\t\toffset, \t\t\t\tcurrentScale, \t\t\t\ttransXOld, \t\t\t\ttransYOld;  \t\t\tif (e.type == 'touchstart') { \t\t\t\tlastTouchesLength = 0; \t\t\t} \t\t\tif (touches.length == 1) { \t\t\t\t\/\/ \u041f\u0440\u043e\u0441\u0442\u043e\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \t\t\t\tif (lastTouchesLength == 1) { \t\t\t\t\ttransXOld = transX; \t\t\t\t\ttransYOld = transY; \t\t\t\t\ttransX -= (touchX - touches[0].pageX) \/ scale; \t\t\t\t\ttransY -= (touchY - touches[0].pageY) \/ scale; \t\t\t\t\tapplyTransform(); \t\t\t\t\tif (transXOld != transX || transYOld != transY) { \t\t\t\t\t\te.preventDefault(); \t\t\t\t\t} \t\t\t\t} \t\t\t\ttouchX = touches[0].pageX; \t\t\t\ttouchY = touches[0].pageY; \t\t\t} else if (touches.length == 2) { \t\t\t\t\/\/ \u041c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \t\t\t\tif (lastTouchesLength == 2) { \t\t\t\t\tcurrentScale = Math.sqrt( \t\t\t\t\t  Math.pow(touches[0].pageX - touches[1].pageX, 2) + \t\t\t\t\t  Math.pow(touches[0].pageY - touches[1].pageY, 2) \t\t\t\t\t) \/ touchStartDistance; \t\t\t\t\tsetScale(touchStartScale * currentScale, centerTouchX, centerTouchY); \t\t\t\t\te.preventDefault(); \t\t\t\t} else { \t\t\t\t\t\/\/ \u041c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0437\u0430\u043f\u043e\u043c\u043d\u0438\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \t\t\t\t\toffset = element.offset(); \t\t\t\t\tif (touches[0].pageX &gt; touches[1].pageX) { \t\t\t\t\t\tcenterTouchX = touches[1].pageX + (touches[0].pageX - touches[1].pageX) \/ 2; \t\t\t\t\t} else { \t\t\t\t\t\tcenterTouchX = touches[0].pageX + (touches[1].pageX - touches[0].pageX) \/ 2; \t\t\t\t\t} \t\t\t\t\tif (touches[0].pageY &gt; touches[1].pageY) { \t\t\t\t\t\tcenterTouchY = touches[1].pageY + (touches[0].pageY - touches[1].pageY) \/ 2; \t\t\t\t\t} else { \t\t\t\t\t\tcenterTouchY = touches[0].pageY + (touches[1].pageY - touches[0].pageY) \/ 2; \t\t\t\t\t} \t\t\t\t\tcenterTouchX -= offset.left; \t\t\t\t\tcenterTouchY -= offset.top; \t\t\t\t\ttouchStartScale = scale; \t\t\t\t\ttouchStartDistance = Math.sqrt( \t\t\t\t\t  Math.pow(touches[0].pageX - touches[1].pageX, 2) + \t\t\t\t\t  Math.pow(touches[0].pageY - touches[1].pageY, 2) \t\t\t\t\t); \t\t\t\t} \t\t\t}  \t\t\tlastTouchesLength = touches.length; \t\t};  \tcontainer.bind('touchstart', handleTouchEvent); \tcontainer.bind('touchmove', handleTouchEvent); }; <\/code><\/pre>\n<p>  \u041c\u0430\u0433\u0438\u044f \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0439 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0432\u0437\u044f\u0442\u0430 \u0438\u0437 <a href=\"https:\/\/www.drupal.org\/project\/jvector\">jVector<\/a>.<\/p>\n<p>  \u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u043a\u0430\u0440\u0442\u0443 \u0438 \u043e\u0442\u0440\u0438\u0441\u0443\u0435\u043c \u0435\u0451:  <\/p>\n<pre><code class=\"javascript\">fabric.util.loadImage('Map.png', function(img) { \tvar map = new fabric.Image(img), \t\tcurBaseScale; \tif (('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch)) { \t\tbindContainerTouchEvents(); \t} else { \t\tbindContainerEvents(); \t} \t \t\/\/ \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u0438 \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u044b \tbaseWidth = map.width; \tbaseHeight = map.height; \twidth = element.width(); \theight = element.height(); \t \t\/\/ \u041e\u0442\u043a\u043b\u044e\u0447\u0438\u043c \u043b\u044e\u0431\u0443\u044e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0432\u044b\u0431\u043e\u0440\u0430 \u043a\u0430\u0440\u0442\u044b \u043a\u0430\u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043d\u0430 \u0445\u043e\u043b\u0441\u0442\u0435 \tmap.set({ \t\thasRotatingPoint: false, \t\thasBorders: false, \t\thasControls: false, \t\tlockScalingY: true, \t\tlockScalingX: true, \t\tselectable: false, \t\tleft: map.width \/ 2, \t\ttop: map.height \/ 2, \t\toriginX: 'center', \t\toriginY: 'center' \t}); \tcanvas.add(map); \t \t\/\/ \u041e\u0442\u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c, \u0447\u0442\u043e\u0431\u044b \u0441\u0440\u0430\u0437\u0443 \u0432\u0438\u0434\u0435\u0442\u044c \u0432\u0441\u0451 \u043a\u0430\u0440\u0442\u0443 \tcurBaseScale  = baseScale; \tif (width \/ height &gt; baseWidth \/ baseHeight) { \t\tbaseScale = height \/ baseHeight; \t} else { \t\tbaseScale = width \/ baseWidth; \t} \tscale *= baseScale \/ curBaseScale; \ttransX *= baseScale \/ curBaseScale; \ttransY *= baseScale \/ curBaseScale; \t \tcanvas.setWidth(width); \tcanvas.setHeight(height); \t \tapplyTransform(); \t \t\/\/ \u041c\u0435\u0442\u043a\u0438 \u043d\u0430 \u043a\u0430\u0440\u0442\u0435, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u0437\u0434\u043d\u0435\u0435 \tcreateMarkers(); }); <\/code><\/pre>\n<h4>\u041c\u0435\u0442\u043a\u0438 \u043d\u0430 \u043a\u0430\u0440\u0442\u0435<\/h4>\n<p>  \u041c\u044b \u0443\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0443\u0434\u043e\u0431\u043d\u0443\u044e \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043a\u0430\u0440\u0442\u0443, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430\u043d\u043e\u0441\u0438\u0442\u044c \u043d\u0430 \u043d\u0435\u0451 \u043c\u0435\u0442\u043a\u0438 \u0438 \u0437\u0430\u0442\u0435\u043c \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0438\u0445 \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438.<br \/>  \u041b\u0443\u0447\u0448\u0435 \u0432\u0441\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u043a\u0442\u043e\u0440\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0442\u043e\u0433\u0434\u0430 \u043f\u0440\u0438 \u043b\u044e\u0431\u043e\u043c \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0438 \u043a\u0430\u0440\u0442\u044b \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043e\u0442\u043b\u0438\u0447\u043d\u043e.<br \/>  \u041f\u043e\u043c\u0438\u043c\u043e \u043c\u0435\u0442\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0451 \u0438 \u0442\u0435\u043a\u0441\u0442, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e\u0441\u0435\u0449\u0435\u043d\u0438\u0439 \u044d\u0442\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u043a\u0430\u0440\u0442\u044b. \u0422\u0435\u043a\u0441\u0442 \u0431\u0443\u0434\u0435\u0442 \u0447\u0438\u0442\u0430\u0435\u043c \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u043a\u0430\u0440\u0442\u0435, \u0435\u0441\u043b\u0438 \u0435\u0433\u043e \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u043c \u0441\u043e \u0441\u043f\u043b\u043e\u0448\u043d\u043e\u0439 \u0437\u0430\u043b\u0438\u0432\u043a\u043e\u0439. \u0414\u043b\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u043e\u0431\u0451\u0440\u0442\u043a\u0438 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c originX \u0438 originY \u0432 &#8216;center&#8217;.  <\/p>\n<pre><code class=\"javascript\">var markerColor = '#2567d5';  var addMarker = function(point, text) { \t\/\/ \u0421\u0430\u043c\u0430 \u043c\u0435\u0442\u043a\u0430 \tvar marker = new fabric.Path('m 11,-19.124715 c -8.2234742,0 -14.8981027,-6.676138 -14.8981027,-14.9016 0,-5.633585 3.35732837,-10.582599 6.3104192,-14.933175 C 4.5507896,-52.109948 9.1631953,-59.34619 11,-61.92345 c 1.733396,2.518329 6.760904,9.975806 8.874266,13.22971 3.050966,4.697513 6.023837,8.647788 6.023837,14.667425 0,8.225462 -6.674629,14.9016 -14.898103,14.9016 z m 0,-9.996913 c 2.703016,0 4.903568,-2.201022 4.903568,-4.904687 0,-2.703664 -2.200552,-4.873493 -4.903568,-4.873493 -2.7030165,0 -4.903568,2.169829 -4.903568,4.873493 0,2.703665 2.2005515,4.904687 4.903568,4.904687 z&quot;',  \t{ \t\twidth: 40,  \t\theight: 80, \t\tscaleX: scale,  \t\tscaleY: scale,  \t\tleft: point.x, \t\ttop: point.y, \t\toriginX: 'center', \t\toriginY: 'center', \t\tfill: markerColor, \t\tstroke: '#2e69b6', \t\ttext: text \/\/ \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u0442\u0435\u043a\u0441\u0442 \u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u0435 \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430\/\u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \t}), \t\/\/ \u0422\u0435\u043a\u0441\u0442 \ttextObject = new fabric.Text(text, {  \t\tfontSize: 30,  \t\toriginX: 'center',  \t\tfill: markerColor, \t\toriginY: 'center'  \t}), \t\/\/ \u041e\u0431\u0451\u0440\u0442\u043a\u0430 \u0432\u043e\u043a\u0440\u0443\u0433 \u0442\u0435\u043a\u0441\u0442\u0430 \tbackground = new fabric.Rect({ \t\twidth: 100,  \t\theight: 40,  \t\toriginX: 'center',  \t\toriginY: 'center', \t\tfill: 'white', \t\tstroke: 'black' \t}), \t\/\/ \u0421\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u0435\u043c \u0438\u0445 \u0434\u043b\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \ttextGroup = new fabric.Group([background, textObject], {  \t\tscaleX: scale, \t\tscaleY: scale, \t\tleft: point.x + 20 * scale, \/\/ \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043c\u0430\u0441\u0448\u0442\u0430\u0431 \t\ttop: point.y - 30 * scale \/\/ \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043c\u0430\u0441\u0448\u0442\u0430\u0431 \t});  \tcanvas.add(marker); \tcanvas.add(textGroup); }; <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043b\u0435\u0433\u043a\u043e \u043d\u0430\u043d\u0435\u0441\u0442\u0438 \u043d\u0430 \u043a\u0430\u0440\u0442\u0443 \u043f\u0430\u0440\u043e\u0447\u043a\u0443 \u043c\u0435\u0442\u043e\u043a:  <\/p>\n<pre><code class=\"javascript\">\taddMarker({x: 550, y: 390}, '#0:500'); \taddMarker({x: 460, y: 120}, '#1:300'); \tcanvas.renderAll(); <\/code><\/pre>\n<p>  \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c:<br \/>  <img decoding=\"async\" src=\"\/\/habrastorage.org\/files\/d0d\/468\/398\/d0d468398e8447f3934c7b15181dbe57.png\"\/><\/p>\n<h5>\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h5>\n<p>  \u0412\u0432\u0435\u0434\u0451\u043c \u0440\u0435\u0436\u0438\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u2014 \u043f\u0440\u0438 \u043a\u043b\u0438\u043a\u0435 \u043d\u0430 \u043a\u0430\u0440\u0442\u0443 \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043c\u0435\u0442\u043a\u0443. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043d\u0430\u043c \u0445\u0432\u0430\u0442\u0438\u0442 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0447\u0435\u043a\u0431\u043e\u043a\u0441\u0430 \u0438 \u0444\u043b\u0430\u0433\u0430:  <\/p>\n<pre><code class=\"html\">\t&lt;div&gt;&lt;input type=&quot;checkbox&quot; onclick=&quot;window.isEditing = this.checked&quot; id=&quot;editing&quot;\/&gt;&lt;label for=&quot;editing&quot;&gt;Editing&lt;\/label&gt;&lt;\/div&gt; <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e createMarkers:  <\/p>\n<pre><code class=\"javascript\">var createMarkers = function() { \tvar markersCount = 0; \t \t\/\/ \u0424\u043b\u0430\u0433 \u0440\u0435\u0436\u0438\u043c\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \twindow.isEditing = false; \t \t\/\/ \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0439 \u043c\u0435\u0442\u043a\u0438 \tcanvas.on('mouse:down', function (options) { \t\tvar position; \t\t \t\tif (!window.isEditing) { \t\t\treturn; \t\t} \t\t\/\/ \u041f\u043e\u043b\u0443\u0447\u0438\u043c \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u0443\u044e \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0443 \u043d\u0430 \u0445\u043e\u043b\u0441\u0442\u0435 \t\tposition = canvas.getPointer(options.e); \t\t\/\/ \u0422\u0435\u043a\u0441\u0442 - \u043d\u043e\u043c\u0435\u0440 \u0438 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \t\taddMarker(position, '#' + markersCount++ + ':' + Math.round(Math.random() * 1000)); \t\t\/\/ \u041d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0443 \t\tcanvas.renderAll(); \t}); }; <\/code><\/pre>\n<p>  \u0421 \u0442\u0430\u043a\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u043a\u0430\u0440\u0442\u0443 \u0432 \u043c\u0435\u0441\u0438\u0432\u043e \u0438\u0437 \u043c\u0435\u0442\u043e\u043a \u0438\u043b\u0438 \u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0430:<br \/>  <img decoding=\"async\" src=\"\/\/habrastorage.org\/files\/f14\/6f4\/414\/f146f4414b414f2399a988f2c4296635.png\"\/><\/p>\n<p>  \u0415\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u0430 \u0446\u0432\u0435\u0442\u0430 \u0438 \u0432\u0438\u0434\u0430 \u043c\u0435\u0442\u043a\u0438, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0439 \u0441 \u043d\u0435\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u0435\u0442\u043a\u043e\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u043d\u0430\u0447\u043e\u043a \u044d\u0441\u043a\u0430\u043b\u0430\u0442\u043e\u0440\u0430:  <\/p>\n<pre><code class=\"javascript\">var circle = new fabric.Circle({ radius: 22.5 }), \tpath1 = new fabric.Path('M31,31h-2L15,17H9c-1.1027832,0-2,0.8971558-2,2c0,1.1027832,0.8972168,2,2,2h2l14,14h6c1.1027832,0,2-0.8972168,2-2C33,31.8971558,32.1027832,31,31,31z', { originX: 'center', originY: 'center', fill: markerColor }), \tpath2 = new fabric.Path('M22.5,2C11.1782227,2,2,11.1781616,2,22.5S11.1782227,43,22.5,43S43,33.8218384,43,22.5S33.8217773,2,22.5,2z M26.5,7C27.8806152,7,29,8.1192627,29,9.5c0,1.3806763-1.1193848,2.5-2.5,2.5c-1.3807373,0-2.5-1.1193237-2.5-2.5C24,8.1192627,25.1192627,7,26.5,7z M26.5,13.0023804c1.380249-0.0330811,2.5,0.2385864,2.5,3s0,8,0,8l-6-7C23,17.0023804,25.0908203,13.0361938,26.5,13.0023804z M31,38h-7L10,24H9c-2.7614746,0-5-2.2385864-5-5s2.2385254-5,5-5h7l14,14h1c2.7613525,0,5,2.2385864,5,5S33.7613525,38,31,38z', { originX: 'center', originY: 'center', fill: markerColor }), \tmarker = new fabric.Group([circle, path1, path2], { \t\twidth: 40,  \t\theight: 80, \t\tscaleX: scale,  \t\tscaleY: scale,  \t\tleft: point.x, \t\ttop: point.y, \t\toriginX: 'center', \t\toriginY: 'center', \t\tfill: markerColor, \t}); <\/code><\/pre>\n<p>  <img decoding=\"async\" src=\"\/\/habrastorage.org\/files\/239\/cfb\/6fc\/239cfb6fcf9c4d36a65a47f4cc36d1bb.png\"\/><\/p>\n<p>  \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, fabric.js \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u2014 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c, \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440, \u043f\u043e\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0438 \u0442.\u0434. \u0417\u043d\u0430\u0447\u0438\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0448\u0438\u0440\u043e\u043a\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0439 \u0438 \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438.<\/p>\n<h5>\u0417\u043e\u043d\u044b<\/h5>\n<p>  \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a \u0445\u043e\u0442\u0435\u043b \u0435\u0449\u0451 \u0438 \u0443\u043c\u0435\u0442\u044c \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u043d\u0430 \u043a\u0430\u0440\u0442\u0435 \u0437\u043e\u043d\u044b \u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e \u044d\u0442\u0438\u043c \u0437\u043e\u043d\u0430\u043c. \u041c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0437\u043e\u043d\u044b \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u0439 \u043c\u043d\u043e\u0433\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0442\u043e\u0447\u0435\u043a, \u0440\u0430\u0437\u043c\u0435\u0447\u0430\u0435\u043c\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u043a\u043b\u0438\u043a\u0430\u043c\u0438 \u043c\u044b\u0448\u0438. \u0422\u0430\u043a\u043e\u0439 \u043c\u043d\u043e\u0433\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u0432\u0441\u0435\u0433\u0434\u0430 \u0437\u0430\u043c\u043a\u043d\u0443\u0442 \u0438 \u043b\u0435\u0433\u043a\u043e \u043d\u0430\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043d\u0430 \u043a\u0430\u0440\u0442\u0443. \u0417\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u044c \u0437\u043e\u043d\u0443 \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0438 \u0434\u0432\u043e\u0439\u043d\u043e\u043c \u043a\u043b\u0438\u043a\u0435. \u0410 \u0443\u0431\u0438\u0440\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u043d\u0430\u0436\u0430\u0442\u0438\u0435\u043c \u043a\u043d\u043e\u043f\u043e\u043a backspace \u0438\u043b\u0438 delete \u2014 \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439 \u043e\u0448\u0438\u0431\u043a\u0438.<br \/>  \u0422\u043e\u0433\u0434\u0430 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0430 \u0437\u043e\u043d\u044b \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c  <\/p>\n<pre><code>canvas.on('mouse:down', function (options) { \t\taddExtendZone(options.e); \t}).on('mouse:move', function (options) { \t\tdrawZone(options.e); \t}); \t$(document).on('dblclick', finishZone).on('keydown', undoZonePoint);   \/\/ \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442, \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u0445 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u0430\u0441\u0448\u0442\u0430\u0431 var convertPointToRelative = function(point, object) { \treturn { x: (point.x - object.left) \/ scale, y: (point.y - object.top) \/ scale }; };  var addExtendZone = function(mouseEvent) { \tvar position = canvas.getPointer(mouseEvent);  \t\/\/ \u041d\u043e\u0432\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0437\u043e\u043d\u044b \tif (currentEditingZone) { \t\tcurrentEditingZone.points.push(convertPointToRelative(position, currentEditingZone)); \t\treturn; \t} \t\/\/ \u041d\u043e\u0432\u0430\u044f \u0437\u043e\u043d\u0430 - \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0441\u0440\u0430\u0437\u0443 3 \u0442\u043e\u0447\u043a\u0438, \u0442\u043e\u0433\u0434\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e \u0437\u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u043b\u0438\u043d\u0438\u0435\u0439 \tcurrentEditingZone = new fabric.Polygon( \t\t[{ x: 0, y: 0 }, { x: 1, y: 1 }, { x: -1, y: -1 }], { \t\tscaleX: scale,  \t\tscaleY: scale,  \t\tleft: position.x, \t\ttop: position.y, \t\tfill: new fabric.Color(markerColor).setAlpha(0.3).toRgba(), \t\tstroke: '#2e69b6', \t}); \t \tcanvas.add(currentEditingZone); \tcanvas.renderAll(); };  var drawZone =  function(mouseEvent) { \tvar points; \tif (currentEditingZone) { \t\t\/\/ \u041f\u0440\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0438 \u043c\u044b\u0448\u0438 \u043c\u0435\u043d\u044f\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0442\u043e\u0447\u043a\u0443, \u0441\u043b\u0435\u0434\u0443\u044f \u0437\u0430 \u043a\u0443\u0440\u0441\u043e\u0440\u043e\u043c \t\tpoints = currentEditingZone.points; \t\tpoints[points.length - 1] = convertPointToRelative(canvas.getPointer(mouseEvent), currentEditingZone); \t\tcanvas.renderAll(); \t} };  var finishZone = function () { \tif (!currentEditingZone) { \t\treturn; \t} \t \t\/\/ \u0423\u0431\u0435\u0440\u0451\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0442\u043e\u0447\u043a\u0443, \u0442\u0430\u043a \u043a\u0430\u043a \u043a\u043b\u0438\u043a \u0434\u0432\u043e\u0439\u043d\u043e\u0439 \tcurrentEditingZone.points.pop(); \tcurrentEditingZone = null; };  var undoZonePoint = function(event) { \t\/\/ \u0422\u043e\u043b\u044c\u043a\u043e backspace \u0438 delete \tif (currentEditingZone && (event.which == 8 || event.which == 46)) { \t\tvar points = currentEditingZone.points, \t\t\tisDeleted = points.length &lt;= 3; \t\tpoints[points.length - 2] = points[points.length - 1]; \t\tpoints.pop(); \t\t\/\/ \u041e\u0442\u043c\u0435\u043d\u0430 \u0437\u043e\u043d\u044b \u0432\u043e\u043e\u0431\u0449\u0435 \t\tif (isDeleted) { \t\t\tcanvas.remove(currentEditingZone); \t\t\tcurrentEditingZone = null; \t\t} \t\tcanvas.renderAll(); \t\tevent.preventDefault(); \t} }; <\/code><\/pre>\n<h4>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442<\/h4>\n<p>  \u0421\u043e\u0431\u0440\u0430\u0432 \u0432\u0441\u0451 \u0432\u043e\u0435\u0434\u0438\u043d\u043e, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u043d\u043e\u0441\u0438\u0442\u044c \u043c\u0435\u0442\u043a\u0438 \u0438 \u0437\u043e\u043d\u044b \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u0443\u044e \u043a\u0430\u0440\u0442\u0443, \u0432\u044b\u0433\u0440\u0443\u0436\u0430\u0442\u044c\/\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u0445 \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e \u0438 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0441 \u043a\u043e\u043a\u0440\u0435\u0442\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u043e \u043f\u043e\u0441\u0435\u0449\u0435\u043d\u0438\u044f\u043c \u044d\u0442\u0438\u0445 \u0442\u043e\u0447\u0435\u043a \u0438\u043b\u0438 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u043d\u0430 \u043a\u0430\u0440\u0442\u0435. \u041f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<br \/>  <img decoding=\"async\" src=\"\/\/habrastorage.org\/files\/570\/0d4\/dd1\/5700d4dd16e5468ea335289531a584f1.png\"\/><\/p>\n<p>  \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0440\u0430\u0437\u043e\u043d\u043e\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u0435 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0439 \u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u0432 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u0440\u0438\u044f\u0442\u043d\u043e\u043c \u0438 \u0433\u0438\u0431\u043a\u043e\u043c \u0432\u0438\u0434\u0435 \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0437\u0430\u0442\u0440\u0430\u0442\u0430\u043c\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u0443\u0441\u0438\u043b\u0438\u0439. HTML5 canvas \u0432\u043a\u0443\u043f\u0435 \u0441 fabric.js \u0434\u0430\u044e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0431\u044b\u0441\u0442\u0440\u044b\u0445 \u0438 \u0443\u0434\u043e\u0431\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c.      \t<\/p>\n<div class=\"clear\"><\/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=\"http:\/\/habrahabr.ru\/post\/251335\/\"> http:\/\/habrahabr.ru\/post\/251335\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<br \/>\n<h4>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h4>\n<p>  \u0417\u0430\u043a\u0430\u0437\u0447\u0438\u043a\u043e\u043c \u0431\u044b\u043b\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u2013 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u043a\u0430\u0440\u0442\u0430\u0445 \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445 \u0446\u0435\u043d\u0442\u0440\u043e\u0432 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e \u043f\u043e\u0441\u0435\u0449\u0430\u0435\u043c\u043e\u0441\u0442\u0438 \u043c\u0430\u0433\u0430\u0437\u0438\u043d\u043e\u0432, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u044d\u0441\u043a\u0430\u043b\u0430\u0442\u043e\u0440\u043e\u0432, \u043b\u0438\u0444\u0442\u043e\u0432 \u0438 \u043a\u043e\u0440\u0438\u0434\u043e\u0440\u043e\u0432. \u041a\u0430\u0440\u0442\u0443 \u043d\u0443\u0436\u043d\u043e \u0443\u043c\u0435\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0447\u0430\u0442\u044c \u2014 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u0447\u043a\u0438, \u0433\u0434\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0438 \u043a\u0430\u043a\u0443\u044e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443. \u0418, \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0434\u043b\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0438\u043e\u0434\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432. \u041e\u0442\u043a\u0443\u0434\u0430 \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u0438 \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u2013 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0442\u0435\u043c\u0430, \u0437\u0430 \u0441\u043a\u043e\u0431\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>  \u0420\u0430\u0437 \u043f\u043b\u044e\u043d\u0443\u0442\u044c, \u0441\u043a\u0430\u0436\u0435\u0442\u0435 \u0432\u044b \u2013 \u0431\u0435\u0440\u0451\u043c \u0432\u0435\u043a\u0442\u043e\u0440\u043d\u0443\u044e \u043a\u0430\u0440\u0442\u0443 \u0442\u043e\u0440\u0433\u043e\u0432\u043e\u0433\u043e \u0446\u0435\u043d\u0442\u0440\u0430 \u0432 svg \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0435\u0451 \u0434\u0430\u043d\u043d\u044b\u043c\u0438. \u041a\u0440\u0430\u0441\u0438\u0432\u043e, \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e, \u0431\u044b\u0441\u0442\u0440\u043e. \u0414\u0430\u0436\u0435 \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u0430 jVectorMap.<\/p>\n<p>  \u0422\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0442 \u0432\u0435\u043a\u0442\u043e\u0440\u043d\u044b\u0445 \u043a\u0430\u0440\u0442 \u043d\u0443\u0436\u043d\u044b\u0445 \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445 \u0446\u0435\u043d\u0442\u0440\u043e\u0432 \u043d\u0435\u0442, \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438, \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0432\u043b\u0430\u0434\u0435\u043b\u044c\u0446\u0430\u043c\u0438 \u0446\u0435\u043d\u0442\u0440\u043e\u0432. \u0410\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u0440\u0430\u0437\u043d\u044b\u0435 \u043f\u043e \u0441\u0442\u0438\u043b\u0438\u0441\u0442\u0438\u043a\u0435 \u0438 \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e. \u0410 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0446\u0435\u043d\u0442\u0440\u043e\u0432 (\u043f\u043e\u0440\u044f\u0434\u043a\u0430 300) \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u0434\u0451\u0448\u0435\u0432\u043e. \u0414\u0430 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u0442\u043e\u0440\u0433\u043e\u0432\u044b\u0445 \u0446\u0435\u043d\u0442\u0440\u043e\u0432 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b.<\/p>\n<p>  \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u044b\u043b\u043e \u0440\u0435\u0448\u0435\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c HTML5 canvas \u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 \u043a\u0430\u0440\u0442\u044b, \u0438 \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<h4>\u0412\u044b\u0431\u043e\u0440 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430<\/h4>\n<p>  \u0420\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0441 canvas API \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e, \u043d\u043e \u0443\u0436\u0435 \u043f\u043e\u043d\u0430\u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043d\u0430 \u043a\u0443\u0447\u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b. \u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0443 \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435:  <\/p>\n<ol>\n<li>\u041e\u0431\u044a\u0435\u043a\u0442\u043d\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u043e\u0432\u0435\u0440\u0445 canvas API.<\/li>\n<li>\u0421\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443.<\/li>\n<li>\u0418\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c:<br \/> \n<ul>\n<li>\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 \u043a\u0430\u0440\u0442\u044b,<\/li>\n<li>\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u043f\u043e \u043a\u0430\u0440\u0442\u0435.<\/li>\n<\/ul>\n<\/li>\n<li>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430\/\u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u0440\u0430\u0437\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432.<\/li>\n<li>\u041d\u0430\u043b\u0438\u0447\u0438\u0435 \u0434\u0435\u0442\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439.<\/li>\n<li>\u0412\u044b\u0441\u043e\u043a\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438.<\/li>\n<\/ol>\n<p>  \u041f\u043e\u0434 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u0435 \u043f\u043e\u043f\u0430\u043b\u0438 <a href=\"http:\/\/fabricjs.com\/\">fabric.js<\/a>, <a href=\"http:\/\/www.createjs.com\/EaselJS\">EaselJS<\/a>, <a href=\"http:\/\/raphaeljs.com\/\">Rapha\u00ebl<\/a>, <a href=\"http:\/\/paperjs.org\/\">Paper.js<\/a> \u0438 <a href=\"http:\/\/processingjs.org\/\">Processing.js<\/a>. <br \/>  \u0412\u0441\u0435\u043c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u044f\u0435\u0442 fabric.js. \u0423\u0447\u0438\u0442\u044b\u0432\u0430\u044f \u0438\u043c\u0435\u044e\u0449\u0438\u0439\u0441\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043e\u043f\u044b\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0438\u043c, \u0431\u044b\u043b\u043e \u0440\u0435\u0448\u0435\u043d\u043e \u0432\u0437\u044f\u0442\u044c \u0435\u0433\u043e \u0437\u0430 \u043e\u0441\u043d\u043e\u0432\u0443. \u0414\u0430\u043b\u0435\u0435 \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0430\u0441\u044c \u0432\u0435\u0440\u0441\u0438\u044f 1.4.4.<\/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-253124","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/253124","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=253124"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/253124\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=253124"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=253124"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=253124"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}