JDBな人生  専門的なことから日常的なことまで~ まぁ自由きままに書いていきます。
2014年12月 / 11月<< 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 >>01月

アクセスランキング

[ジャンルランキング]
コンピュータ
356位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
34位
アクセスランキングを見る>>

【改訂版】JSでドラッグ&ドロップを実装する(スマホ対応)

最近、久々にWEB関連の開発を少々やっています。今日は主にクライアントサイドのコーディングをしました。
さて、3年近く前に、DOM要素のドラッグ&ドロップのコードを紹介しましたが、わかりにくく、スマホにも対応していなかったので、書きなおしてみました。

参考:
要素のドラッグ(IE,FF,GC対応) - JDBな人生
http://jabnz.blog69.fc2.com/blog-entry-735.html

今回は、「初期化」「移動量の取得」「設定値の計算」「代入」等の処理を、それぞれはっきりと分けて書いてみました。
また、オブジェクト型を使ったクラス実装も使っています。

var DDHandler = (function(){
    var that = {};
    
    /* イベント情報からマウスポインタの座標を取得 */
    var getMousePosition = function(e){
        // 座標値取得のクロスブラウザ対応
        if (e) return [e.pageX, e.pageY];
            else if(window.event) return [event.clientX, event.clientY];
    }
    
    /* スタイル値(文字列)から数値を取得 */
    var getPixelValue = function(str){
        if (str && str.match(/^\d{1,}(\.\d{1,})*px$/)) return Number(str.replace(/px/g, ""));
            else return 0;
    }
    
    /* オブジェクトを引数の値分移動する */
    var moveElement = function(target, dx, dy){
        var obj = {}, l, r, t, b;
        if (document.defaultView && document.defaultView.getComputedStyle){
            obj = document.defaultView.getComputedStyle(target, "");
        } else if (target.currentStyle) {
            obj = target.currentStyle;
        }
        l = obj.left, r = obj.right, t = obj.top, b = obj.bottom;
        
        if (l + "" == "auto") target.style.right = (getPixelValue(r) - dx) + "px";
            else target.style.left = (getPixelValue(l) + dx) + "px";
        if (t + "" == "auto") target.style.bottom = (getPixelValue(b) - dy) + "px";
            else target.style.top = (getPixelValue(t) + dy) + "px";
    }
    
    /* オブジェクトへのハンドラの設定 */
    var setDragAndDropListener = function(target, handle){
        if (typeof target.draggable != "undefined") target.draggable = false; // ブラウザ実装のドラッグを禁止
        if (typeof target.unselectable != "undefined") target.unselectable = true; // 選択禁止
        if (typeof handle == "undefined") handle = target; // 掴む部分を指定していない場合全体とする
        
        var type = null;
        var regExp = null;
        var op = [];
        var start = function(e){
            if (type != null) return;
            if (e && e.type.match(/touch/g))
                type = "touch";
            else
                type = "mouse";
            if (e && e.targetTouches) e = e.targetTouches[0];
            regExp = new RegExp(type, "g");
            op = getMousePosition(e);
        }
        
        var move = function(e){
            if (!type) return;
            if (e && !e.type.match(regExp)) return;
            if (e && e.targetTouches) e = e.targetTouches[0];
            var np = getMousePosition(e);
            var dx = np[0] - op[0], dy = np[1] - op[1];
            moveElement(target, dx, dy);
            op = np;
        }
        var end = function(e){
            if (!type) return;
            if (e && !e.type.match(regExp)) return;
            if (e && e.targetTouches) e = e.targetTouches[0];
            var np = getMousePosition(e);
            var dx = np[0] - op[0], dy = np[1] - op[1];
            moveElement(target, dx, dy);
            type = null;
        }
        
        if (document.addEventListener) {
            document.addEventListener("mouseup", end, false);
            document.addEventListener("touchmove", function(event){
                if (type == "touch") event.preventDefault();
                return false;
            }, false);
        } else {
            document.attachEvent("onmouseup", end)
        }
        
        // addEventListenerはイベントの伝播の処理が面倒なのでここでは直接代入
        handle.onmousedown = start;
        handle.onmousemove = move;
        handle.onmouseup = end;
        
        handle.ontouchstart = start;
        handle.ontouchmove = move;
        handle.ontouchend = end;
        
        /* 選択処理への対策 */
        handle.onselectstart = function() {
            return false;
        }
    }
    that.setDragAndDropListener = setDragAndDropListener;
    
    return that;
})();



使用法は、display: absolute;(fixed)な要素のインスタンスを取得して、DDHandlersetDragAndDropListener(対象オブジェクト);と実行するのみです。
サンプルもおいておきます。

要素ドラッグサンプル
141230.html


可読性や構造の簡潔さはだいぶ向上しているように思えます。(やっていることは同じですが)

過去に書いたコードと、現在書けるコードを見比べてみるのもなかなか面白いですね。
   JavaScript    TB(0)    CM(0)    EDIT    ページ↑

"Penny in the air."と"Penny drops."

久々にイディオムの記事でも書こうと思います。
この①"Penny in the air."または"The penny in the air."と②"Penny drops."または"The penny drops."という表現、(Doctor Whoなら各シーズンに1,2回は登場するくらいには)そこそこ使われていますが、日本語で紹介しているサイトがあまりないので、こちらを紹介します。

どちらも、基本的にイギリス英語で使われる表現です。意味は、①「まだ理解できていない」、②「合点がいった」という感じでしょうか。特に、②の「合点がいった」というのは、はじめは重要だと思わなかったことに対して、後から「そういうことだったのか!」と合点がいく様子を表します。"I got it."や"I'm getting that."と似た表現ですが、第三者が独り言のように"And penny drops."という(つぶやく)ことで、「わかったのね。」「やっとわかったか。」という使われ方をすることもあるようです。

