Создаем web-part, подключаем скрипты
<script src="/_layouts/15/cropper/cropper.js"></script>
<link href="/_layouts/15/cropper/cropper.css" rel="stylesheet" />
<script src="/_layouts/15/cropper/jquery-cropper.js"></script>
<div class="form-ui ui blue segment">
<span class="header">Параметры</span>
<div class="form-row flex">
<div class="form-item">
<span class="title-ui">X</span>
<asp:TextBox ID="_posX" CssClass="form-input" runat="server" style="width: 50px;"></asp:TextBox>
</div>
<div class="form-item">
<span class="title-ui">Y</span>
<asp:TextBox ID="_posY" CssClass="form-input" runat="server" style="width: 50px;"></asp:TextBox>
</div>
<div class="form-item">
<span class="title-ui">Width</span>
<asp:TextBox ID="_width" CssClass="form-input" runat="server" style="width: 50px;"></asp:TextBox>
</div>
<div class="form-item">
<span class="title-ui">Height</span>
<asp:TextBox ID="_height" CssClass="form-input" runat="server" style="width: 50px;"></asp:TextBox>
</div>
<div class="form-item">
<span class="title-ui">Rotate</span>
<asp:TextBox ID="_rotate" CssClass="form-input" runat="server" style="width: 50px;"></asp:TextBox>
</div>
<div class="form-item">
<span class="title-ui">ScaleX</span>
<asp:TextBox ID="_scaleX" CssClass="form-input" runat="server" style="width: 50px;"></asp:TextBox>
</div>
<div class="form-item">
<span class="title-ui">ScaleY</span>
<asp:TextBox ID="_scaleY" CssClass="form-input" runat="server" style="width: 50px;"></asp:TextBox>
</div>
<div class="form-item">
<span class="title-ui">Соотношение сторон</span>
<asp:RadioButtonList CssClass="aspect-ratio" ID="_aspectRatio" runat="server" RepeatDirection="Horizontal">
<asp:ListItem Value="1" Selected="True">1:1</asp:ListItem>
<asp:ListItem Value="1.7777777777777777">16:9</asp:ListItem>
<asp:ListItem Value="1.3333333333333333">4:3</asp:ListItem>
<asp:ListItem Value="0.6666666666666666">2:3</asp:ListItem>
<asp:ListItem Value="NaN">Произвольный</asp:ListItem>
</asp:RadioButtonList>
</div>
</div>
<div class="form-row flex">
<div class="form-item">
<input type="file" id="_inputImage" name="file" class="form-file-upload" accept=".jpg,.jpeg,.png,.gif,.bmp,.tiff">
</div>
<div class="form-item">
<button class="action-btn" type="button" data-method="zoom" data-option="0.1" title="Увеличить">
<i class="fa-solid fa-magnifying-glass-plus"></i>
</button>
</div>
<div class="form-item">
<button class="action-btn" type="button" data-method="zoom" data-option="-0.1" title="Уменьшить">
<i class="fa-solid fa-magnifying-glass-minus"></i>
</button>
</div>
<div class="form-item">
<button class="action-btn" type="button" data-method="move" data-option="-10" data-second-option="0" title="Подвинуть влево">
<i class="fa-solid fa-arrow-left"></i>
</button>
</div>
<div class="form-item">
<button class="action-btn" type="button" data-method="move" data-option="10" data-second-option="0" title="Подвинуть вправо">
<i class="fa-solid fa-arrow-right"></i>
</button>
</div>
<div class="form-item">
<button class="action-btn" type="button" data-method="move" data-option="0" data-second-option="-10" title="Подвинуть вверх">
<i class="fa-solid fa-arrow-up"></i>
</button>
</div>
<div class="form-item">
<button class="action-btn" type="button" data-method="move" data-option="0" data-second-option="10" title="Подвинуть вниз">
<i class="fa-solid fa-arrow-down"></i>
</button>
</div>
<div class="form-item">
<button class="action-btn" type="button" data-method="rotate" data-option="-45" title="Вращать влево">
<i class="fa-solid fa-rotate-left"></i>
</button>
</div>
<div class="form-item">
<button class="action-btn" type="button" data-method="rotate" data-option="45" title="Вращать вправо">
<i class="fa-solid fa-rotate-right"></i>
</button>
</div>
<div class="form-item">
<button class="action-btn" type="button" data-method="scaleX" data-option="-1" title="Отразить по горизонтали">
<i class="fa-solid fa-arrows-left-right"></i>
</button>
</div>
<div class="form-item">
<button class="action-btn" type="button" data-method="scaleY" data-option="-1" title="Отразить по вертикали">
<i class="fa-solid fa-arrows-up-down"></i>
</button>
</div>
<div class="form-item">
<button class="action-btn" type="button" data-method="reset" title="Сброс">
<i class="fa-solid fa-rotate"></i>
</button>
</div>
<div class="form-item">
<button class="action-btn" type="button" data-method="getCroppedCanvas" data-option="{ 'maxWidth': 4096, 'maxHeight': 4096 }" title="Подтвердить">
<i class="fa-solid fa-check"></i>
</button>
</div>
<div class="form-item">
<a class="action-btn" id="download" href="/" title="Сохранить" style="display:none;" ><i class="fa-solid fa-download"></i></a>
</div>
</div>
</div>
<div>
<asp:Image ID="_image" runat="server" />
</div>
Добавляем код в code behind
private SPSite oSite;
private SPWeb oWeb;
private string imgURL;
protected void Page_Load(object sender, EventArgs e)
{
oSite = SPContext.Current.Site;
oWeb = SPContext.Current.Web;
_image.CssClass = "cropper";
if (Page.Request.Params["source"] != null)
{
imgURL = Page.Request.Params["source"];
_image.ImageUrl = imgURL;
}
}
На страницу добавляем JS
<script language="javascript" type="text/javascript">
$(document).ready(function() {
$("div[class='ms-cui-topBar2']").hide();
$("table[class='ms-webpartPage-root']").css("border-spacing", "0");
$(".ms-webpartPage-root").css("border-spacing", "0");
var URL = window.URL || window.webkitURL;
var $image = $('.cropper');
var $download = $('#download');
var $inputImage = $("input[id$='_inputImage']");
$image.hide();
setTimeout(InitCropper, 100);
function InitCropper()
{
$image.show();
var $dataX = $("input[id$='posX']");
$dataX.val($image.width());
var $dataY = $("input[id$='posY']");
$dataY.val($image.height());
var $dataHeight = $("input[id$='height']");
$dataHeight.val($image.height());
var $dataWidth = $("input[id$='width']");
$dataWidth.val($image.width());
var $dataRotate = $("input[id$='rotate']");
$dataRotate.val("0");
var $dataScaleX = $("input[id$='scaleX']");
$dataScaleX.val("0");
var $dataScaleY = $("input[id$='scaleY']");
$dataScaleY.val("0");
var options = {
aspectRatio: 1 / 1,
preview: '.img-preview',
//data:{ //define cropbox size
//width: 200,
//height: 90,
//},
crop: function (e) {
$dataX.val(Math.round(e.detail.x));
$dataY.val(Math.round(e.detail.y));
$dataHeight.val(Math.round(e.detail.height));
$dataWidth.val(Math.round(e.detail.width));
//$dataHeight.val(200);
//$dataWidth.val(200);
$dataRotate.val(e.detail.rotate);
$dataScaleX.val(e.detail.scaleX);
$dataScaleY.val(e.detail.scaleY);
}
};
var $aspectRatio = $('.aspect-ratio');
var $actionBtn = $('.action-btn');
var originalImageURL = $image.attr('src');
var uploadedImageName = 'cropped.jpg';
var uploadedImageType = 'image/jpeg';
var uploadedImageURL;
/*
$image.cropper({
//aspectRatio: 16 / 9,
crop: function(e) {
$dataX.val(Math.round(e.detail.x));
$dataY.val(Math.round(e.detail.y));
$dataHeight.val(Math.round(e.detail.height));
$dataWidth.val(Math.round(e.detail.width));
$dataRotate.val(e.detail.rotate);
$dataScaleX.val(e.detail.scaleX);
$dataScaleY.val(e.detail.scaleY);
}
});
*/
// Get the Cropper.js instance after initialized
var cropper = $image.data('cropper');
// Cropper
$image.on({
ready: function (e) {
//console.log(e.type);
},
cropstart: function (e) {
//console.log(e.type, e.detail.action);
},
cropmove: function (e) {
//console.log(e.type, e.detail.action);
},
cropend: function (e) {
//console.log(e.type, e.detail.action);
},
crop: function (e) {
//console.log(e.type);
},
zoom: function (e) {
//console.log(e.type, e.detail.ratio);
}
}).cropper(options);
// Соотношение сторон
$aspectRatio.on('change', 'input', function () {
var $this = $(this);
//var name = $this.attr('name');
//var type = $this.prop('type');
var cropBoxData;
var canvasData;
if (!$image.data('cropper')) {
return;
}
/*
if (type === 'checkbox') {
options[name] = $this.prop('checked');
cropBoxData = $image.cropper('getCropBoxData');
canvasData = $image.cropper('getCanvasData');
options.ready = function () {
$image.cropper('setCropBoxData', cropBoxData);
$image.cropper('setCanvasData', canvasData);
};
}
else */
//if (type === 'radio')
//{
options["aspectRatio"] = $this.val();
//}
$image.cropper('destroy').cropper(options);
});
// Download
if (typeof $download[0].download === 'undefined') {
$download.addClass('disabled');
}
// Кнопки
$actionBtn.click(function() {
var $this = $(this);
var data = $this.data();
var cropper = $image.data('cropper');
var cropped;
var $target;
var result;
if ($this.prop('disabled') || $this.hasClass('disabled')) {
return;
}
if (cropper && data.method) {
data = $.extend({}, data); // Clone a new one
if (typeof data.target !== 'undefined') {
$target = $(data.target);
if (typeof data.option === 'undefined') {
try
{
data.option = JSON.parse($target.val());
} catch (e)
{
console.log(e.message);
}
}
}
cropped = cropper.cropped;
switch (data.method)
{
case 'rotate':
if (cropped && options.viewMode > 0)
{
$image.cropper('clear');
}
break;
case 'getCroppedCanvas':
if (uploadedImageType === 'image/jpeg')
{
if (!data.option)
{
data.option = {};
}
data.option.fillColor = '#fff';
}
break;
}
result = $image.cropper(data.method, data.option, data.secondOption);
switch (data.method) {
case 'rotate':
if (cropped && options.viewMode > 0)
{
$image.cropper('crop');
}
break;
case 'scaleX':
case 'scaleY':
$(this).data('option', -data.option);
break;
case 'getCroppedCanvas':
if (result)
{
//console.log(result.toDataURL(uploadedImageType));
//window.open(result.toDataURL(uploadedImageType), '_blank').focus();
$download.attr('href', result.toDataURL(uploadedImageType));
$download.css("display", "block")
// Bootstrap's Modal
//$('#getCroppedCanvasModal').modal().find('.modal-body').html(result);
if (!$download.hasClass('disabled'))
{
download.download = uploadedImageName;
$download.attr('href', result.toDataURL(uploadedImageType));
}
}
break;
case 'destroy':
if (uploadedImageURL)
{
URL.revokeObjectURL(uploadedImageURL);
uploadedImageURL = '';
$image.attr('src', originalImageURL);
}
break;
}
if ($.isPlainObject(result) && $target)
{
try
{
$target.val(JSON.stringify(result));
}
catch (e)
{
console.log(e.message);
}
}
}
});
// Keyboard
$(document.body).on('keydown', function (e) {
if (e.target !== this || !$image.data('cropper') || this.scrollTop > 300)
{
return;
}
switch (e.which) {
case 37:
e.preventDefault();
$image.cropper('move', -1, 0);
break;
case 38:
e.preventDefault();
$image.cropper('move', 0, -1);
break;
case 39:
e.preventDefault();
$image.cropper('move', 1, 0);
break;
case 40:
e.preventDefault();
$image.cropper('move', 0, 1);
break;
}
});
// Импорт изображения
if (URL)
{
$inputImage.change(function () {
var files = this.files;
var file;
if (!$image.data('cropper'))
{
return;
}
if (files && files.length)
{
file = files[0];
if (/^image\/\w+$/.test(file.type))
{
uploadedImageName = file.name;
uploadedImageType = file.type;
if (uploadedImageURL)
{
URL.revokeObjectURL(uploadedImageURL);
}
uploadedImageURL = URL.createObjectURL(file);
$image.cropper('destroy').attr('src', uploadedImageURL).cropper(options);
$inputImage.val('');
$download.css("display", "none")
}
else
{
window.alert('Пожалуйста, выберете файл с изображением');
}
}
});
}
else
{
$inputImage.prop('disabled', true).parent().addClass('disabled');
}
}
});
</script>
