写真をアップロードして切り抜きが出来る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 スマホ用 切り替え 前回の記事のゲームですが、スマホだとサイズが合わなくてや

記事を読む

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

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

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

記事を読む

Wordpress VR Test

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

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

記事を読む

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

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

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

記事を読む

Javascript ノード の取得や挿入

Javascript ノードの取得や挿入

ノードの取得 ノードの取得(ダイレクトアクセス) document.getElementById

記事を読む

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

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

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

記事を読む

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

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

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

記事を読む

android javascript

Message

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

WordPress Twenty Seventeen function.php
WordPress twentyseventeen の function.php を見る – その2

前回の続きです。 次のスターターコンテンツは、今回のシンプルテン

WordPress Twenty Seventeen function.php
WordPress twentyseventeen の function.php を見る – その1

WordPress の最低限の機能だけのシンプルなテンプレートが欲しか

WordPress Warning エラー
WordPress フォルダー・ファイル系の関数 is_dir や opendir や exif_imagetype で Warning エラー

Wordpress の管理画面でフォルダーの中身を読み込む関数 ope

Wordpress 自作フォーム (チェックボックスなど)
WordPress 自作フォーム その3(チェックボックスなど)

以前、WordPress 自作フォーム その1の記事で Wordpre

Javascript ノード の取得や挿入
Javascript ノードの取得や挿入

ノードの取得 ノードの取得(ダイレクトアクセス) document

→もっと見る

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