56324


**前提**  
アップロードか画像URLから画像を読み込み、表示し、画像にお絵描きができるツールを作っています。

[動作サンプル](https://jsbin.com/vokohexoxe/1/edit?html,js,output)

表示された画像をクリックするとパスを打つことができ、パスを3点以上打ってから1点目を打つとパスが閉じます。  
パスを閉じた後の次のクリックは、リセットされ1点目になります。

**問題点**  
リセットボタンを押すと画像が消えフォームの中身もクリアされますが、パスがクリアされません。  
パスを打った後にリセットボタンを押し再度画像を読み込むと、リセット前に打ったパスが復活します。  
なので、リセットボタンによってパスもクリアできるようにしたいです。

**使用ライブラリ**  
・jQuery  
・Paper.js

**ソースコード**

[code]

    $(function () {
      
      //リセットボタン
      $('#close').click(function () {
        $('#view').fadeOut();
        $('#url')[0].value = '';
        $('#file')[0].value = '';
        $('#pen').value = '';
      });
      
      $('#url').change(function () {
        $('#view').fadeOut(1);
        $('#file')[0].value = '';
        $('#view').fadeIn();
        input(this.value);
      });
      $('#file').change(function () {
        $('#view').fadeOut(1);
        $('#url')[0].value = '';
        $('#view').fadeIn();
        var fr = new FileReader();
        fr.onload = function (e) {
          input(e.target.result);
        };
        fr.readAsDataURL(this.files[0]);
      });
      function input(e) {
        var img = new Image();
        img.onload = draw;
        img.src = e;
      }
      function draw(e) {
        var img = e.target;
        var imgcnv = $('#img');
        var imgH = 800;
        var imgW = img.naturalWidth * imgH / img.naturalHeight;
        imgcnv.attr('width', imgW);
        imgcnv.attr('height', imgH);
        var ctx = imgcnv[0].getContext('2d');
        ctx.drawImage(img, 0, 0, imgW, imgH);
        $('#img').width('100%');
        $('#img').height('100%');
        var penW = $('#img').width();
        var penH = $('#img').height();
        var pencnv = $('#pen');
        pencnv.attr('width', penW);
        pencnv.attr('height', penH);
        }
      });
[/code]

[code]

    #view {
      display: none;
    }
    #draw {
      position: relative;
    }
    #img {
      border: 3px solid black;
    }
    #pen {
      position: absolute;
      cursor: crosshair;
      top: 0;
      left: 0;
    }
[/code]

[code]

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
      <script
      src="https://code.jquery.com/jquery-3.4.1.js"
      integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
      crossorigin="anonymous"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.2/paper-full.js"></script>
    </head>
    <body>
      <input id="url" type="text" placeholder="画像URLを貼付">
      <input id="file" type="file" accept="image/*">
      <div id="view">
        <div id="draw">
          <canvas id="img"></canvas>
          <script type="text/paperscript" canvas="pen">
            var hitOptions = Object.seal({
              segments: true,
              stroke: false,
              fill: false,
              tolerance: 10
            });
            var path = null;
            function onMouseDown(e) {
              var hitSeg = project.hitTest(e.point.clone(), hitOptions);
              var isClose = path != null
                  && path.segments.length > 2
                  && hitSeg
                  && hitSeg.type === 'segment'
                  && hitSeg.item.firstSegment === hitSeg.segment;
              if (isClose) {
                path.closed = true;
                path = null;
                return false;
              }
              if (path == null) {
                path = new Path();
                path.selected = true;
                path.add(e.point);
              }
              else {
                path.add(e.point);
              }
            } 
          </script>
          <canvas id="pen" width="720" height="600"></canvas>
        </div>
        <button id="close">リセット</button>
      </div>
    </body>
    </html>
[/code]

**試したこと**  
paper.js及びpaperscriptの有無でパスを打てる機能のオンオフが切り替えられると考え、

[code]

    <script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.2/paper-full.js"></script>
    
    <script type="text/paperscript" canvas="pen">
    
[/code]

画像を読み込んだタイミング上記2つのタグをで生成し、リセットボタンで上記2つのタグを消す、という処理をしてみました。  
しかし、生成したタグではpaperscriptが機能せず、パスが打てませんでした。


CC BY-SA 4.0
2019-07-02T02:31:37.033
56308
2019-07-02T11:09:48.947
32275
question
javascript html css
リセットボタンでcanvasに描いた線を消したい。


※ Paper.js
は今始めて知ったものなので、間違っている箇所があるかもしれませんが、一応質問文の問題点が改善されたと思われるので、回答を残しておきます。

* * *

