DIR : /home/kozerus/public_html/jkwii/js/jsdoit/Kira-Kira-Camera/index.js

/home/kozerus/public_html/jkwii/js/jsdoit/Kira-Kira-Camera

// forked from akm2's "Motion Detection" http://jsdo.it/akm2/2VGa
// forked from akm2's "Slit Scan Camera" http://jsdo.it/akm2/gmjx
// forked from akm2's "Scanner Camera" http://jsdo.it/akm2/63bn

/**
 * requestAnimationFrame polyfill by Erik Möller
 * fixes from Paul Irish and Tino Zijdel
 *
 * @see http://paulirish.com/2011/requestanimationframe-for-smart-animating/
 * @see http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
 */
(function(e){var t=0;var n=["ms","moz","webkit","o"];var r="requestAnimationFrame";var i="cancelAnimationFrame";for(var s=0;s<n.length&&!e[r];++s){e[r]=e[n[s]+"RequestAnimationFrame"];e[i]=e[n[s]+"CancelAnimationFrame"]||e[n[s]+"CancelRequestAnimationFrame"]}if(!e.requestAnimationFrame)e[r]=function(n,r){var i=(new Date).getTime();var s=Math.max(0,16-(i-t));var o=e.setTimeout(function(){n(i+s)},s);t=i+s;return o};if(!e[i])e[i]=function(e){clearTimeout(e)}})(window);

// window.URL
window.URL = window.URL || window.webkitURL;

// navigator.getUserMedia
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;


// Config

var CANVAS_WIDTH = 465,
    CANVAS_HEIGHT = 348,
    MAX_NUM = 1500,
    GRAVITY = 0.045;

// Vars

var video, canvas, context,
    pastImageData = null,
    destImageData,
    particles = [],
    pool = [],
    threshold = 50,
    showMap = false,
    gui;

/**
 * Init
 */
function init() {
    if (!navigator.getUserMedia) {
        alert('getUserMedia() Not supported');
        return;
    }

    canvas = document.getElementById('c');
    canvas.width = CANVAS_WIDTH;
    canvas.height = CANVAS_HEIGHT;
    canvas.style.top = ((document.getElementById('container').offsetHeight - CANVAS_HEIGHT) / 2 | 0) + 'px';
    context = canvas.getContext('2d');
    context.fillStyle = 'hotpink';

    destImageData = context.createImageData(CANVAS_WIDTH, CANVAS_HEIGHT);

    video = document.createElement('video');
    video.autoplay = true;

    Kirakira.initialize(12, 4);

    navigator.getUserMedia({ video: true }, function(stream) {
        video.addEventListener('canplaythrough', function(e) {
            gui = new dat.GUI();
            gui.width = 250;
            gui.add(window, 'threshold', 0, 255).step(1).name('Threshold');
            gui.add(window, 'toggleDisplay').name('Toggle display');
            gui.close();

            setTimeout(update, 1000);
        }, false);
        video.src = window.URL.createObjectURL(stream);
    }, function(e) {
        alert('Error: ' + (e.code === e.PERMISSION_DENIED ? 'Permission denied' : 'Unknown'));
    });
}

/**
 * マップ表示を切替
 */
function toggleDisplay(e) {
    showMap = !showMap;
}

/**
 * Update
 */
