16*16の2色のドット絵を打って投稿するサイトです。
突発的に思いついて5時間近く費やして作りました。
「Digital Pixel Monster」 http://digimon.laineus.com/
Digital Pixel Monster、略してデジモンです。
何気にGoで作ったapiを公開サーバーで実際に運用するの初めてだったりします。
使い方
左のキャンバスはピクセルをクリックすると着色できます。
着色済みのピクセルをクリックすると無色に戻ります。
右側ではサイトに投稿された作品一覧を閲覧できます。
何でも自由に投稿して大丈夫ですが、僕の独断で整理(削除)する場合があります。
riotとcssで描画しているだけなので画像データになったりはしません。
ソース
以下、RiotとGoのソース(一部)です。
ご指摘・アドバイス大歓迎です。
Riot ソース
描画と編集を行うコンポーネントです。
動作に最低限必要なところだけ抜き出してます。
app-canvas.tag
<app-canvas>
<ul class="dots">
<li each="{row, y in dots}">
<ul class="row">
<li class="{active: val==1}" each="{val, x in row}" onclick="{paint.bind(this, x, y)}"></li>
</ul>
</li>
</ul>
<style scoped>
:scope {
display: flex;
flex-direction: column;
min-height: 300px;
align-items: center;
justify-content: center;
}
:scope .dots {
display: inline-flex;
flex-direction: column;
border-top: 1px solid rgba(0,0,0,0.15);
border-left: 1px solid rgba(0,0,0,0.15);
}
:scope .dots .row {
display: flex;
flex-direction: row;
}
:scope .dots li {
list-style: none;
}
:scope .dots .row li {
width: 7px;
height: 7px;
border-right: 1px solid rgba(0,0,0,0.15);
border-bottom: 1px solid rgba(0,0,0,0.15);
}
:scope .dots .row li:hover {
background: #ccc;
}
:scope .dots .row li.active {
background: #333;
}
:scope .dots .row li.active:hover {
background: #666;
}
</style>
<script>
var self = this;
self.digimons = [];
self.dots = [
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0],
[0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0],
[0,0,1,1,1,0,0,0,0,1,1,0,0,1,0,0],
[0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0],
[0,1,0,0,0,0,0,0,0,1,1,1,0,1,0,0],
[0,1,0,0,0,0,1,1,0,0,0,0,0,1,0,0],
[0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0],
[0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,0],
[0,0,0,1,1,1,1,1,0,1,1,0,1,0,0,0],
[0,0,1,0,0,1,0,0,1,0,0,0,0,1,0,0],
[0,0,1,1,1,1,0,0,1,1,1,1,0,1,0,0],
[0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0],
[0,0,0,1,1,0,0,1,1,1,1,0,0,0,1,0],
[0,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1],
[0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,1],
];
self.paint = function(x, y, e) {
self.dots[y][x] = (self.dots[y][x] == 1) ? 0 : 1;
self.update();
}
</script>
</app-canvas>
16*16の長さの配列を[][]int
型で用意して、それをキャンバスとして扱っています。
テンプレートでは、この配列をループして、0なら白、1なら黒になるようclass名を付与しています。
各ドットをクリックした際のイベントでは、白なら黒、黒なら白に切り替える処理をしています。
[{x:2,y:3},{x:6,y:4}]
みたいな感じで、塗った部分の座標を保持する形でもできましたかね。
実際のソース
ソース | |
---|---|
index.html | view-source:http://digimon.laineus.com/index.html |
editor component | view-source:http://digimon.laineus.com/app-editor.html |
viewer component | view-source:http://digimon.laineus.com/app-viewer.html |
Go ソース
コントローラー部分のみ抜粋
package controller
import (
"../models"
"github.com/gin-gonic/gin"
"strconv"
)
// GetDigimon デジモン取得api
func GetDigimon(c *gin.Context) {
digimonID, e := strconv.Atoi(c.Query("id"))
repo := model.NewDigimonRepository()
if e == nil {
digimon := repo.GetByID(digimonID)
c.JSON(200, digimon)
} else {
digimons := repo.GetAll()
c.JSON(200, digimons)
}
}
// Request リクエスト形式を定義する構造体
type Request struct {
Name string `json:"name"`
Data [][]int `json:"data"`
}
// PostDigimon デジモン投稿api
func PostDigimon(c *gin.Context) {
var request Request
c.BindJSON(&request)
chk := checkSize(&request.Data, 16, 16)
if chk {
if request.Name == "" {
request.Name = "no name"
}
repo := model.NewDigimonRepository()
repo.SetNewDigimon(request.Name, &request.Data)
digimons := repo.GetAll()
c.JSON(200, digimons)
} else {
c.JSON(200, false)
}
}
// n*nの[][]intであるかチェック
func checkSize(dots *[][]int, width, height int) bool {
chk := true
if len(*dots) != height {
chk = false
} else {
for _, row := range *dots {
if len(row) != width {
chk = false
break
}
}
}
return chk
}
DBには、[][]int
のデータをそのままjson型で突っ込んでます。