Processing.jsを用いる方法【Django】

※11/21現在作成途中（仮公開中）
DjangoでProcessing.jsとAjaxを用いたデータ通信の方法の紹介です。

環境
・Django 1.10
・Python 3

ファイル構成
・プロジェクト名： Ajax
・アプリケーション名：Ajax,Core

あらかじめプロジェクト・アプリの作成及び設定が完了前提とする。

----
1.事前設定
setting.pyに以下のコードを追加する。
今回はpde形式ファイル、js形式ファイルは、staticフォルダ内に保存する。

```/setting.py
MEDIA_ROOT = os.path.join('Core', 'static')
STATIC_ROOT = '/static/'
STATIC_URL = '/static/'
MEDIA_URL = '/static_site/'
```
----
2.モデル（データベーステーブル）作成
対象モデルは、座席だけとする。
座席モデルの要素は、ｘ座標、y座標。

```/models.py
from django.db import models
//座席モデル
class Seat(models.Model):
    x = models.IntegerField()
    y = models.IntegerField()
```
----

3.Django側の処理作成

```/views.py
from django.http import JsonResponse
from .models import *
from django.shortcuts importrender,redirect

//Top画面表示用関数
def get(request):
    return render(request,'Core/get.html')

//受信用Ajax関数
def get_v1_posts(request):
    if request.method == 'GET':
        d = {"nodes": [
            {"x":seat.x,"y":seat.y,"diameter":30,"name":1,} for seat in Seat.objects.filter()
            ]
        }
        return JsonResponse(d)

//更新用Ajax関数
def get_v2_posts(request):
    if request.method == 'GET':
        x_ = request.GET.get('x')
        y_ = request.GET.get('y')
        seat = Seat(x = x_,y = y_)
        seat.save()
        d = {
            "nodes": [
                {"x":seat.x,"y":seat.y,"diameter":30,"name":1,}
            ]
        }
        return JsonResponse(d)

//削除用Ajax関数
def get_v3_posts(request):
    if request.method == 'GET':
        x_ = int(request.GET.get('x'))
        y_ = int(request.GET.get('y'))
        deleteList = Seat.objects.filter(x__lte = x_+15,x__gte = x_-15,y__lte = y_+15,y__gte = y_-15)
        for seat in deleteList:
            seat.delete()
  
        d = {
            "nodes": [
               {"x":seat.x,"y":seat.y,"diameter":30,"name":1,} for seat in Seat.objects.filter()
            ]
        }
        return JsonResponse(d)
```


```/urls.py
from django.conf.urls import url
from .views import *
 
urlpatterns = [
    url(r'^get/$', get, name='get'),
    url(r'^get/v1/posts$', get_v1_posts, name='get_v1_posts'),
    url(r'^get/v2/posts$', get_v2_posts, name='get_v2_posts'),
    url(r'^get/v3/posts$', get_v3_posts, name='get_v3_posts'),
]
```
----
4.htmlページの作成

