[CreateJS] TwinkleLights 〜Stage.compositeOperation〜

CreateJSを使って、TwinkleLightsを作ってみるよ。 :bouzu:

createjs_twinklelights

StageクラスcompositeOperationプロパティを使って、ブレンドモード適用してるよ。 :girl:

index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>TwinkleLights | CreateJS</title>
<script src="js/easeljs-0.8.1.min.js"></script>
<script src="js/tweenjs-0.6.1.min.js"></script>
<script src="js/movieclip-0.8.1.min.js"></script>
<script src="js/preloadjs-0.6.1.min.js"></script>
<script src="js/stats.min.js"></script>
<style type="text/css">
  #canvas{
    display:block;
    width:600px;
    margin-top:40px;
    margin-left:auto;
    margin-right:auto;
    padding-left:0;
    padding-right:0;
  }
</style>
<script>
var canvas, stage, stats;
var images;
var loader;
var title, map;
var image, container;
var playing = false;

function init() {
  stats = new Stats();
  stats.setMode(0);
  stats.domElement.style.position = "fixed";
  stats.domElement.style.right = "0px";
  stats.domElement.style.top = "0px";
  document.body.appendChild(stats.domElement);

  canvas = document.getElementById("canvas");

  stage = new createjs.Stage(canvas);

  background();

  images = images||{};
  var manifest = [
    {src: "assets/title.png", id: "title"},
    {src: "assets/light.png", id: "light"}
  ];
  var loader = new createjs.LoadQueue(false);
  loader.addEventListener("fileload", fileload);
  loader.addEventListener("complete", complete);
  loader.loadManifest(manifest);

  createjs.Ticker.setFPS(30);
  createjs.Ticker.timingMode = createjs.Ticker.RAF_SYNCHED;
  if (createjs.Touch.isSupported()) {
    createjs.Touch.enable(stage);
  }
  stage.enableMouseOver(10);
  stage.update();
  createjs.Ticker.addEventListener("tick", update);
}
function update(event) {
  twinkle();

  stage.update();

  stats.update();
}
function fileload(event) {
  if (event.item.type == "image") {
    images[event.item.id] = event.result;
  }
}
function complete(event) {
  event.target.removeEventListener("fileload", fileload);
  event.target.removeEventListener("complete", complete);

  initialize();
  start();
  playing = true;
}
function initialize() {
  var titleimage = images["title"];
  title = new createjs.Bitmap(titleimage);
  stage.addChild(title);
  title.regX = titleimage.width >> 1;
  title.regY = titleimage.height >> 1;
  title.x = 300;
  title.y = 180;
  title.alpha = 0.2;

  map = detect(30, 140, 540, 80);

  image = images["light"];

  container = new createjs.Container();
  stage.addChild(container);
  stage.compositeOperation = "lighter";
}
function detect(x, y, w, h) {
  stage.update();

  var context = canvas.getContext("2d");
  var imageData = context.getImageData(x, y, w, h);
  var data = imageData.data;

  var list = [];
  var max = data.length;
  for (var n = 0; n < max; n += 4) {
    if (data[n + 3] < 0x33) continue;
    var c = n/4;
    var x = c%w;
    var y = (c/w) >> 0;
    list.push({x: x, y: y});
  }
  return list;
}
function start() {
  createjs.Tween.get(title, {override: true})
    .to({alpha: 0.5}, 3000, createjs.Ease.linear)
    .to({alpha: 0.2}, 3000, createjs.Ease.linear)
    .call(repeat);
}
function repeat() {
  start();
}
function twinkle() {
  if (!playing) return;

  create();
}
function create() {
  var light = new createjs.Container();
  container.addChild(light);
  var bitmap = new createjs.Bitmap(image);
  bitmap.regX = 30;
  bitmap.regY = 30;
  light.addChild(bitmap);
  var scale = 0.5 + Math.random()*0.5;
  bitmap.scaleX = bitmap.scaleY = scale;
  var hue = Math.random()*360;
  var colorfilter = HSVtoColorFilter(hue, 0.5, 1);
  bitmap.filters = [colorfilter];
  bitmap.cache(0, 0, 60, 60);

  var mid = (Math.random()*map.length) >> 0;
  light.x = 30 + map[mid].x;
  light.y = 140 + map[mid].y;
  light.scaleX = light.scaleY = 0;
  light.alpha = 0;

  createjs.Tween.get(light, {override: true})
    .to({scaleX: 1, scaleY: 1, alpha: 1}, 300, createjs.Ease.quintOut)
    .to({scaleX: 0, scaleY: 0, alpha: 0}, 1200, createjs.Ease.quadOut)
    .call(remove);
}
function remove() {
  container.removeChild(this);
}
function HSVtoColorFilter(h, s, v) {
  var r, g, b, i, f, p, q, t;
  if (h && s === undefined && v === undefined) {
    s = h.s, v = h.v, h = h.h;
  }
  i = Math.floor(h * 6);
  f = h * 6 - i;
  p = v * (1 - s);
  q = v * (1 - f * s);
  t = v * (1 - (1 - f) * s);
  switch (i % 6) {
    case 0: r = v, g = t, b = p; break;
    case 1: r = q, g = v, b = p; break;
    case 2: r = p, g = v, b = t; break;
    case 3: r = p, g = q, b = v; break;
    case 4: r = t, g = p, b = v; break;
    case 5: r = v, g = p, b = q; break;
  }
  var colorfilter = new createjs.ColorFilter(r, g, b, 1, 0, 0, 0, 0);
  return colorfilter;
}
function background() {
  var basic = new createjs.Text("HTML5 / CreateJS [0.8.1]", "14px Arial", "#FFFFFF");
  stage.addChild(basic);
  basic.textAlign = "left";
  basic.textBaseline = "top";
  basic.x = 4;
  basic.y = 2;
  basic.alpha = 0.6;
}
</script>
</head>
<body onload="init();" style="background-color:#EEEEEE">
  <canvas id="canvas" width="600" height="360" style="background-color:#000000"></canvas>
</body>
</html>

title.png

createjs_twinklelights_title

light.png

createjs_twinklelights_light


[修正] (15/09/21 Mon 01:19)
CreateJS 0.8.1 にバージョンアップ。