2012年2月19日日曜日

Playing with Dartium

前にjavascriptで書いてた処理をdartに移植してDartiumで動かしてみた。やらんとしていたのはニコニコもどきだけど、書いてる途中にjavascriptに嫌気がさして投げたので色々と中途半端。とりあえず処理の内容は以下。

  1. 特定のid(今回だと"stage")を持つノードにいくつかノードを追加する。
  2. ボタンがクリックされるたびにTextArea内の内容を(最初に追加された)ノードにわりあてて、CSSアニメーションをくっつけて表示する。

完成図

Postをクリックするたびに麻呂がフェードアウトしながら右にスライドしていきます。スバラシイ。

html + dart

dartのコードはclassの使い方を試す意図もあったので、あえてclassにして書いてる。その過程で学んだことを数点書くと以下の通り。

  • Dart Style Guideには従っとけ。
  • 変数名の頭に"_"をつけるとprivateな変数になる。つけないと自動的にpublicになる。
  • intの変数を文字列表現に変換したいような場合は"$value"や"${value}"という書きかた(string interpolation syntax)をすると自動的に文字列変換してくれる。こういう仕様になった事情はDartの言語仕様を見ると書いてあって、抜粋すると以下の通り。

    The string interpolation syntax is designed to be familiar and easy to use, if somewhat awkward to parse. The intent is to encourage its use over alternatives such as s1 + s2. In a dynamically typed language, the use of the + operator requires dynamic dispatch. In contrast, in the case of string interpolation we can statically determine that the string concatenation operation is required, making the operation more efficient. Even more importantly, it helps the system to determine if other uses of + are numeric, helping the implementation speed up those operations. This is especially crucial for a language that must be efficiently compiled into Javascript.

    要するに対象の変数が文字列なのか数字なのかがより明確にできるから、周辺の処理を高速化しやすくなる、という話みたい。

<!doctype html>
<head>
    <meta charset="utf-8">
    <title>dartlang test</title>
    <link rel="stylesheet" type="text/css" href="./css/bootstrap.min.css" />
    <link rel="stylesheet" type="text/css" href="./css/client.css" />