function update() {
    var W = CANVAS_WIDTH,
        H = CANVAS_HEIGHT,
        currImageData,
        p;

    context.save();
    context.translate(W, 0);
    context.scale(-1, 1);
    context.drawImage(video, 0, 0, W, H);
    context.restore();

    currImageData = context.getImageData(0, 0, W, H);

    if (pastImageData) {
        var TWO_PI = Math.PI * 2,
            destPixels = destImageData.data,
            currPixels = currImageData.data,
            pastPixels = pastImageData.data,
            pastAverage, currAverage,
            diff, isDiff,
            x, y, yi, i, i1, i2;

        for (y = 0, i = 0; y < H; y++) {
            yi = y * W;
            for (x = 0; x < W; x++, i += 4) {
                i1 = i + 1;
                i2 = i + 2;
                pastAverage = (pastPixels[i] + pastPixels[i1] + pastPixels[i2]) / 3;
                currAverage = (currPixels[i] + currPixels[i1] + currPixels[i2]) / 3;

                diff = pastAverage - currAverage;
                if (diff < 0) diff *= -1;

                isDiff = diff > threshold;

                // 差があれば一定の確立でパーティクルを生成
                if (isDiff && Math.random() < 0.005 && particles.length < MAX_NUM) {
                    p = pool.length ? pool.shift() : new Particle(); // 生成済みのパーティクルがあれば使い回す
                    mag = 0.5 + 2.5 * Math.random();
                    magAngle = TWO_PI * Math.random();
                    p.init(
                        x, y,
                        mag * Math.cos(magAngle),
                        mag * Math.sin(magAngle),
                        0.5 + 0.5 * Math.random(), // scale
                        TWO_PI * Math.random() //angle
                    );
                    particles.push(p);
                }

                // 表示用
                destPixels[i] = destPixels[i + 1] = destPixels[i + 2] = isDiff ? 255 : 0;
                destPixels[i + 3] = 255;
            }
        }
    }

    if (showMap) context.putImageData(destImageData, 0, 0);

    pastImageData = currImageData;

    var G = GRAVITY,
        symbols   = Kirakira.symbols,
        symbolNum = Kirakira.symbols.length,
        radius    = Kirakira.radius,
        size      = Kirakira.size,
        dScale, dSize, dSizeHalf;

    for (i = 0, len = particles.length; i < len; i++) {
        p = particles[i];

        p.vy += G;
        p.x += p.vx;
        p.y += p.vy;
        p.scale -= 0.02 * Math.random();
        p.angle += Math.random();

        if (p.x + radius < 0 || p.x - radius > W || p.y + radius < 0 || p.y - radius > H || p.scale <= 0) {
            pool.push(p); // 使い回すためプール
            particles.splice(i, 1);
            len--;
            i--;
            continue;
        }

        dScale = p.scale;
        if (Math.random() < 0.5) dScale *= 0.2;
        dSize = size * dScale;
        dSizeHalf = dSize * 0.5;

        context.save();
        context.globalCompositeOperation = 'lighter';
        context.translate(p.x, p.y);
        context.rotate(p.angle);
        context.drawImage(symbols[symbolNum * Math.random() | 0], 0, 0, size, size, -dSizeHalf, -dSizeHalf, dSize, dSize);
        context.restore();
    }

    requestAnimationFrame(update);
}


/**
 * Particle
 */
function Particle(x, y, vx, vy, scale, angle) {
    this.init(x, y, vx, vy, scale, angle);
}

Particle.prototype.init = function(x, y, vx, vy, scale, angle) {
    this.x = x || 0;
    this.y = y || 0;
    this.vx = vx || 0;
    this.vy = vy || 0;
    this.scale = scale || 0;
    this.angle = angle || 0;
};


/**
 * Kirakira
 */
var Kirakira = (function() {

    var VERTEX_NUMS = [4, 6, 8, 10, 12];

    return {
        symbols: [],
        radius:  0,
        blur:    0,
        size:    0,

        initialize: function(radius, blur) {
            this.radius = radius;
            this.blur = blur;
            this.size = (this.radius + this.blur) * 2;

            for (var i = 0, len = VERTEX_NUMS.length; i < len; i++) {
                this.symbols.push(this._createSymbol(VERTEX_NUMS[i], this.radius, this.blur));
            }
        },

        _createSymbol: function createSymbol(vertexNum, radius, blur) {
            var canvas = document.createElement('canvas');
            canvas.width = canvas.height = this.size;

            var context = canvas.getContext('2d');
            context.fillStyle = 'rgba(255, 255, 255, 1)';
            context.shadowBlur = blur;
            context.shadowColor = 'rgba(255, 255, 255, 0.75)';

            var center = this.size / 2;
            var r, a;

            context.beginPath();
            for (var i = 1, len = vertexNum * 2; i <= len; i++) {
                r = i % 2 ? this.radius * 0.1 : this.radius;
                a = i / len * Math.PI * 2;
                context[i === 1 ? 'moveTo' : 'lineTo'](center + r * Math.cos(a), center + r * Math.sin(a));
            }
            context.fill();

            return canvas;
        }
    };

})();

// Init

window.addEventListener('load', init, false);
//


koh5_pano



Your browser does not support the HTML5 canvas element.


Drag mouse to navigate.

Navigation





17.Aug.2010, Martin Wengenmayer