意味はここまでですが、せっかくなので由来も調べてみました。

共通して登場するこの"penny"という単語は、イギリスの通貨『ポンド』の補助単位『ペニー(複数形ペンス)』の意味です。日本でいえば、100円玉や500円玉みたいな感じです。

ここで、"penny"を500円玉のイメージで解釈すると、①「500円玉が宙に浮いているという状態」、②「500円玉が落ちた」ということになりますが…よくわかりませんね。

辞書サイトThe Phrase Finderの"The penny drops"の項目によると、

『ごった返す自動販売機の順番を待つ人』というイメージがもっともな説明に思える。(むしろそれが由来でなければこの表現がどんな様子なのかイメージ想像し辛い。)

だそうです。

つまり、①500円玉を手に持って(このときは宙に浮いています)、順番はまだかまだかと待つ状態、②ついに自分の順番が来て、「やっと硬貨を入れて商品を購入できる」という状態、ということですね。もしかしたら、ディズニーシーの、機械仕掛けで銅板に模様を刻印するコイン自販機のようなイメージが近いのかもしれません。

それが、その様子を①言われたことを理解できていない状態、②ようやく「やっと意味がわかったぞ。」「あれはこういう意味だったのか。」となった状態、を表すようになった、ということですね。
#親や先生に受けた説教の意味が何年も経ってからわかるというのは、誰にでも一度や二度は経験があるのではないでしょうか。

最後に、作中での使用例を紹介します。

以下は、MELSがAMYに「あなたには彼(=RORY)がいるじゃない。」と言ったところに、AMYが「彼(=RORY)はゲイなのよ。あり得ないわ。」と返した後の場面です。

RORY: No. No, I'm not. 「いやいや、違うって。」
AMY: Course you are. Don't be stupid. In the whole time I've known you, when have you shown any interest in a girl?「なんでかって、とぼけないでよ。私があなたと知り合ってから、一度でも女の子に興味を示したことがある?」

MELS: Penny in the air.「わかってないわね。」

AMY: [...] I've seen you practically every day. Name one girl you've paid the slightest bit of attention to?「あなたのことを毎日間近に見てきたけど、興味を持った女の子の名前の一人くらい挙げてみなさいよ。」

(ここでローリーがその場から逃げ出してしまう)

AMY: Oh, my God! Rory! 「そんな、そういうことなのね。RORY!」

MELS: And the penny drops.「やっとわかったか。」

2011 BBC Doctor Who " Let's Kill Hitler"より

RORYはAMYのことがずっと好きだった。でもAMYは気づかずに過ごしてきた。が、ここでようやくそれに気付いたというわけです。

---

以上です。
こういうスタイルで記事を書くのは初めてなので少し時間がかかってしまいましたが、これからも、なんじゃこりゃという表現があれば、紹介していこうと思います。
   English    TB(0)    CM(0)    EDIT    ページ↑

『なんとなく』の感覚からの語学

突然ですが、この写真。
英BBCのDoctor Whoというドラマのワンシーンですが、
141129.jpg
THE DAY OF THE DOCTOR 2013 BBC

どんな場面に見えますか?

表情からして、何か詠嘆しているように見えると思います。
たとえば、「休みが取れたら旅行に行きたいなぁ」とか、「なんて美しい絵なんだろう…」とか、「こんなに美しい絵を人生で二度も三度も見られるだろうか。」とか、そんな感じでしょう。文法的には、それぞれ「仮定法」「感嘆文」「修辞疑問文・反語」などと呼ばれるものです。

実際、このシーンのセリフは、

I could be a curator. I'd be great at curating.
[...]
I could retire and be the curator of this place.


日本語では、

館長になれたらなあ。僕ならきっと立派に務められることだろう。
(中略)
引退したら、ここの館長になりたいなあ。

というような感じです。若干意訳ですが。つまりこのシーンは仮定法(願望や想像を表現する文法)を使っているシーンですね。

ストーリーの詳細はともかく(この後に本当に館長になった未来の主人公と、↑の主人公が会話するシーンが続きます)、
何が言いたいかというと。

人間というのは不思議なもので、言葉や文化が違っても、感情表現の仕方は似るものです。
英語の知識があまりなくても、冒頭の写真を見れば、何かを夢見ているような、あるいは感動しているような、感じが伝わってくるのではないでしょうか。

外国語の学習においては、もちろん文法的な分類も重要です。しかし、もともと言葉や言語というものは、コミュニケーションの道具なのですから、このように「この人はどんなことを言っているのだろう」と想像するだけでも、文化の壁を越えて理解できるものがあるはずです。

そうした感覚を語学の入口(アプローチ)として用い、「じゃあ具体的にはどう表現すれば良いんだ?」という疑問を解決できるように学習することで、学習に対する抵抗感が減る(あるいはモチベーションが向上する)ということにもつながると思います。

---

昨日今日あたり、各地で初雪が観測されています。気温も急激に低下していますから、体調を崩さないように気を付けましょう。あと風呂場で脳梗塞になるやつも気を付けましょうね。
   雑談    TB(0)    CM(0)    EDIT    ページ↑

プロフィール

JDB Luigi

Author:JDB Luigi
どこにでもいるようなありふれた人間・・・という訳でもなく、かと言って怪しい宗教を信仰する変人という訳でも無い。

基本的に掲載しているコード等は煮ていただいても焼いていただいても結構ですが、利用は自己責任にてお願いいします。
また、バグ・アドバイス等もしあればよろしくお願いします。