</head>
<body>
    <script type="application/dart" >
        #import("dart:html");
        /**
          * Class that manages remark display
          */
        class RemarkDisplayer {
            RemarkDisplayer(int numberOfRemarks) {
                _numberOfRemarks = numberOfRemarks;
                _remarkList = new List<Element>();
                _currentRemark = 0;
            }
            
            /**
             * Create remark nodes under the tag with the given ID
             */
            void initialize(String stageID) {
                var stage = document.query(stageID);
                for (int i=0; i<_numberOfRemarks; i++) {
                    var tag = '<pre class="remark" id="remark${i}" draggable="true"/>';
                    var elem = new Element.html(tag);
                    stage.nodes.add(elem);
                    _remarkList.add(elem);
                }
            }

            /**
              * Display given remark at the current node
              */
            void display(String remark) {
                var node = _remarkList[_currentRemark];
                var durationMS= 5000;
                node.innerHTML = remark;
                node.style.visibility = "visible";
                node.style.animationName = "fade, hslide";
                node.style.animationDuration = "${durationMS}ms";
                node.style.animationTimingFunction = "linear";
                node.style.animationFillMode = "forwards";

                // Replace node with a clone to restart animation
                var newNode = node.clone(true);
                node.replaceWith(newNode);
                _remarkList[_currentRemark] = newNode;

                // proceed to next remark
                _currentRemark++;
                if (_currentRemark >= _numberOfRemarks) {
                    _currentRemark = 0;
                }
            }
            
            int _numberOfRemarks;
            get numberOfRemarks() => _numberOfRemarks;

            List<Element> _remarkList;
            int _currentRemark;
        }

        void main() {
            final int MAX_NUMBER_OF_REMARKS = 10;
            var displayer = new RemarkDisplayer(MAX_NUMBER_OF_REMARKS);
            displayer.initialize("#stage");
            var button = document.query("#postRemark");
            TextAreaElement textNode = document.query("#remarkText");
            button.on.click.add((Event e) {
                    displayer.display(textNode.value);
            });
         }
    </script>
    <div class="topbar">
        <div class="fill">
            <div class="container">
                <a class="brand" href="#">dartlang test</a>
            </div>
        </div>
    </div>
    
    <div class="container">
        <div class="content" >
            <form action="">
                <textarea class="xxlarge" rows="23" id="remarkText">
        ___|二ニー-、、;:;:;:;:;:;:;:;:;:;:;:;:;:;:;:;:;:;:|;::;:;:;:;:;:;:;:;:;:;:;:;:l
        /rヽ三三三三三─‐-- 、;:;:;:;:;:;:;:|;:;:;:;:;:;:;:;:;:;:;:;:;:;l
        ',i ,-三三三三三、   _,.ニ、ー-、!;: -‐二 ̄彡′
        ',、、ヾ三三'" ̄ ̄   `ー‐"    ヾ-'"  .〉′
        ヽ ヽヾ三,'    :::..,. -‐- 、     _,,..-‐、、,'
         `ー',ミミ     ::.弋ラ''ー、   i'"ィ'之フ l
         /:l lミミ     ::::.. 二フ´   l ヽ、.ノ ,'     
      ,.-‐フ:::::| |,ミ             l      /       
     /r‐'":::::::::| |ヾ        /__.   l    /      
 _,. -‐"i .|::::::::::::::::::',.',. \        ⌒ヽ、,ノ   /ヽ,_             
"    l ヽ:::::::::::::::::ヽヽ. \   _,_,.、〃  /l |    ___,. -、
     ',\\:::::::::::::::ヽ\  \  、. ̄⌒" ̄/:::::| |    ( ヽ-ゝ _i,.>-t--、
     \\\;::::::::::::\\  `、.__  ̄´ ̄/::::::::::l |    `''''フく _,. -ゝ┴-r-、
       ヽ \`ー-、::::::ヽ ヽ    ̄フフ::::::::::::::ノ ./   ,.-''"´ / ̄,./´ ゝ_'ヲ
          `ー-二'‐┴┴、__/‐'‐´二ー'".ノ   / _,. く  / ゝ_/ ̄|
               ̄`ー─--─‐''" ̄      / にニ'/,.、-t‐┴―'''''ヽ
                              /  /  .(_ヽ-'__,.⊥--t-⊥,,_
                              /  /  /   ̄   )  ノ__'-ノ
                             /      /    ゝニ--‐、‐   |
                            /           /‐<_   ヽ  |ヽ </textarea>
                <button class="btn primary" id="postRemark" type="button">Post</button>
            </form>
        </div>

        <div id="stage"></div>
    </div>
</body>
</html>

css

bootstrapなcssを除き、自分で新たに定義したcssも掲載する。

html, body {
    background-color: #eee;
}
body {
    padding-top: 40px; /* 40px to make the container go all the way to the bottom of the topbar */
}
.container > footer p {
    text-align: center; /* center align it with the container */
}

.remark {
    background : rgba(0,0,0,0); /* transparent background*/
    position: absolute;
    width: auto;
    height: auto;
    font-family: "IPA モナーPゴシック", monospace;
}

/* Fading animation */
@-webkit-keyframes fade {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}

/* vertical scroll animation */
@-webkit-keyframes vslide {
  0%   { -webkit-transform: translateY(0px); }
  100% { -webkit-transform: translateY(100px); }
}

/* horizontal scroll animation */
@-webkit-keyframes hslide {
  0%   { -webkit-transform: translateX(0px); }
  100% { -webkit-transform: translateX(1000px); }
}

感想

classに変数やら処理をまとめて隠蔽できるのは気持ちいいっすね。

0 件のコメント:

コメントを投稿