何かが悟れそうな画像ジェネレーター

Standard

http://bugcloud.com/worcloud/canvas/3/
 
 

class Block
  constructor:(row, col) ->
    @alive = true
    @row = row
    @col = col
  kill: () ->
    @alive = false

class Grid
  constructor: () ->
    @width = 22
    @height = 22
    winWidth = $(window).width()
    winHeight = $(window).height()
    @totalWidth = winWidth + (@width - (winWidth % @width))
    @totalHeight = winHeight + (@height - (winHeight % @height))
    @cols = Math.ceil(@totalWidth / @width) + 1
    @rows = Math.ceil(@totalHeight / @height) + 1
    @loopCount = @cols * @rows
    @totalWidth = @width * @cols
    @totalHeight = @height * @rows
    @blocks = []
    @blockCollection = []
    for i in [0..(@rows-1)]
      cols = []
      for j in [0..(@cols-1)]
        b = new Block(i, j)
        cols.push b
        @blockCollection.push b
      @blocks[i] = cols
  
  printBlocks: () ->
    str = ""
    for i in [0..(@rows-1)]
      for j in [0..(@cols-1)]
        b = @blocks[i][j]
        str += if b.alive then "□" else "■"
      str += "\n"
    console.log str
  pickupTryCount: 0
  pickup: (width, height) ->
    if @pickupTryCount > 60
      @pickupTryCount = 0
      return null
    else
      @pickupTryCount++
      result = null
      l = @blockCollection.length
      return null if l is 0
      b = @blockCollection[Math.floor(Math.random() * l)]
      if (b.col + width) <= @cols and (b.row + height) <= @rows
        for i in [b.row..(b.row+height-1)]
          for j in [b.col..(b.col+width-1)]
            block = @blocks[i][j]
            unless block.alive
              return this.pickup(width, height)
            else
              result = b
      else
        return this.pickup(width, height)
      @pickupTryCount = 0
      result

class Global
  constructor: () ->
    @canvas
    @context
  init: () ->
    me = this
    @canvas = document.getElementById 'canvas01'
    @context = @canvas.getContext '2d'

class Square
  constructor: (x, y, width, height) ->
    @x = x
    @y = y
    @width = width
    @height = height
    @radius = 3
    @radius2 = 14
    @r = Math.floor(Math.random() * 255)
  render: () ->
    _g.context.beginPath()
    _g.context.fillStyle = "hsla(#{@r}, 100%, 50%, 1)"
    _g.context.rect(@x, @y, @width, @height)
    console.log "x:#{@x}, y:#{@y}, w:#{@width}, h:#{@height}"
    _g.context.fill()
    _g.context.closePath()

_g = new Global()
_grid = new Grid()

$ ->
  $("#canvas01").attr("width", Math.floor($(document).width()))
  $("#canvas01").attr("height", Math.floor($(document).height()))
  _g.init()

  collection = []
  for i in [1.._grid.loopCount]
    collection.push {
      size: {
        col: Math.floor(1 + Math.random() * 4)
        row: Math.floor(1 + Math.random() * 4)
      }
    }
  for i in [1.._grid.loopCount]
    collection.push {
      size: {
        col: 1
        row: 1
      }
    }

  $.each collection, () ->
    block = _grid.pickup(this.size.col, this.size.row)
    unless block is null
      for i in [0..(this.size.row - 1)]
        for j in [0..(this.size.col - 1)]
          bb = _grid.blocks[block.row + i][block.col + j]
          bb.kill()
          newCollection = []
          for b in _grid.blockCollection
            newCollection.push b unless bb is b
          _grid.blockCollection = newCollection

      (new Square((_grid.width * block.col), (_grid.height * block.row), (_grid.width * this.size.col), (_grid.height * this.size.row))).render()
      _grid.printBlocks()

  img = _g.canvas.toDataURL("image/png")
  _g.context.clearRect(0, 0, _grid.totalWidth, _grid.totalHeight)
  $("body").append "<img src='#{img}' />"
  $("#canvas01").remove()

 
 
元ネタはこれです。
http://toyota.jp/86/

jsプラクティス2

Standard

http://bugcloud.com/?p=1355
Backbone.js with CoffeeScriptで書きなおしてみた。たぶんこっちのがなういホット
http://bugcloud.com/worcloud/tbb/
https://github.com/bugcloud/tbb

coffeescript最高ですね。ストレスフリーだ(゚д゚)ウマー
jsオンリーで開発するときはコンソールで

coffee -wo ./ -cb ./coffee/*.coffee

ってやっときましょう。
※ bオプションつけるとトップレベルのスコープになって

(function() {
 .....
}).call(this);

っていうのがつかなくなる。
wオプションは.coffeeファイルを監視して変更されると即コンパイルしてくれる。
 
Backbone.jsのほうはたぶん本領を発揮させてあげれていない(:.;゚;Д;゚;.:)ハァハァ

最近ちょいちょい使うjsプラクティス

Standard

http://bugcloud.com/worcloud/tb/
規模が小さいときはだいたいこんな感じで書いてるので、Tumblr APIで画像を取得して並べただけのもので紹介してみます。
index.html

<!DOCTYPE html>
<html dir="ltr" lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>.T.umblr</title>
    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js"></script>
    <script type="text/javascript" src="js/obj.js"></script>
    <script type="text/javascript" src="js/Tumblr.js"></script>
    <script type="text/javascript" src="js/Common.js"></script>
    <script type="text/javascript" src="js/Page.js"></script>
    <script type="text/javascript" src="js/Init.js"></script>
    <script type="text/javascript" src="js/bind.js"></script>
    <link href='http://fonts.googleapis.com/css?family=Gravitas+One' rel='stylesheet' type='text/css'>
    <link href="css/reset.css" type="text/css" rel="stylesheet"/>
    <link href="css/default.css" type="text/css" rel="stylesheet"/>
    <link href="css/style.css" type="text/css" rel="stylesheet"/>
  </head>
  <body>
    <h1 id="siteName">.T.umblr</h1>
    <div id="wrapper">
    </div>
    <div id="buttonLoad">
      <a href="javascript:void(0);"><img src="img/refresh.png" alt="load more" title="" /></a>
    </div>
  </body>
</html>

読み込んでいるjsについて上から。
 
 
jquery

ないと仕事できないので説明不要。
 
 
js/obj.js

/*
 *  * object - オブジェクトを作る
 *  * Object object(BaseObj [, mixinObj1 [, mixinObj2...]])
 */
