Skip to content

Commit

Permalink
crop image widget
Browse files Browse the repository at this point in the history
  • Loading branch information
debian8 committed Mar 12, 2017
1 parent a005d9e commit c99410b
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 0 deletions.
25 changes: 25 additions & 0 deletions CropAsset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace mdm\widgets;

/**
* Description of CropAsset
*
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
* @since 1.0
*/
class CropAsset extends \yii\web\AssetBundle
{
public $sourcePath = '@mdm/widgets/assets';
public $js = [
'http://jcrop-cdn.tapmodo.com/v0.9.12/js/jquery.Jcrop.min.js',
'js/dcropbox.js'
];
public $css = [
'http://jcrop-cdn.tapmodo.com/v0.9.12/css/jquery.Jcrop.min.css'
];

public $depends = [
'yii\web\JqueryAsset',
];
}
71 changes: 71 additions & 0 deletions CropImage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

namespace mdm\widgets;

use yii\helpers\Html;
use yii\helpers\Json;

/**
* Description of CropImage
*
* @author Misbahul D Munir <misbahuldmunir@gmail.com>
* @since 1.0
*/
class CropImage extends \yii\widgets\InputWidget
{
/**
* @var array the HTML attributes for the input tag.
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
public $imgOptions = [];

/**
*
* @var array
*/
public $clientOptions = [];
/**
*
* @var string
*/
public $cropParam = 'crop';

/**
* @inheritdoc
*/
public function init()
{

parent::init();
}

/**
* @inheritdoc
*/
public function run()
{
$id = $this->options['id'] = $this->getId();

Html::addCssClass($this->options, 'dcorpbox');
Html::addCssClass($this->imgOptions, 'content');
CropAsset::register($this->getView());

$clientOptions = $this->clientOptions;
$this->imgOptions['id'] = $id . '-img';
$clientOptions['imgTemplate'] = Html::tag('img', '',$this->imgOptions);
$opts = Json::encode($clientOptions);
$js = "jQuery('#{$id}').dCropBox($opts);";
$this->getView()->registerJs($js);
$inputOptions = ['style' => 'visibility:hidden;', 'class' => 'file-input', 'id' => $id . '-file'];
if ($this->hasModel()) {
$fileInput = Html::activeFileInput($this->model, $this->attribute, $inputOptions);
} else {
$fileInput = Html::fileInput($this->name, $this->value, $inputOptions);
}
return $this->render('crop-image', [
'options' => $this->options,
'fileInput' => $fileInput,
'cropParam' => $this->cropParam,
]);
}
}
111 changes: 111 additions & 0 deletions assets/js/dcropbox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
(function () {

function updateCoords(c) {
var $element = this.$el;
var factor = this.zoomFactor;
$element.find('input[data-attr="x"]').val(c.x * factor);
$element.find('input[data-attr="y"]').val(c.y * factor);
$element.find('input[data-attr="w"]').val(c.w * factor);
$element.find('input[data-attr="h"]').val(c.h * factor);
}

function inputChange() {
var input = this;
var $el = $(this).closest('div.dcorpbox');
var id = $el.attr('id');
var imgId = id + '-img';
var opts = $el.data('dCropBox');

if (input.files && input.files[0]) {
if (opts.api) {
opts.api.destroy();
}
$el.children('div.container').html(opts.imgTemplate);

var reader = new FileReader();
reader.onload = function (e) {
$el.trigger('beforeLoadFile');
$el.find('input[data-attr="x"]').val('');
var $img = $('#' + imgId);
$img.attr('src', e.target.result);
var img = new Image();

img.onload = function () {
if ((opts.minWidth && img.width < opts.minWidth) ||
(opts.minHeight && img.width < opts.minHeight)) {
alert(opts.toSmallMsg);
return;
}
var factor = img.width / $img.width();
var params = {
onSelect: updateCoords,
};
var selection;
if (opts.minWidth || opts.minHeight) {
var minW = opts.minWidth / factor;
var minH = opts.minHeight / factor;
selection = [0, 0, minW, minH];
params = $.extend({}, params, {
minSize: [minW, minH],
});
}
opts.api = $.Jcrop('#' + imgId, $.extend({}, params, {
aspectRatio: opts.aspectRatio,
}, opts.jcrop || {}));
opts.api.$el = $el;
opts.api.zoomFactor = factor;

if (selection){
opts.api.setSelect(selection);
}
$el.trigger('afterLoadFile');
}
img.src = e.target.result;
}
reader.readAsDataURL(input.files[0]);
}
}

var methods = {
init: function (options) {
return this.each(function () {
var $this = $(this);
var opts = $.extend({}, defaults, options || {});

if (opts.minWidth && opts.minHeight == undefined) {
opts.minHeight = opts.minWidth / opts.aspectRatio;
} else if (opts.minHeight && opts.minWidth == undefined) {
opts.minWidth = opts.minHeight * opts.aspectRatio;
}
if(opts.button){
$(opts.button).click(function (){
methods.selectFile.call($this);
});
}
$this.data('dCropBox', opts);
$this.children(':input.file-input').change(inputChange);
});
},
selectFile: function () {
return this.each(function () {
$(this).children(':input.file-input').trigger('click');
});
}
}

var defaults = {
aspectRatio: 1,
toSmallMsg: 'Image to small',
}

$.fn.dCropBox = function (method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.dCropBox');
return false;
}
}
})();
18 changes: 18 additions & 0 deletions views/crop-image.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

use yii\web\View;
use yii\helpers\Html;

/* @var $this View */
?>

<div <?= Html::renderTagAttributes($options) ?> >
<div class="container"></div>
<div style="display: none;">
<input type="hidden" name="<?= $cropParam; ?>[x]" data-attr="x">
<input type="hidden" name="<?= $cropParam; ?>[y]" data-attr="y">
<input type="hidden" name="<?= $cropParam; ?>[w]" data-attr="w">
<input type="hidden" name="<?= $cropParam; ?>[h]" data-attr="h">
</div>
<?= $fileInput ?>
</div>

0 comments on commit c99410b

Please sign in to comment.