かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

ぬるっと大きくなる画像を作る

画像をぬるぬると拡大・縮小して、さらに拡大縮小された画像でもマウスカーソルの位置は、拡大・縮小してないときと同じ座標を取りたかったんです。とりあえず動くのが出来たのでメモメモ。

MVC 4プロジェクト作成

jQueryとかで何かと試すにはASP.NET MVC4のプロジェクトがお手軽です。とりあえず基本で作ってnugetでjQueryの最新版を入れておきます。
あとは、HomeControllerとIndex.cshtmlを作って準備完了。

画像を準備

とりあえず、今回はdaruyanagi.pngという画像を使いました。

画像を置くdivタグのスタイル

画像が大きくなったときにはみ出た部分はスクロールするようにスタイルを作っておきます。

/* 画像のコンテナ */
#imageContainer {
    overflow: scroll;
    border: 1px solid black;
    width: 500px;
    height: 250px;
}

HTMLの作成

画像と画像サイズをリセットするボタンと、右クリックしたときの座標を取得するためのdivタグがある画面をさくっと作ります。

<h2>Index</h2>

<div id="imageContainer">
    <img id="daruyanagi" src="~/Content/daruyanagi.png" />
</div>
<input id="buttonReset" type="button" value="reset" />
<div id="log"></div>

画像の拡大と縮小

今回は拡大と元の大きさに戻すのしか実装しません。(手抜き)とりあえず画像の初期状態をjQueryのdataメソッドでとっておいて、必要に応じてanimateメソッドでスタイルのwidthをアニメーションさせます。画像をクリックすると少し大きくなって、右クリックすると座標が取得できて、リセットボタンを押すと画像のサイズが元に戻るJavaScript

// 初期状態の記録
function initializeImage(img) {
    img.data("default-width", img.css("width").replace("px", ""));
    img.data("scale", "1");
};
// リセット
function resetImage(img) {
    img.data("scale", "1");
    img.animate({ width: img.data("default-width") }, 500);
};

$(function () {
    var img = $("#daruyanagi");
    initializeImage(img);
    $("#buttonReset").click(function () {
        // リセットボタンが押されたらリセット
        resetImage(img);
    });

    img.click(function () {
        // クリックされたらちょっと拡大
        var scale = Number(img.data("scale"));
        scale *= 1.1;
        img.data("scale", scale);
        img.animate({width: Number(img.data("default-width") * scale)}, 500);
    });

    img.contextmenu(function (event) {
        // 右クリックされたら拡大率を考慮して座標を取得
        var scale = Number(img.data("scale"));
        $("<p>").text(event.offsetX / scale + ", " + event.offsetY / scale).appendTo("#log");
        event.preventDefault();
    });

});

実行

起動直後で黒い目玉の真ん中で右クリックしたところ。

目玉の位置は170, 63ぐらいの位置にあることがわかります。画像を10回くらい左クリックして黒い目玉の真ん中を右クリックしたところ。

画像はでかくなってるけど、目玉をクリックした座標は変わってない(誤差の範囲)になってます。

ソース全体

Index.cshtmlの全体です。

@{
    ViewBag.Title = "Index";
}
<style type="text/css">
    /* 画像のコンテナ */
    #imageContainer {
       overflow: scroll;
       border: 1px solid black;
       width: 500px;
       height: 250px;
    }
</style>

<h2>Index</h2>

<div id="imageContainer">
    <img id="daruyanagi" src="~/Content/daruyanagi.png" />
</div>
<input id="buttonReset" type="button" value="reset" />
<div id="log"></div>

@section scripts {
    <script type="text/javascript">
        // 初期状態の記録
        function initializeImage(img) {
            img.data("default-width", img.css("width").replace("px", ""));
            img.data("scale", "1");
        };
        // リセット
        function resetImage(img) {
            img.data("scale", "1");
            img.animate({ width: img.data("default-width") }, 500);
        };

        $(function () {
            var img = $("#daruyanagi");
            initializeImage(img);
            $("#buttonReset").click(function () {
                // リセットボタンが押されたらリセット
                resetImage(img);
            });

            img.click(function () {
                // クリックされたらちょっと拡大
                var scale = Number(img.data("scale"));
                scale *= 1.1;
                img.data("scale", scale);
                img.animate({width: Number(img.data("default-width") * scale)}, 500);
            });

            img.contextmenu(function (event) {
                // 右クリックされたら拡大率を考慮して座標を取得
                var scale = Number(img.data("scale"));
                $("<p>").text(event.offsetX / scale + ", " + event.offsetY / scale).appendTo("#log");
                event.preventDefault();
            });

        });
    </script>
}

ここらへんを、もうちょっと作りこんでオレオレjQueryプラグインにしておけばいいかな…。

求む

もうちょっといい方法…。