https://segmentfault.com/a/1190000012818387
JQuery 插件图片裁剪插件cropper.js使用,上传,后台怎么处理
https://blog.csdn.net/wxl1555/article/details/79650062
图片上传裁剪插件cropper.js的API详解
兼容性较好,之前的php也是用得这个。
http://www.webhek.com/post/save-canvas-to-image.html
将画布(canvas)图像保存成本地图片的方法
https://www.jianshu.com/p/5d76ec4c97e7
js base64与canvas base64
https://fengyuanchen.github.io/cropperjs/
cropper官网,注意用jquery版本
代码实例:
@extends("layouts.frame")
@section("title")
{{$title}}
@stop
@section('mydefinecss')
<!-- cropper css -->
<link rel="stylesheet" href="{{ URL::asset('plugins/cropper/cropper.css') }}" />
<style>
.avatar-wrapper {
margin-top: 15px;
overflow: hidden;
}
.avatar-wrapper img {
display: block;
height: 300px;
max-width: 100%;
}
.avatar-preview {
float: left;
margin-top: 15px;
margin-right: 15px;
border: 1px solid #eee;
border-radius: 4px;
background-color: #fff;
overflow: hidden;
}
.avatar-preview:hover {
border-color: #ccf;
box-shadow: 0 0 5px rgba(0,0,0,.15);
}
.avatar-preview img {
width: 100%;
}
.preview-md {
height: 100px;
width: 100px;
}
.preview-sm {
height: 50px;
width: 50px;
}
.radio-label{
margin-bottom: 10px;
display: block;
width: 120px;
}
</style>
@endsection
@section("content")
<div class="card-body">
<div class="card-title">
<i class="fas fa-list"></i> {{$title}}
{{--<a class="btn btn-sm btn-outline-primary ml-5" href="{{route('images.create')}}"> 添加图片</a>--}}
</div>
<div class="row mt-2 mb-2">
<div class="col-12">
<form action="{{route('images.store')}}" method="post">
@csrf
<input type="hidden" name="images_guid" value="{{ $images_guid }}"/>
<input type="hidden" name="originurl" id="originurl" value=""/>
<input type="hidden" name="largeurl" id="largeurl" value=""/>
<div class="row mb-4 mt-4">
<div class="col-md-4">
<div class="form-group row">
<label for="fld_title" id="lbl_title"
class="fld_Chn_label col-sm-3 col-form-label text-right">标题</label>
<input type="text" class=" form-control col-md-8"
id="fld_title" name="title" value="">
</div>
<div class="form-group row">
<label for="fld_titlecolor" id="lbl_titlecolor"
class="fld_Chn_label col-sm-3 col-form-label text-right">标题颜色</label>
<input class=" form-control col-2" id="fld_titlecolor" type="color" name="titlecolor" value="#f8d034">
</div>
<div class="form-group row">
<label for="fld_imagetype" id="lbl_imagetype"
class="fld_Chn_label col-sm-3 col-form-label text-right">发布到</label>
<select name="imagetype" class=" form-control col-sm-8" id="fld_imagetype">
@foreach($ImagesRsset as $reset)
<option value="{{ $reset }}">{{ $reset }}</option>
@endforeach
</select>
</div>
<div class="form-group row">
<label for="fld_description" id="lbl_description" class="fld_Chn_label col-sm-3 text-right col-form-label">描述</label>
<textarea class="form-control col-sm-8" id="fld_description" name="description" ></textarea>
</div>
</div>
<div class="col-md-8">
<div class="form-group mx-sm-4 row">
<button type="button" class="btn btn-outline-primary thzc-photoup-btn">
<i class="far fa-folder"></i> 点击选择照片
</button>
<div class="prj-file-item col-sm-8" style="display: none;"></div>
<input type="hidden" name="upfileguid" id="file" value="">
</div>
<div class="row" id="afterimg" style="display: none">
<div class="col-6">
<div class="avatar-wrapper">
<img id="image-show" src="" alt="剪切后图片" >
</div>
</div>
</div>
<div class="row" id="beforeimg">
<div class="col-6">
<div class="avatar-wrapper">
<img id="image-cropper" src="{{ asset('imgs/nopic.jpg')}}" alt="暂无图片">
</div>
</div>
<div class="col-6" >
<div class="row">
<div class="col-12">
<div class="avatar-preview preview-md" style="float:left;"></div>
<div class="avatar-preview preview-sm" style="float:left;"></div>
</div>
</div>
<div class="row" style="margin-top: 20px">
<div class="col-12">
<div class="avatar-ratio" data-toggle="buttons">
<label class="btn btn-primary radio-label" data-option="NaN" >
<input type="radio" name="options" id="option1" autocomplete="off" checked> 自由比例
</label>
<label class="btn btn-primary radio-label" data-option="1.7777777777777777" >
<input type="radio" name="options" id="option2" autocomplete="off"> 16:9
</label>
<label class="btn btn-primary radio-label" data-option="1.3333333333333333" >
<input type="radio" name="options" id="option3" autocomplete="off"> 4:3
</label>
<label class="btn btn-primary radio-label" data-option="1" style="margin-bottom:10px">
<input type="radio" name="options" id="option4" autocomplete="off"> 1:1
</label>
</div>
</div>
</div>
<div class="row" style="margin-top: 20px">
<div class="col-12">
<button type="button" class="btn btn-outline-primary radio-label" onclick="CropperImage()">确定裁剪</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" style="margin-top:20px; margin-bottom: 30px">
<div class="col-md-12 text-center">
<button type="submit" class="btn btn-outline-primary">添加保存</button>
</div>
</div>
</form>
<input type="file" id="thzc-photo-load" style="display: none"/>
</div>
</div>
</div>
@endsection
@section('mydefinejs')
{{--cropper.js--}}
<script type="text/javascript" src="{{ URL::asset('plugins/cropper/cropper.js')}}"></script>
<script type="text/javascript" src="{{ URL::asset('plugins/cropper/jquery-cropper.js')}}"></script>
<script>
var $image=$("#image-cropper");
var cropper;
var options={
aspectRatio: NaN,
autoCropArea: .7,
preview: '.avatar-preview',
crop: function(event) {
}
};
// 初始化Cropper
function InitCropper() {
$image.cropper(options);
cropper = $image.data('cropper');
}
//要传送的数据对象
var uploadFormData = new FormData();
//上传 host
var uploadHost = '{{route('photo_upload')}}';
var uploadHost2 = '{{route('UploadCropperImage')}}';
$(document).ready(function () {
InitCropper();
});
// 点击照片上传按钮
$(".thzc-photoup-btn").off("click").on("click", function () {
choseImage()
});
var animal_index;
//选择文件上传
function choseImage() {
var filedom = $('#thzc-photo-load');
filedom.click();
//监听文件选择
filedom.change(function (e) {
//上传动画
animal_index = layer.load(1, {
shade: [0.5,'#000'] //0.1透明度的白色背景
});
//文件选择好了 这里开始上传
uploadFormData.append('file', filedom[0].files[0]);
uploadImage()
});
}
// 上传文件
function uploadImage() {
$.ajax({
type: "post",
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
url: uploadHost,
dataType: "json",
processData: false,
contentType: false,
data: uploadFormData,
success: function (data) {
$("#beforeimg").prop("style", "");
$("#afterimg").prop("style", "display: none;");
$("#image").prop("src", data.photourl);
$("#originurl").prop("value", data.photoname);
// 销毁之前创建的cropper对象,重新初始化
$image.cropper('destroy').attr('src', data.photourl).cropper(options);
//关闭加载动画
layer.close(animal_index);
}
});
}
// 确定裁剪图片
function CropperImage(){
var cropCanvas = $image.cropper('getCroppedCanvas');
var base64Url = cropCanvas.toDataURL('image/jpeg');
// 生成Blob的图片格式
cropCanvas.toBlob(function (blob) {
$.ajax({
type: "post",
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
url: uploadHost2,
dataType: "json",
data: {'base64Url':base64Url},
success: function (data) {
alert('裁剪成功');
$("#beforeimg").prop("style", "display: none;");
$("#afterimg").prop("style", "");
$("#image-show").prop("src", data.photourl);
$("#largeurl").prop("value", data.photoname);
// 销毁之前创建的cropper对象,重新初始化
$image.cropper('destroy').attr('src', data.photourl).cropper(options);
//关闭加载动画
layer.close(animal_index);
},
error:function(data){
alert("裁剪失败");
}
})
});
}
//设置比例
$(".avatar-ratio > label").on("click",function(){
$image.cropper("setAspectRatio", $(this).attr("data-option") );
});
</script>
@endsection