みかづきブログ その3

3ヶ月つづけてみました。

選択した文字同士を入れ替える

クリックした文字同士を入れ替えます。
JSはやたら長いですが単純にクラスを付け替えているだけで、後はCSSアニメーションに任せています。
謎のちらつきは謎のままです。FFだときれいに見えます。


See the Pen hello world. by kimmy (@kimmy) on CodePen.

HTML

<div class="trade">
  <span class="txt t1">H</span>
  <span class="txt t2">E</span>
  <span class="txt t3">L</span>
  <span class="txt t4">L</span>
  <span class="txt t5">O</span>
  <span class="txt t6">W</span>
  <span class="txt t7">O</span>
  <span class="txt t8">R</span>
  <span class="txt t9">L</span>
  <span class="txt t10">D</span>
</div>

CSS

body {
  padding: 40px;
  background: #000;
}

.trade {
  position: relative;
}
.trade .txt {
  position: absolute;
  width: 24px;
  color: #fff;
  font: 30px Copperplate, sans-serif;
  text-align: center;
  white-space: nowrap;
  cursor: pointer;
  -webkit-transition: -webkit-transform .2s ease, top .5s ease, left .5s ease;
  transition: transform .2s ease, top .5s ease, left .5s ease;
}
.trade .txt.t1 {
  left: 30px;
}
.trade .txt.t2 {
  left: 60px;
}
.trade .txt.t3 {
  left: 90px;
}
.trade .txt.t4 {
  left: 120px;
}
.trade .txt.t5 {
  left: 150px;
}
.trade .txt.t6 {
  left: 195px;
}
.trade .txt.t7 {
  left: 230px;
}
.trade .txt.t8 {
  left: 260px;
}
.trade .txt.t9 {
  left: 290px;
}
.trade .txt.t10 {
  left: 320px;
}
.trade .txt.t10:after {
  content: ".";
}
.trade .txt.on {
  z-index: -1;
  -webkit-transform: scale(0.9);
  -ms-transform: scale(0.9);
  transform: scale(0.9);
  -webkit-animation: shake .1s ease 0s infinite normal;
  animation: shake .1s ease 0s infinite normal;
}

@-webkit-keyframes shake {
  0% {
    margin: -1px;
  }

  25% {
    margin: 1px 0 0 -1px;
  }

  50% {
    margin: -1px 0 0 1px;
  }

  100% {
    margin: 1px;
  }
}

@keyframes shake {
  0% {
    margin: -1px;
  }

  25% {
    margin: 1px 0 0 -1px;
  }

  50% {
    margin: -1px 0 0 1px;
  }

  100% {
    margin: 1px;
  }
}

JavaScript

(function (win, doc, $) {

    "use strict";

    win.app = win.app || {};

})(this, document, $);

(function (win, doc, $, ns) {

    "use stricr";

    function EventDispatcher() {
        this._events = {};
    }

    EventDispatcher.prototype.hasEventListener = function(eventName) {
        return !!this._events[eventName];
    };

    EventDispatcher.prototype.addEventListener = function(eventName, callback) {
        if (this.hasEventListener(eventName)) {
            var events = this._events[eventName];

            for (var i in events) {
                if (events[i] === callback) {
                    return;
                }
            }

            events.push(callback);
        } else {
            this._events[eventName] = [callback];
        }
    };

    EventDispatcher.prototype.removeEventListener = function(eventName, callback) {
        if (!this.hasEventListener(eventName)) {
            return;
        } else {
            var events = this._events[eventName],
                i = events.length,
                index;

            while (i--) {
                if (events[i] === callback) {
                    index = i;
                }
            }

            events.splice(index, 1);
        }
    };

    EventDispatcher.prototype.fireEvent = function(eventName, opt_this) {
        if (!this.hasEventListener(eventName)) {
            return;
        } else {
            var events     = this._events[eventName],
                copyEvents = $.merge([], events),
                arg        = $.merge([], arguments);

            arg.splice(0, 2);

            for (var i in copyEvents) {
                copyEvents[i].apply(opt_this || this, arg);
            }
        }
    };

    ns.EventDispatcher = EventDispatcher;

})(this, document, $, app);

(function (win, doc, $, ns) {

    "use strict";

    var EventDispatcher = ns.EventDispatcher,
        originalConstructor,
        instance;

    function CellManager() {
        var _cells = [],
            _queue = [],
            _count = 0;

        EventDispatcher.call(this);

        function _trade(cell1, cell2) {
            var className = cell1.getClass();

            cell1.setClass(cell2.getClass());
            cell2.setClass(className);

            setTimeout(function() {
                cell1.off();
                cell2.off();
            }, 500);
        }

        function push(cell) {
            _cells.push(cell);
        }

        function on(cell) {
            ++_count;

            _queue[1] = _queue[0];
            _queue[0] = cell;

            if (_count > 1) {
                _trade(_queue[0], _queue[1]);
            }
        }

        function off(cell) {
            if (_count) {
                --_count;
            }
        }

        function shuffle() {
            var length = _cells.length,
                queue  = [],
                i      = 0,
                j      = 0;

            for (; i < length; i++) {
                queue.push(i);
            }

            for (; j < length; j++) {
                _cells[queue.splice(Math.random() * queue.length | 0, 1)].on();
            }
        }

        this.push    = push;
        this.on      = on;
        this.off     = off;
        this.shuffle = shuffle;
    }

    originalConstructor = CellManager.prototype.constructor;
    CellManager.prototype = new EventDispatcher();
    CellManager.prototype.constructor = originalConstructor;

    CellManager.getInstance = function() {
        if (!instance) {
            instance = new CellManager();
        }

        return instance;
    };

    ns.CellManager = CellManager;

})(this, document, $, app);

(function (win, doc, $, ns) {

    "use strict";

    var EventDispatcher = ns.EventDispatcher,
        originalConstructor;

    function CellController ($elm) {
        var that = this;

        EventDispatcher.call(this);

        this._$elm = $elm;

        _init();

        function _init() {  
            $elm.on("click", _handleClick);
        }

        function _handleClick() {
            that.toggle();
        }
    }

    originalConstructor = CellController.prototype.constructor;
    CellController.prototype = new EventDispatcher();
    CellController.prototype.constructor = originalConstructor;

    CellController.prototype.toggle = function () {
        if (this._$elm.hasClass("on")) {
            this.off();
        } else {
            this.on();
        }
    };

    CellController.prototype.on = function () {
        this._$elm.addClass("on");
        this.fireEvent("ON");
    };

    CellController.prototype.off = function () {
        this._$elm.removeClass("on");
        this.fireEvent("OFF");
    };

    CellController.prototype.getClass = function () {
        return this._$elm[0].className;
    };

    CellController.prototype.setClass = function (className) {
        this._$elm[0].className = className;

        return this;
    };

    ns.CellController = CellController;

})(this, document, $, app);

(function(win, doc, $, ns) {

    "use strict";

    var CellManager    = ns.CellManager,
        CellController = ns.CellController;

    var cellManager = CellManager.getInstance(),
        $cells      = $(".txt"),
        length      = $cells.length,
        i = 0,
        cellController;

    for (; i < length; i++) {
        cellController = new CellController($cells.eq(i));

        cellController.addEventListener("ON",  _handleOnCell);
        cellController.addEventListener("OFF", _handleOffCell);
        cellManager.push(cellController);
    }

    function _handleOnCell() {
        cellManager.on(this, this);
    }

    function _handleOffCell() {
        cellManager.off();
    }

})(this, document, $, app);