写真をアップロードして切り抜きが出来る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

関連記事

マウスドラッグ

マウスドラッグ で ボール投げたい

アイキャッチ画像がマウスドラッグを描いたつもりが、子供の好きなあのボールみたいになりました。

記事を読む

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

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

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

記事を読む

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

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

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

記事を読む

Wordpress VR Test

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

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

記事を読む

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

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

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

記事を読む

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

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

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

記事を読む

android javascript

Message

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

マウスドラッグ
マウスドラッグ で ボール投げたい

アイキャッチ画像がマウスドラッグを描いたつもりが、子供の好きなあのボー

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

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

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

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

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

Git Hub の cropbox 写真をアップロードしてカット出来

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

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

→もっと見る

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