まず、リファレンスによれば、Path
アイテムはアクティブなレイヤーの最上位に配置されます[[1]](http://paperjs.org/tutorials/project-
items/project-hierarchy/#active-layer)。

> ## Active Layer[[1]](http://paperjs.org/tutorials/project-items/project-
> hierarchy/#active-layer)
>
> Each Paper.js Project starts out with one Layer which can be accessed
> through project.activeLayer. All newly created items are automatically added
> as a child of the layer which is currently active.

また、`Layer` クラスは `removeChildren` メソッドを実装しており、

> ### Hierarchy
> Operations[[2]](http://paperjs.org/reference/layer/#removechildren)
>
> **`removeChildren()`**  
>  Removes all of the item’s children (if any).
>
> **Returns:**  
>  Array of Item objects — an array containing the removed items

`Item` クラスを継承した `Group`
クラスを継承している[[3]](http://paperjs.org/reference/layer/)ため、`hasChildren`
メソッドが使用出来ます[[4]](http://paperjs.org/reference/item/#haschildren)。

> # Layer[[3]](http://paperjs.org/reference/layer/)
>
> Extends `Item`, `Group`
>
> The Layer item represents a layer in a Paper.js project.
>
> The layer which is currently active can be accessed through
> `project.activeLayer`. An array of all layers in a project can be accessed
> through `project.layers`.
>
> * * *
>
> # Item[[4]](http://paperjs.org/reference/item/#haschildren)
>
> ## Hierarchy Tests
>
> **`hasChildren()`**  
>  Checks if the item contains any children items.
>
> **Returns:**  
>  Boolean — true it has one or more children, false otherwise

そして、paper オブジェクトのスコープは `PaperScope` クラスの `install`
メソッドによってグローバルに注入出来ます[[5]](http://paperjs.org/reference/paperscope/#install-
scope)。

> # PaperScope[[5]](http://paperjs.org/reference/paperscope/#install-scope)
>
> ## Methods
>
> **`install(scope)`**  
>  Injects the paper scope into any other given scope. Can be used for example
> to inject the currently active PaperScope into the window’s global scope, to
> emulate PaperScript-style globally accessible Paper classes and objects.
>
> **Please note:** Using this method may override native constructors (e.g.
> Path). This may cause problems when using Paper.js in conjunction with other
> libraries that rely on these constructors. Keep the library scoped if you
> encounter issues caused by this.
>
> **Parameters:**  
>  scope:
>
> **Example:**
[code]

>     paper.install(window);
>  
[/code]

* * *

以上を用いて、以下のように JavaScript を変更することで、質問文の問題点は改善します。

[code]

    $(function() {
      //リセットボタン
      $('#reset').click(function() {
        $('#view').fadeOut();
        $('#url')[0].value = '';
        $('#file')[0].value = '';
        $('#pen').value = '';
        paper.project.activeLayer.removeChildren();
      });
    
      $('#url').change(function() {
        $('#view').fadeOut(1);
        $('#file')[0].value = '';
        $('#view').fadeIn();
        input(this.value);
      });
      $('#file').change(function() {
        $('#view').fadeOut(1);
        $('#url')[0].value = '';
        $('#view').fadeIn();
        var fr = new FileReader();
        fr.onload = function(e) {
          input(e.target.result);
        };
        fr.readAsDataURL(this.files[0]);
      });
    
      function input(e) {
        var img = new Image();
        img.onload = draw;
        img.src = e;
      }
    
      function draw(e) {
        var img = e.target;
        var imgcnv = $('#img');
        var imgH = 800;
        var imgW = img.naturalWidth * imgH / img.naturalHeight;
        imgcnv.attr('width', imgW);
        imgcnv.attr('height', imgH);
        var ctx = imgcnv[0].getContext('2d');
        ctx.drawImage(img, 0, 0, imgW, imgH);
        $('#img').width('100%');
        $('#img').height('100%');
        var penW = $('#img').width();
        var penH = $('#img').height();
        var pencnv = $('#pen');
        pencnv.attr('width', penW);
        pencnv.attr('height', penH);
      }
    });
[/code]

[code]

    #view {
      display: none;
    }
    
    #draw {
      position: relative;
    }
    
    #img {
      border: 3px solid black;
    }
    
    #pen {
      position: absolute;
      cursor: crosshair;
      top: 0;
      left: 0;
    }
[/code]

[code]

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
      <script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.2/paper-full.js"></script>
    </head>
    
    <body>
      <input id="url" type="text" placeholder="画像URLを貼付">
      <input id="file" type="file" accept="image/*">
      <div id="view">
        <div id="draw">
          <canvas id="img"></canvas>
          <script type="text/paperscript" canvas="pen">
          paper.install(window);
          var hitOptions = Object.seal({
            segments: true,
            stroke: false,
            fill: false,
            tolerance: 10
          });
          var path = null;
    
          function onMouseDown(e) {
            var hitSeg = project.hitTest(e.point.clone(), hitOptions);
            var isClose = path != null && path.segments.length >
              2 && hitSeg && hitSeg.type === 'segment' && hitSeg.item.firstSegment === hitSeg.segment;
            if (isClose) {
              path.closed = true;
              path = null;
              return false;
            }
            if (path == null || !paper.project.activeLayer.hasChildren()) {
              path = new Path();
              path.selected = true;
              path.add(e.point);
            } else {
              path.add(e.point);
            }
          }
          </script>
          <canvas id="pen" width="720" height="600"></canvas>
        </div>
        <button id="reset">リセット</button>
      </div>
    </body>
    
    </html>
[/code]


CC BY-SA 4.0
2019-07-02T11:09:48.947
56324
2019-07-02T11:09:48.947
32986
56308
answer