写真をアップロードして切り抜きが出来るcropboxにタッチイベントを付けてみる

公開日: : android, javascript

画像加工 cropbox.js

Git Hub の cropbox

写真をアップロードしてカット出来るjQueryのプラグイン cropbox というものが Git Hub にあり、手軽に設置出来て気に入りました。

cropbox のスクリーンショットはこんな感じです。デモは一番最後にあります。
画像加工 cropbox.js
cropbox は、パソコンだとマウスで移動できるし、スクロールで拡大・縮小もついていますが、スマホだと出来ないので、タッチイベントを追加してみようと思います。

cropbox の設置

index.html と cropbox.js と style.css を以下のように設置します。

index.html

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js"></script>
<![endif]-->
<title>Tinny Cropper</title>
<link rel="stylesheet" href="style.css" type="text/css" />
</head>
<body>
<script src="cropbox.js"></script>
<div class="container">
    <div class="imageBox">
        <div class="thumbBox"></div>
        <div class="spinner" style="display: none">Loading...</div>
    </div>
    <div class="action">
        <input type="file" id="file" style="float:left; width: 250px">
        <input type="button" id="btnCrop" value="Crop" style="float: right">
        <input type="button" id="btnZoomIn" value="+" style="float: right">
        <input type="button" id="btnZoomOut" value="-" style="float: right">
    </div>
    <div class="cropped">

    </div>
</div>
<script type="text/javascript">
    window.onload = function() {
        var options =
        {
            imageBox: '.imageBox',
            thumbBox: '.thumbBox',
            spinner: '.spinner',
            imgSrc: 'avatar.png'
        }
        var cropper;
        document.querySelector('#file').addEventListener('change', function(){
            var reader = new FileReader();
            reader.onload = function(e) {
                options.imgSrc = e.target.result;
                cropper = new cropbox(options);
            }
            reader.readAsDataURL(this.files[0]);
            this.files = [];
        })
        document.querySelector('#btnCrop').addEventListener('click', function(){
            var img = cropper.getDataURL()
            document.querySelector('.cropped').innerHTML += '<img src="'+img+'">';
        })
        document.querySelector('#btnZoomIn').addEventListener('click', function(){
            cropper.zoomIn();
        })
        document.querySelector('#btnZoomOut').addEventListener('click', function(){
            cropper.zoomOut();
        })
    };
</script>
</body>
</html>

style.css

.container{
	position: absolute;
	top: 10%; left: 10%; right: 0; bottom: 0;
}
.action{
	width: 400px;
	height: 30px;
	margin: 10px 0;
}
.cropped>img{
	margin-right: 10px;
}
.imageBox{
    position: relative;
    height: 400px;
    width: 400px;
    border:1px solid #aaa;
    background: #fff;
    overflow: hidden;
    background-repeat: no-repeat;
    cursor:move;
}
.imageBox .thumbBox{
    position: absolute;
    top: 50%;
    left: 50%;
    width: 200px;
    height: 200px;
    margin-top: -100px;
    margin-left: -100px;
    box-sizing: border-box;
    border: 1px solid rgb(102, 102, 102);
    box-shadow: 0 0 0 1000px rgba(0, 0, 0, 0.5);
    background: none repeat scroll 0% 0% transparent;
}
.imageBox .spinner{
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    text-align: center;
    line-height: 400px;
    background: rgba(0,0,0,0.7);
}

cropbox.js

