内容
- はじめに
 - 値、タイプ、および演算子
 - プログラム構成
 - 機能
 - データ構造:オブジェクトと配列
 - 高階関数
 - オブジェクトの秘密の生活
 - プロジェクト:電子生活
 - 検索とエラー処理
 - 正規表現
 - モジュール
 - プロジェクト:プログラミング言語
 - JavaScriptとブラウザー
 - ドキュメントオブジェクトモデル
 - イベント処理
 - プロジェクト:プラットフォームゲーム
 - キャンバスに描く
 - HTTP
 - フォームとフォームフィールド
 - プロジェクト:ペイント
 - Node.js
 - プロジェクト:経験共有ウェブサイト
 - コードのサンドボックス
 
さまざまな色を見ています。 空白のキャンバスを見ます。 それから、詩が生まれる言葉、音楽が生まれる音符として色を適用しようとします。
ジョアン・ミロ
前の章の資料は、単純なWebアプリケーションを作成するために必要なすべてを提供します。 それが私たちのすることです。
アプリケーションは、Microsoft Paintに似たブラウザ描画プログラムになります。 その助けを借りて、画像でファイルを開き、マウスでそれらをペイントし、それらを保存することが可能になります。 これは次のようになります。
      簡単な描画プログラム
コンピューターにクールドロー。 材料、スキル、才能について心配する必要はありません。 あなたはちょうどそれを取り、あなたはがらくたを始めます。
実装
プログラムインターフェイスの上部に大きな要素が表示されます
 ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; } 
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; } 
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      , .
– createPaint, DOM, . , controls, .
var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      , –
.        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); }; 
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); }; 
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1> 
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
 ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
       ,      .    ,     ,      .     ,   ,    .. 
      
        
        
        
      
     
      
        
        
        
      
          "mousedown"  ,   ,   .  , ,    "mousemove",      ,           . 
      
        
        
        
      
     
      
        
        
        
      
             .         fillStyle, strokeStyle,  lineWidth     . 
      
        
        
        
      
     
      
        
        
        
      
           .    file,       .   URL     . 
      
        
        
        
      
     
      
        
        
        
      
        .  save       .    ,       .   ,   . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      DOM 
      
        
        
        
      
           30  DOM.   -  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM  HTML.     HTML    –   DOM        ,    -   .       querySelector   ,     DOM  . 
      
        
        
        
      
     
      
        
        
        
      
          DOM      JavaScript,   .       DOM   JavaScript.      13,      DOM  .      ,    . 
      
        
        
        
      
     
      
        
        
        
      
       –    elt   13.        ,     ,  ,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function elt(name, attributes) { var node = document.createElement(name); if (attributes) { for (var attr in attributes) if (attributes.hasOwnProperty(attr)) node.setAttribute(attr, attributes[attr]); } for (var i = 2; i < arguments.length; i++) { var child = arguments[i]; if (typeof child == "string") child = document.createTextNode(child); node.appendChild(child); } return node; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,       . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        –  createPaint,      DOM,     .      ,    controls,           . 
      
        
        
        
      
     
      
        
        
        
      
     var controls = Object.create(null); function createPaint(parent) { var canvas = elt("canvas", {width: 500, height: 300}); var cx = canvas.getContext("2d"); var toolbar = elt("div", {class: "toolbar"}); for (var name in controls) toolbar.appendChild(controls[name](cx)); var panel = elt("div", {class: "picturepanel"}, canvas); parent.appendChild(elt("div", null, panel, toolbar)); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
               ,    –   .        –    ,   (  fillStyle)    (  lineWidth). 
      
        
        
        
      
     
      
        
        
        
      
              ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       
      
        
        
        
      
       ,    –  ,    .      controls,        ,           ,       .       ,          . 
      
        
        
        
      
     
      
        
        
        
      
     var tools = Object.create(null); controls.tool = function(cx) { var select = elt("select"); for (var name in tools) select.appendChild(elt("option", null, name)); cx.canvas.addEventListener("mousedown", function(event) { if (event.which == 1) { tools[select.value](event, cx); event.preventDefault(); } }); return elt("span", null, "Tool: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       tool        ,    "mousedown"          ,    event  context.    preventDefault,          . 
      
        
        
        
      
     
      
        
        
        
      
        – ,     .   ,           .    13   getBoundingClientRect     .  ,   ,     .    clientX  clientY      ,                . 
      
        
        
        
      
     
      
        
        
        
      
     function relativePos(event, element) { var rect = element.getBoundingClientRect(); return {x: Math.floor(event.clientX - rect.left), y: Math.floor(event.clientY - rect.top)}; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           "mousemove",    .  trackDrag       . 
      
        
        
        
      
     
      
        
        
        
      
     function trackDrag(onMove, onEnd) { function end(event) { removeEventListener("mousemove", onMove); removeEventListener("mouseup", end); if (onEnd) onEnd(event); } addEventListener("mousemove", onMove); addEventListener("mouseup", end); }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        .  – ,      "mousemove",   – ,     .      . 
      
        
        
        
      
     
      
        
        
        
      
               . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Line = function(event, cx, onEnd) { cx.lineCap = "round"; var pos = relativePos(event, cx.canvas); trackDrag(function(event) { cx.beginPath(); cx.moveTo(pos.x, pos.y); pos = relativePos(event, cx.canvas); cx.lineTo(pos.x, pos.y); cx.stroke(); }, onEnd); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          lineCap  “round”, -      ,   ,     .     ,      .     ,      ,     lineCap  . 
      
        
        
        
      
     
      
        
        
        
      
     ,    "mousemove",  ,   ,         ,      strokeStyle  lineWidth,     . 
      
        
        
        
      
     
      
        
        
        
      
      onEnd   ,  trackDrag.        ,        undefined,       .        ,  erase,      . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Erase = function(event, cx) { cx.globalCompositeOperation = "destination-out"; tools.Line(event, cx, function() { cx.globalCompositeOperation = "source-over"; }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      globalCompositeOperation   ,        .  ,   "source-over",  ,  ,  ,   .   ,    ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
      “erase”  globalCompositeOperation  "destination-out",    ,     . 
      
        
        
        
      
     
      
        
        
        
      
             .          (     strokeStyle  lineWidth  ),   . ,   ,  . 
      
        
        
        
      
     
      
        
        
        
      
         
      
        
        
        
      
     ,              ,      . 
      
        
        
        
      
     
      
        
        
        
      
       18      .        .          ,            .    - .   - "date", "email", "url"  "number".      .      – “text”,     ,     ,       . ,   ,       ,       ,       . 
      
        
        
        
      
     
      
        
        
        
      
     controls.color = function(cx) { var input = elt("input", {type: "color"}); input.addEventListener("change", function() { cx.fillStyle = input.value; cx.strokeStyle = input.value; }); return elt("span", null, "Color: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         color     fillStyle  strokeStyle    . 
      
        
        
        
      
     
      
        
        
        
      
          . 
      
        
        
        
      
     
      
        
        
        
      
     controls.brushSize = function(cx) { var select = elt("select"); var sizes = [1, 2, 3, 5, 8, 12, 25, 35, 50, 75, 100]; sizes.forEach(function(size) { select.appendChild(elt("option", {value: size}, size + " pixels")); }); select.addEventListener("change", function() { cx.lineWidth = select.value; }); return elt("span", null, "Brush size: ", select); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
           ,    ,    lineWidth    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
      ,     ,      URL  .     http:  https:, URL      ,      .  URL  ,   HTML : 
      
        
        
        
      
     
      
        
        
        
      
     data:text/html,<h1 style="color:red">Hello!</h1>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      URL    , , ,       .           ,  ,      - . 
      
        
        
        
      
     
      
        
        
        
      
           toDataURL,   URL  ,        .            .        URL   .       ,      href  ,            . 
      
        
        
        
      
     
      
        
        
        
      
     controls.save = function(cx) { var link = elt("a", {href: "/"}, "Save"); function update() { try { link.href = cx.canvas.toDataURL(); } catch (e) { if (e instanceof SecurityError) link.href = "javascript:alert(" + JSON.stringify("Can't save: " + e.toString()) + ")"; else throw e; } } link.addEventListener("mouseover", update); link.addEventListener("focus", update); return link; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      ,          ,       ,      ,     . 
      
        
        
        
      
     
      
        
        
        
      
         ,      URL  ,    .       . 
      
        
        
        
      
     
      
        
        
        
      
               .     URL   ,      ,       (.  17),    ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
            (   ).        ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,  ,  ,    ,     «».  ,  URL  ,     «» .    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         try/catch   update   .   «»,  toDataURL  ,   SecurityError.           URL   javascript:.     ,   ,     ,   . 
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
                  URL.    ,      URL     . 
      
        
        
        
      
     
      
        
        
        
      
     function loadImageURL(cx, url) { var image = document.createElement("img"); image.addEventListener("load", function() { var color = cx.fillStyle, size = cx.lineWidth; cx.canvas.width = image.width; cx.canvas.height = image.height; cx.drawImage(image, 0, 0); cx.fillStyle = color; cx.strokeStyle = color; cx.lineWidth = size; }); image.src = url; }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
         ,    . -          (fillStyle  lineWidth),              . 
      
        
        
        
      
     
      
        
        
        
      
             FileReader   18.     readAsText        readAsDataURL –   ,   .   ,   ,  URL  ,     loadImageURL    . 
      
        
        
        
      
     
      
        
        
        
      
     controls.openFile = function(cx) { var input = elt("input", {type: "file"}); input.addEventListener("change", function() { if (input.files.length == 0) return; var reader = new FileReader(); reader.addEventListener("load", function() { loadImageURL(cx, reader.result); }); reader.readAsDataURL(input.files[0]); }); return elt("div", null, "Open file: ", input); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
        URL  .       ,       URL,        “change”.         ,     –    Enter,     load. 
      
        
        
        
      
     
      
        
        
        
      
     controls.openURL = function(cx) { var input = elt("input", {type: "text"}); var form = elt("form", null, "Open URL: ", input, elt("button", {type: "submit"}, "load")); form.addEventListener("submit", function(event) { event.preventDefault(); loadImageURL(cx, form.querySelector("input").value); }); return form; };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
          ,   ,      . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            ,    ,     . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Text = function(event, cx) { var text = prompt("Text:", ""); if (text) { var pos = relativePos(event, cx.canvas); cx.font = Math.max(7, cx.lineWidth) + "px sans-serif"; cx.fillText(text, pos.x, pos.y); } };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
              ,        sans-serif   ,    .   – 7 ,      . 
      
        
        
        
      
     
      
        
        
        
      
          - – “”.      ,    ,            . 
      
        
        
        
      
     
      
        
        
        
      
     tools.Spray = function(event, cx) { var radius = cx.lineWidth / 2; var area = radius * radius * Math.PI; var dotsPerTick = Math.ceil(area / 30); var currentPos = relativePos(event, cx.canvas); var spray = setInterval(function() { for (var i = 0; i < dotsPerTick; i++) { var offset = randomPointInRadius(radius); cx.fillRect(currentPos.x + offset.x, currentPos.y + offset.y, 1, 1); } }, 25); trackDrag(function(event) { currentPos = relativePos(event, cx.canvas); }, function() { clearInterval(spray); }); };
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       setInterval      25 ,    .  trackDrag   ,  currentPos     ,       . 
      
        
        
        
      
     
      
        
        
        
      
      ,         ,           30.         randomPointInRadius. 
      
        
        
        
      
     
      
        
        
        
      
     function randomPointInRadius(radius) { for (;;) { var x = Math.random() * 2 - 1; var y = Math.random() * 2 - 1; if (x * x + y * y <= 1) return {x: x * radius, y: y * radius}; } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
            (-1,-1)  (1,1).   ,  ,         1.    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .       ,        Math.sin  Math.cos   .            .    ,    ,   . 
      
        
        
        
      
     
      
        
        
        
      
          .    . 
      
        
        
        
      
     
      
        
        
        
      
     <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
            .    . 
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
       Rectangle,   (.  fillRect   16)  .      ,     ,    ,    . ,         . 
      
        
        
        
      
     
      
        
        
        
      
       ,  ,        .           ,       ,    ? 
      
        
        
        
      
     
      
        
        
        
      
       ,    position: absolute,      13.   ,      .  pageX  pageY          ,      left, top, width  height. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools.Rectangle = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
       
      
        
        
        
      
          –  ,        ,    .   . 
      
        
        
        
      
     
      
        
        
        
      
            .  toDataURL    ,       URL   .       getImageData,          width, height  data.   data     0  255,        - red, green, blue  alpha (). 
      
        
        
        
      
     
      
        
        
        
      
            ,  ,    (  –  ),   ,      . 
      
        
        
        
      
     
      
        
        
        
      
     function pixelAt(cx, x, y) { var data = cx.getImageData(x, y, 1, 1); console.log(data.data); } var canvas = document.createElement("canvas"); var cx = canvas.getContext("2d"); pixelAt(cx, 10, 10); // → [0, 0, 0, 0] cx.fillStyle = "red"; cx.fillRect(10, 10, 1, 1); pixelAt(cx, 10, 10); // → [255, 0, 0, 255]
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      getImageData     x  y,    ,      . 
      
        
        
        
      
     
      
        
        
        
      
         ,         .        color   .  ,  fillStyle  strokeStyle    ,   . 
      
        
        
        
      
     
      
        
        
        
      
     ,      ,   CSS,    rgb(R, G, B),      15. 
      
        
        
        
      
     
      
        
        
        
      
      getImageData    ,   toDataURL –   ,      ,    .   try/catch        alert. 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Pick color"] = function(event, cx) { // Your code here. }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      
        
        
        
      
     
      
        
        
        
      
      
      
        
        
        
      
        ,  ,        . ,           ,   ,     -   . 
      
        
        
        
      
     
      
        
        
        
      
                  ,    .       ,      ,      ,         (   ),    ,     . 
      
        
        
        
      
     
      
        
        
        
      
         , ,       : 
      
        
        
        
      
     
      
        
        
        
      
     
 
      
        
        
        
      
     
      
        
        
        
      
              ,   ,      ,   . 
      
        
        
        
      
     
      
        
        
        
      
        getImageData    .  ,       ,          .           7,  ,      .       (x,y)    (x + y × width) × 4 
      
        
        
        
      
     
      
        
        
        
      
          (),          () . 
      
        
        
        
      
     
      
        
        
        
      
                , ,   ,       .         .      -      ,    9.        ,    ,       ,    ,    . 
      
        
        
        
      
     
      
        
        
        
      
          .      ,       .  ,  ,    . 
      
        
        
        
      
     
      
        
        
        
      
           fillRect,   -  ,  ,     . 
      
        
        
        
      
     
      
        
        
        
      
     <script> tools["Flood fill"] = function(event, cx) { //   }; </script> <link rel="stylesheet" href="css/paint.css"> <body> <script>createPaint(document.body);</script> </body>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     