【Angular】パワポみたいにオブジェクトをぐりぐり動かすWEB画面の作り方

#はじめに
丸や四角などのオブジェクトをぐりぐり動かせるWEBページをAngularで作る方法を説明しています。
公式ドキュメントにはAngular用のソースコードが少ないので参考になればと思います。


#前提
- Angularがインストールされていること

#概要
- Konvaのインストール
- Konvaでの実装方法

#Konvaとは
JavaScriptのライブラリです。
そのためJavaScriptベースのフレームワーク（React、Vue.js、Angularなど）で使用することが出来ます。
表や図形・文字・写真などのオブジェクト、アニメーションを簡単に扱うことができます。

Konva公式サイト
https://konvajs.org/

#AngularでKonvaを使うならng2-konvaをインストールする
ng2-konvaとはAngularで使う際に使用するライブラリです。
短くわかりやすいソースコードを書くことができます。
公式からもng2-konvaでの実装方法が記載されています。

ng2-konva
http://rafaelescala.com/ng2-konva/


#ということでng2-konvaをインストール
###インストールは以下のコマンドを入力するだけ
**npm install konva ng2-konva --save**

###app.module.tsにng2-konvaを設定する

```\my-app\src\app\app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';
import { KonvatestComponent } from './konvatest/konvatest.component';
import { AppRoutingModule } from './app-routing.module';
import { KonvaModule } from "ng2-konva"; //これを追加

@NgModule({
  declarations: [
    AppComponent,
    KonvatestComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    KonvaModule, //これを追加
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
```

以上でkonvaを使えるようになりました。

#色んなオブジェクトを紹介
以下のようなオブジェクトや文字を簡単に作成することができます。
文字も含め全部ドラッグで動かせます。

![konva画面](https://github.com/study-for-ryouta/items/blob/master/konva%E7%94%BB%E9%9D%A2_1.PNG?raw=true)

```\my-app\src\app\konvatest\konvatest.component.html
<section>
    <ko-stage [config]="configStage">
        <ko-layer>
            <ko-circle [config]="configCircle"></ko-circle> <!--丸-->
            <ko-rect [config]="configRect"></ko-rect> <!--四角-->
            <ko-ellipse [config]="configEllipse"></ko-ellipse> <!--楕円-->
            <ko-line [config]="configLine"></ko-line> <!--線-->
            <ko-image [config]="configImage"></ko-image> <!--画像-->
            <ko-text [config]="configText"></ko-text> <!--文字-->
            <ko-text-path [config]="configTextpath"></ko-text-path> <!--ぐにゃぐにゃ文字-->
            <ko-star [config]="configStar"></ko-star> <!--星-->
            <ko-regular-polygon [config]="configRegularPolygon"></ko-regular-polygon> <!--ポリゴン-->
            <ko-shape [config]="configShape"></ko-shape> <!--カスタムシェープ-->
        </ko-layer>
    </ko-stage>
    <br>
</section>
```


```\my-app\src\app\konvatest\konvatest.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { KonvaComponent } from 'ng2-konva';
import { of, Observable, BehaviorSubject } from "rxjs";

let ng: any;

@Component({
  selector: 'app-konvatest',
  templateUrl: './konvatest.component.html',
  styleUrls: ['./konvatest.component.scss']
})
export class KonvatestComponent implements OnInit {

  @ViewChild('tooltip') tooltip!: KonvaComponent;
  
  imageObj = new Image();

  constructor() {
  }

  ngOnInit() {
    this.imageObj.src ='/assets/image/flower.jpg';
  }

  // ステージ（オブジェクトを表示する土台部分）の設定
  public configStage = new BehaviorSubject({
    width: 1200,
    height: 500
  });

  // 丸の設定
  public configCircle: Observable<any> = of({
    x: 100,
    y: 100,
    radius: 50,
    fill: 'red',
    stroke: 'black',
    strokeWidth: 4,
    draggable: true,
  });

  // 四角の設定
  public configRect: Observable<any> = of({
    x: 200,
    y: 100,
    width: 50,
    height: 60,
    fill: 'red',
    stroke: 'black',
    strokeWidth: 5,
    draggable: true,
  });

  // 楕円の設定
  public configEllipse: Observable<any> = of({
    x: 350,
    y: 100,
    radiusX: 50,
    radiusY: 15,
    fill: 'yellow',
    stroke: 'black',
    strokeWidth: 4,
    draggable: true,
  });

  // 線の設定
  public configLine: Observable<any> = of({
    x: 100,
    y: 200,
    points: [5, 70, 140, 23, 250, 60, 300, 20],
    stroke: 'red',
    strokeWidth: 15,
    lineCap: 'round',
    lineJoin: 'round',
    draggable: true,
  });


  // 画像の設定
  public configImage: Observable<any> = of({
    x: 400,
    y: 100,
    image: this.imageObj,
    width: 100,
    height: 100,
    draggable: true,
  });

  // 文字の設定
  public configText: Observable<any> = of({
    x: 450,
    y: 200,
    text: 'Simple Text',
    fontSize: 30,
    fontFamily: 'Calibri',
    fill: 'green',
    draggable: true,
  });

  // ぐにゃぐにゃ文字の設定
  public configTextpath: Observable<any> = of({
    x: 500,
    y: 80,
    fill: '#333',
    fontSize: 16,
    fontFamily: 'Arial',
    text:"All the world's a stage, and all the men and women merely players.",
    data: 'M10,10 C0,0 10,150 100,100 S300,150 5.0.300',
    draggable: true,
  });


  // 星の設定
  public configStar: Observable<any> = of({
    x: 750,
    y: 100,
    numPoints: 5,
    innerRadius: 40,
    outerRadius: 70,
    fill: 'yellow',
    stroke: 'black',
    strokeWidth: 4,
    draggable: true,
  });

  // ラベル文字の設定
  public configLabel: Observable<any> = of({
    x: 750,
    y: 100,
    opacity: 0.75,
    draggable: true,
  }); 
  
  // ポリゴンの設定
  public configRegularPolygon: Observable<any> = of({
    x:900,
    y: 100,
    sides: 6,
    radius: 70,
    fill: 'red',
    stroke: 'black',
    strokeWidth: 10,
    draggable: true,
  });
  
  // カスタムの設定
   public configShape: Observable<any> = of({
    x:900,
    y: 40,
    sceneFunc: function(context: any) {
      context.beginPath();
      context.moveTo(20, 50);
      context.lineTo(220, 80);
      context.quadraticCurveTo(150, 100, 260, 170);
      context.closePath();
 
      // special Konva.js method
      context.fillStrokeShape(this);
    },
    fill: '#00D2FF',
    stroke: 'black',
    strokeWidth: 4,
    draggable: true,
  });
}

```

#終わりに
ng2-konvaの使い方は公式サイトには部分的にしかないためもう少し複雑なことをしようとすると少し難しいです。
konvaでの実装方法をみて、ng2-konvaでうまいことこんな風にやればいいかなーって感じで実装する必要があります。
アプリっぽいものができたら共有します。