質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

699閲覧

paper.jsで図形を描く際、3点以上クリックしたのち、1点目をクリックすることでパスを閉じたい

whoiwhoi

総合スコア48

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2019/03/25 09:15

編集2019/03/25 09:26

前提・実現したいこと

canvas上をクリックすることで点を記憶し、点と点の間を直線で結ぶ機能をpaper.jsで施しています。
Illustratorで言うところのペンツールのようなものです。
以下リンク動作サンプルです。
サンプル

3点以上クリックしたのちに1点目をクリックすることでパスを閉じ、次のクリックは1点目から。
という機能にしたいです。

発生している問題

3点以上クリックしたのち1点目をクリックしてもパスを閉じることができず、点を無限に増やすことができる状態です。
【例:三角形を作る場合】
■現状:4点目で1点目をクリック→次の点は5点目
■理想:4点目で1点目をクリック→パス閉じる→次の点は1点目

該当のソースコード

paperscript

1<script type="text/paperscript" canvas="canvas"> 2 var path = new Path(); 3 path.strokeColor = "red"; 4 path.strokeWidth = 2; 5 path.selected = true; 6 function onMouseDown(e) { 7 path.add(e.point); 8 } 9 </script>

試したこと

paperscript

1<script type="text/paperscript" canvas="canvas"> 2 var path = new Path(); 3 path.strokeColor = "red"; 4 path.strokeWidth = 2; 5 path.selected = true; 6 function onMouseDown(e) { 7 path.add(e.point); 8 //1点目を打つと発火 9 function isFirst() { 10   //パスを閉じる 11   path.closePath(); 12   //リセット 13 14 } 15 } 16 </script>

paper.jsの公式サイトのリファレンスに
isFirst()
最初のセグメントかどうかを判定すると思われるメソッドがありました。
isFirst()の判定の結果がtrueになればパスを閉じる、というイベントができるかもしれないと希望を持ってスクリプトを書いてみましたが、上記スクリプトは全く機能しませんでした。
また、パスを閉じる→次のクリックは1点目、を実装できそうなプロパティ等は見当たりませんでした。

補足情報

paper.jsは外部ファイルではなく、paperscriptで記述しています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

まずはポイントだけ。

  1. 3点以上の判定はpath.segmentsを数えれば良いです。3つ以上あるかチェック。
  2. マウス押下時、起点のポイントかどうかは、マウスポイントとprojectのヒットテストの結果オブジェクトを元に、その型をチェック。segmentかどうかチェック。

http://paperjs.org/reference/hitresult/
3. ヒットしたオブジェクトのfirstSegmentとヒットしたsegmentが同じかどうか

上記条件が揃った場合、pathを閉じます。

片手間で書いたのでざっくりなコードですが、こうやればとりあえずできます。

js

1/** ヒット判定オプション */ 2var hitOptions = Object.seal( { 3 segments: true, 4 stroke: false, 5 fill: false, 6 tolerance: 10 7} ); 8 9var path = null; 10 11function onMouseDown( e ) 12{ 13 var hitSeg = project.hitTest( e.point.clone(), hitOptions ); 14 var isClose = path != null 15 && path.segments.length > 2 16 && hitSeg 17 && hitSeg.type === 'segment' 18 && hitSeg.item.firstSegment === hitSeg.segment; 19 if ( isClose ) 20 { 21 path.closed = true; 22 path = null; 23 return false; 24 } 25 26 27 if ( path == null ) 28 { 29 path = new Path(); 30 path.strokeColor = "red"; 31 path.strokeWidth = 2; 32 path.selected = true; 33 path.add( e.point ); 34 } 35 else 36 { 37 path.add( e.point ); 38 } 39}

あとはsegmentをマウスオーバーでわかりやすく、といった視覚効果等も実装できればより良いでしょう。

追記
isFirst()が効かないとのことですが、利用されているライブラリのバージョンが古そうです。
回答の作例はwhoiwhoiさんが示されたサンプル(jsbin.com)で利用されているバージョンでの回答です。

投稿2019/03/27 09:07

編集2019/03/27 09:26
so87

総合スコア764

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

whoiwhoi

2019/03/27 12:38

so87様 先日はpaper.jsを教えてくださりありがとうございました。 また当問題も解決していただきありがとうございます。 動作確認ができました。 ご教示いただいたスクリプトを一行一行反芻いたします。 ライブラリは下記CDNから、一番新しいと私が勝手に思った0.22を使用しました。 https://cdnjs.com/libraries/paper.js/0.12.0 試しに推奨されているとおぼしき0.12.0のpaper-full.jsに差し替えると、paperscriptそのものが機能しませんでした。 動作しないサンプル→ https://jsbin.com/vulelayeli/1/edit?html,js,output これはCDNかJS Binの問題かもしれません。 また、isFirst()が機能しなかったのは当たり判定の許容値の設定をしていなかったからかもと、ご教示いただいたスクリプトを見て思いました。(tolerance: 10 ←これが許容値でしょうか)
so87

2019/03/28 01:07

0.22は現在のバージョニングになる以前のpaper.jsの最終バージョンだと思います。0.22からv0.1.0へと移行したものと推測されます。よって現在確認できる一番古いバージョンかと思われます。ソースコード自体にisFirstも見当たりません。 また、0.12.0のpaper-full.jsで機能しないとのことですが、確認したところ機能はしています。 ただし、paper.jsがcanvasを認識した時のサイズが[縦:0,横:0]となっていますので、paper.jsのインスタンス内でのprojectサイズが[縦:0,横:0]となっているのが、機能しないと判断された原因かと思います。 正しく動作させるならば、まずはキャンバスサイズを決定してからということになるのと、もうひとつ、現在svgを同じcanvasにdrawImageさせていますが、現行のpaper.jsではpaper.jsのレイヤーを使って切り分けるか、canvas自体をcssで2重に重ねて表示させるか、という仕様に変更する必要があります。 この辺りの仕様変更は、よりプログラマブルに機能性が分離した結果かと思います。 toleranceは許容値ですね。大変ありがたい機能です。 パスを閉じるまではマウスポインタまで動的にstrokeを追いかけて、起点segmentへの吸着!といったイラストレーターのpathツールのあの動作もいけるな~って想像が膨らみます。わたくし的にpaper.jsは神ライブラリのひとつだと思っています^^ ちなみに作例でObject.sealしているのは今回は特に意味ないです。普段の自分のコードでは定数オブジェクトはなるべくsealだったりfreezeさせて守っているというだけなので。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問