var cropbox = function(options){
    var el = document.querySelector(options.imageBox),
    obj =
    {
        state : {},
        ratio : 1,
        options : options,
        imageBox : el,
        thumbBox : el.querySelector(options.thumbBox),
        spinner : el.querySelector(options.spinner),
        image : new Image(),
        getDataURL: function ()
        {
            var width = this.thumbBox.clientWidth,
                height = this.thumbBox.clientHeight,
                canvas = document.createElement("canvas"),
                dim = el.style.backgroundPosition.split(' '),
                size = el.style.backgroundSize.split(' '),
                dx = parseInt(dim[0]) - el.clientWidth/2 + width/2,
                dy = parseInt(dim[1]) - el.clientHeight/2 + height/2,
                dw = parseInt(size[0]),
                dh = parseInt(size[1]),
                sh = parseInt(this.image.height),
                sw = parseInt(this.image.width);

            canvas.width = width;
            canvas.height = height;
            var context = canvas.getContext("2d");
            context.drawImage(this.image, 0, 0, sw, sh, dx, dy, dw, dh);
            var imageData = canvas.toDataURL('image/png');
            return imageData;
        },
        getBlob: function()
        {
            var imageData = this.getDataURL();
            var b64 = imageData.replace('data:image/png;base64,','');
            var binary = atob(b64);
            var array = [];
            for (var i = 0; i < binary.length; i++) {
                array.push(binary.charCodeAt(i));
            }
            return  new Blob([new Uint8Array(array)], {type: 'image/png'});
        },
        zoomIn: function ()
        {
            this.ratio*=1.1;
            setBackground();
        },
        zoomOut: function ()
        {
            this.ratio*=0.9;
            setBackground();
        }
    },
    attachEvent = function(node, event, cb)
    {
        if (node.attachEvent)
            node.attachEvent('on'+event, cb);
        else if (node.addEventListener)
            node.addEventListener(event, cb);
    },
    detachEvent = function(node, event, cb)
    {
        if(node.detachEvent) {
            node.detachEvent('on'+event, cb);
        }
        else if(node.removeEventListener) {
            node.removeEventListener(event, render);
        }
    },
    stopEvent = function (e) {
        if(window.event) e.cancelBubble = true;
        else e.stopImmediatePropagation();
    },
    setBackground = function()
    {
        var w =  parseInt(obj.image.width)*obj.ratio;
        var h =  parseInt(obj.image.height)*obj.ratio;

        var pw = (el.clientWidth - w) / 2;
        var ph = (el.clientHeight - h) / 2;

        el.setAttribute('style',
                'background-image: url(' + obj.image.src + '); ' +
                'background-size: ' + w +'px ' + h + 'px; ' +
                'background-position: ' + pw + 'px ' + ph + 'px; ' +
                'background-repeat: no-repeat');
    },
    imgMouseDown = function(e)
    {
        stopEvent(e);

        obj.state.dragable = true;
        obj.state.mouseX = e.clientX;
        obj.state.mouseY = e.clientY;
    },
    imgMouseMove = function(e)
    {
        stopEvent(e);

        if (obj.state.dragable)
        {
            var x = e.clientX - obj.state.mouseX;
            var y = e.clientY - obj.state.mouseY;

            var bg = el.style.backgroundPosition.split(' ');

            var bgX = x + parseInt(bg[0]);
            var bgY = y + parseInt(bg[1]);

            el.style.backgroundPosition = bgX +'px ' + bgY + 'px';

            obj.state.mouseX = e.clientX;
            obj.state.mouseY = e.clientY;
        }
    },
    imgMouseUp = function(e)
    {
        stopEvent(e);
        obj.state.dragable = false;
    },
    zoomImage = function(e)
    {
        var evt=window.event || e;
        var delta=evt.detail? evt.detail*(-120) : evt.wheelDelta;
        delta > -120 ? obj.ratio*=1.1 : obj.ratio*=0.9;
        setBackground();
    }

    obj.spinner.style.display = 'block';
    obj.image.onload = function() {
        obj.spinner.style.display = 'none';
        setBackground();

        attachEvent(el, 'mousedown', imgMouseDown);
        attachEvent(el, 'mousemove', imgMouseMove);
        attachEvent(document.body, 'mouseup', imgMouseUp);
        var mousewheel = (/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel';
        attachEvent(el, mousewheel, zoomImage);
    };
    obj.image.src = options.imgSrc;
    attachEvent(el, 'DOMNodeRemoved', function(){detachEvent(document.body, 'DOMNodeRemoved', imgMouseUp)});

    return obj;
};

Git Hub の MITライセンス とは?

cropbox はGit HubのMITライセンスがついています。

MITライセンス

MITライセンスのもとで配布されているものは、改変でも、再配布でも、商用利用でも、有料販売でも、どんなことにでも自由に無料でつかうことができます。

<参考サイト>
MITライセンスってなに?どうやって使うの?商用でも無料で使えるの?

という訳で、cropbox.js と style.css にこんな感じで付けておけばOKかと思われます。

/**
 * Copyright (c) 2014 Nguyen Hong Khanh
 * Copyright (c) 2014 ezgoing
 * Released under the MIT license
 * https://github.com/hongkhanh/cropbox/blob/master/LICENSE
 */

cropbox にタッチイベントを追加してみる

6行目辺りの ratio : 1,の下に以下を追加します。

touchmove_bar : 0,
touchstart_bar : 0,

139行目辺りの attachEvent(el, mousewheel…行の下にタッチイベントを追加します。

attachEvent(el, 'touchstart', imgTouchstart,false);
attachEvent(el, 'touchmove', imgTouchmove);
attachEvent(el, 'touchend', imgTouchend);

122行目辺りの zoomImage の下に以下のタッチイベントに対する関数を追加します。

,
imgTouchstart = function(e){
	if(e.touches.length > 1){
		this.touchstart_bar =Math.abs(e.touches[1].pageX - e.touches[0].pageX)*Math.abs(e.touches[1].pageY - e.touches[0].pageY);
	}
	else{
		stopEvent(e);
		obj.state.dragable = true;
		obj.state.mouseX = e.touches[0].pageX;
		obj.state.mouseY = e.touches[0].pageY;
	}
},
imgTouchmove = function(e){
	if(e.touches.length > 1){
		this.touchmove_bar = Math.abs(e.touches[1].pageX - e.touches[0].pageX)*Math.abs(e.touches[1].pageY - e.touches[0].pageY);
		var area_bar = this.touchstart_bar-this.touchmove_bar;
		area_bar<0 ? obj.ratio*=1.1 : obj.ratio*=0.9;
		setBackground();
	}
	else{
		stopEvent(e);
		if (obj.state.dragable){
			var x = e.touches[0].pageX - obj.state.mouseX;
			var y = e.touches[0].pageY - obj.state.mouseY;
			var bg = el.style.backgroundPosition.split(' ');
			var bgX = x + parseInt(bg[0]);
			var bgY = y + parseInt(bg[1]);
			el.style.backgroundPosition = bgX +'px ' + bgY + 'px';
			obj.state.mouseX = e.touches[0].pageX;
			obj.state.mouseY = e.touches[0].pageY;
		}
	}
},
imgTouchend = function(e){
	if(e.touches.length == 1){
		 stopEvent(e);
       	 obj.state.dragable = false;
	}
}

cropbox にタッチイベントを追加してみたデモです。
DEMO を見る
javascriptを変更した全文はこちらです → cropbox_mobile.js

関連記事

JavaScript タイピングゲーム スマホ用

Javascript タイピング ゲーム スマホ用 をつくる

JavaScript スマホ用 切り替え 前回の記事のゲームですが、スマホだとサイズが合わなくてや

記事を読む

Javascript 写真ギャラリー サムネイルスライド横 レスポンシブ対応

Javascript 写真ギャラリー サムネイルスライド横 レスポンシブ対応

Javascript でマウスドラッグのテストをしていきます。 分かりやすいように、ボールを投げる

記事を読む

Wordpress VR Test

WordPress で VR させて、360°のパノラマ画像を表示する

WordPress.com内ショートコードで VR させる WordPress.com内で、VR(

記事を読む

Three.jsで360°パノラマ画像を VR させる

Three.jsで360°パノラマ画像を VR させる

Three.jsで360°パノラマ画像を VR させる VRを作るのに前回のプラグイン「WP-VR

記事を読む

画像の拡大・縮小 タッチイベント

画像の拡大縮小を javascript の touch イベントでやってみる

画像の幅と高さを取得 まずは、neko.jpg という画像を用意して、幅と高さを取得します。

記事を読む

JavaScript 規制標識 タイピングゲーム(自分用・激ムズ)

HTML5 audio タグ を使って音声を出す

HTML5からaudioタグを使えば、Flashなどのプラグインを使わなくてもブラウザ上で音声を再生

記事を読む

android javascript

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Wordpress 自作フォーム 2(注意点とエラー:This is somewhat embarrassing, isn’t it? など)
WordPress 自作フォーム その2(注意点とエラー:This is somewhat embarrassing, isn’t it? など)

前回(WordPress 自作フォーム 1)のつづきです。 今回は細

Wordpress 自作フォーム
WordPress 自作フォーム その1(サンプルと設置)

Wordpress でプラグインを使わずにフォームをやってみます。

Javascript 写真ギャラリー サムネイルスライド横 レスポンシブ対応
Javascript 写真ギャラリー サムネイルスライド横 レスポンシブ対応

Javascript でマウスドラッグのテストをしていきます。 分か

Three.jsで360°パノラマ画像を VR させる
Three.jsで360°パノラマ画像を VR させる

Three.jsで360°パノラマ画像を VR させる VRを作るの

Wordpress VR Test
WordPress で VR させて、360°のパノラマ画像を表示する

WordPress.com内ショートコードで VR させる Word

→もっと見る

にほんブログ村 IT技術ブログへ にほんブログ村 IT技術ブログ PHPへ にほんブログ村 IT技術ブログ WordPressへ
にほんブログ村 FC2 Blog Ranking
PAGE TOP ↑