function object(o) {
    var f = object.f, i, len, n, prop;
    f.prototype = o;
    n = new f;
    for (i=1, len=arguments.length; i<len; ++i)
        for (prop in arguments[i])
            n[prop] = arguments[i][prop];
    return n;
}
object.f = function(){};

“functionを定義してそれにprototypeを設定してnewしてオブジェクトを作る”っていうのを object(o) という関数に隠匿しています。プロトタイプベースのJavascriptで普段利用しているクラスベース言語でいうところのクラスのようなオブジェクトを簡単に利用できるようになります。
参考 → newを封印して、JavaScriptでオブジェクト指向する
 
 
js/Tumblr.js

var Tumblr = {
  init: function() {},
  apiConsumerKey: "SyMOX3RGVS4OnK2bGWBcXNUfX34lnzQJY5FRB6uxpFqjEHz2SY",
  hostName: "dvdp.tumblr.com",
  offset: 0,
  photoPosts: function() {
    var me = this
    var url = "http://api.tumblr.com/v2/blog/" + me.hostName + "/posts/photo"
    var data = {api_key: me.apiConsumerKey, offset: me.offset}
    $.ajax({
      url: url,
      data: data,
      dataType: 'jsonp',
      jsonp: 'jsonp',
      success: function(data, type) {
        me.photoPostsCallback(data, type)
      },
      error: function(XMLHttpRequest, textStatus, errorThrown) {
        console.log(errorThrown)
      }
    })
  },
  photoPostsCallback: function(data, type) {
    console.log(data)
  }
}

上のjs/obj.jsを利用する為にTumblr(クラスのような)オブジェクトを定義しています。
見たままですが、Tumblr APIをコールするためのWrapperのようなオブジェクトです。

var myTumblr = object(Tumblr)
myTumblr.photoPosts()

とすればhttp://dvdp.tumblr.com/の投稿から画像のものを取得してログに出力します。

var myTumblr2 = object(Tumblr)
myTumblr2.hostName = "shyouhei.tumblr.com"
myTumblr2.photoPostsCallback = function() {
  $.each(data.response.posts, function() {
    $('body').append('<p>' + this.body + '</p>')
  })
}

で、http://shyouhei.tumblr.com/の投稿をhtml bodyに出力します。ここでわかるように定義しておいたオブジェクトからobject関数を使ってオブジェクトを作った後に、そのオブジェクトのメンバを変更することができます。

因みに、入門な話をすると、

var s = {
  a: 'a',
  b: function() {...}
}

という書き方は

var s = new Object
s.a = 'a'
s.b = function() {...}

のシンタックスシュガーです。
 
 
js/Common.js

var Common = {
  init: function() {},
  randomColor: function() {
    var c = "rgba(" + Math.floor(Math.random()*256) + ","
    c = c + Math.floor(Math.random()*256) + ","
    c = c + Math.floor(Math.random()*256) + ","
    c = c + "0.65)"
    return c
  }
}

共通関数を定義しています。どのサイトでも使いまわせるものをここに入れています。
 
 
js/Page.js

var Page = {
  currentIndex: 0,
  currentLeft: 0,
  init: function() {
    this.currentIndex = 1
  },
  increment: function() {
    this.currentIndex = this.currentIndex + 1
  }
}

ページ全体で使う関数を定義しています。レイアウトを調整するような関数があればここで定義します。
 
 
js/Init.js

var _mysiteTumblr = object(Tumblr)
var _mysiteCommon = object(Common)
var _mysitePage = object(Page)

$(function() {
  _mysiteTumblr.init()
  _mysiteCommon.init()
  _mysitePage.init()
})

グローバル変数の定義と各オブジェクトの初期化です。グローバル変数はまとめて書くようにしておかないと、そのうち追えなくなって破綻します。
 
 
js/bind.js

$(function() {
  _mysiteTumblr.photoPostsCallback = function(data, type) {
    _mysiteTumblr.offset = _mysiteTumblr.offset + data.response.posts.length
    $.each(data.response.posts, function() {
      $.each(this.photos, function() {
        var html = '<div class="floatbox" style="'
        html = html + 'background-color:'
        _mysitePage.increment()
        html = html + _mysiteCommon.randomColor() + ';">'
        html = html + '<a href="' + this.original_size.url + '" target="_blank"><img src="' + this.alt_sizes[0].url + '"/></a>'
        html = html + '</div>'
        $("#wrapper").append(html)
      })
    })
  }
  _mysiteTumblr.photoPosts()
  $("#buttonLoad a").bind('click', function() {
    _mysiteTumblr.photoPosts()
  })
})

MVCで言ったらコントローラーです。onLoadで、Tumblr#photoPostsCallbackの振る舞いを設定してから実行しています。またボタンのクリックイベントのバインドをしています。
 
 
 
とりあえずjsはこれで全部です。
 
 
会社用に書いたんだよこれ恥ずかしい