```/get.html
<html>
    <head>
      <meta charset="utf-8">
      <title>My Processing Page</title>
      <script type="text/javascript" charset="UTF-8" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
      <script type="text/javascript" charset="UTF-8" src="/static/djangoajax.js"></script>
      {% load staticfiles %}
      <script src= "{% static "processing.min.js" %}"></script>
<script type="text/javascript">

  // 取得したJSONオブジェクトを格納する配列
  var obj_array = new Array();
  var t = 0;
  // JSONを読込み
  $.ajax({
    url: '{% url "get_v1_posts" %}',
    type:'GET',
    data:{
        
        },
    dataType:'json',
    })
    .then(
      (data) => {
        jQuery.each( data.nodes, function(i) {
        // JSONから取得したオブジェクトを配列に格納
        obj_array[i] = data.nodes[i];
      });
      },
      () => {
            alert("読み込み失敗");
        }
      );
  var tId, pjs, cnt=0;
  // 文書全体が読み終わったら
  $(function(){
    // Processingが取得できるまで
    if (!pjs){
      // 100msごとにくりかえし
      tId=setInterval(function(){
        // Processingの貼ってあるCanvasを取得
        pjs = Processing.getInstanceById("pjsid");
        // 取得できたら
        if (pjs && obj_array){
          // 取得を中止
          clearInterval(tId);
          // Processingの関数を実行して、配列を送信
          pjs.addObjects(obj_array);
        }
      },100);
    }
  });
  function input(x,y){
    var obj_array = new Array();
    console.log("x:"+x,"y:"+y);

    $.ajax({
    url: '{%url "get_v2_posts" %}',
    type:'GET',
    data:{
        'x':x,
        'y':y,
        },
    dataType:'json',
    })
    .then(
      (data) => {
        jQuery.each( data.nodes, function(i) {
        // JSONから取得したオブジェクトを配列に格納
        obj_array[i] = data.nodes[i];
      });
      },
      () => {
            alert("読み込み失敗");
        }
      );
  
  var tId, pjs, cnt=0;
  // 文書全体が読み終わったら
  $(function(){
    // Processingが取得できるまで
    if (!pjs){
      // 100msごとにくりかえし
      tId=setInterval(function(){
        // Processingの貼ってあるCanvasを取得
        pjs = Processing.getInstanceById("pjsid");
        // 取得できたら
        if (pjs && obj_array){
          // 取得を中止
          clearInterval(tId);
          // Processingの関数を実行して、配列を送信
          pjs.addObjects(obj_array);
        }
      },100);
    }
  });
  };
  function deleteS(x,y){
    var obj_array = new Array();
    console.log("x:"+x,"y:"+y);

    $.ajax({
    url: '{%url "get_v3_posts" %}',
    type:'GET',
    data:{
        'x':x,
        'y':y,
        },
    dataType:'json',
    })
    .then(
      (data) => {
        jQuery.each( data.nodes, function(i) {
        // JSONから取得したオブジェクトを配列に格納
        obj_array[i] = data.nodes[i];
      });
      },
      () => {
            alert("読み込み失敗");
        }
      );
  var tId, pjs, cnt=0;
  $(function(){
    if (!pjs){
      tId=setInterval(function(){
        pjs = Processing.getInstanceById("pjsid");
        if (pjs && obj_array){
          clearInterval(tId);
          pjs.addObjects(obj_array);
        }
      },100);
    }
  });
  };
  </script>
</head>
<style type="text/css">
.main{

}
</style>
<body>
  <div class = "main">
    <p> Processing </p>
    <canvas id="pjsid" data-processing-sources="{% static "p5jsjson.pde" %}"></canvas>
  </div>
</body>
</html>

```

----
5.Processingコード

```/p5jsjson.pde

ArrayList circles;
//２画面
int screen[] = {1,0};
void setup(){ 
  size(600, 600);
  circles = new ArrayList();
}

void draw(){
	if (screen[0] == 1){
		background(63);
		fill(255);
		rect(0, 0, 100, 100);
		for (int i = 0; i < circles.size(); i++) {
			circles.get(i).draw();
		}
	}else if (screen[1] == 1){
		background(0);
		fill(255);
		rect(0, 0, 100, 100);
		for (int i = 0; i < circles.size(); i++) {
			circles.get(i).draw();
		}
	}
}
void mousePressed(){
	if (screen[0] == 1){
		if ((mouseX <= 100 && mouseX >= 0) && (mouseY <= 100 && mouseY >= 0)){
			screen[0] = 0;
			screen[1] = 1;
		}else{
			int x = mouseX;
			int y = mouseY;
			input(x,y);
		}
	}else if (screen[1] == 1){
		if ((mouseX <= 100 && mouseX >= 0) && (mouseY <= 100 && mouseY >= 0)){
			screen[0] = 1;
			screen[1] = 0;
		}else{
			int x = mouseX;
			int y = mouseY;
			circles = new ArrayList();
			deleteS(x,y);
			for (int i = 0; i < circles.size(); i++) {
				circles.get(i).draw();
			}
		}
	}
}


void addObjects(nodes){
  for(int i = 0; i < nodes.length; i++){
    PVector pos = new PVector(nodes[i].x, nodes[i].y);
    float diameter = nodes[i].diameter;
    string name = nodes[i].name;
    circles.add(new MyCircle(pos, diameter, name));
  }
}

class MyCircle{
  PVector pos;
  float diameter;
  string name;

  MyCircle(PVector _pos, float _diameter, string _name){
    pos = _pos;
    diameter = _diameter;
    name = _name;
  }

  void draw(){
    fill(0, 127, 255, 15)
    stroke(31, 127, 255);
    ellipse(pos.x, pos.y, diameter, diameter);
    fill(255);
    noStroke()
    ellipse(pos.x, pos.y , 5, 5);
    text(name, pos.x+4 , pos.y-2 );
  }
}
```