当前位置: 首页 > news >正文

Html实现图片上传/裁剪/马赛克/压缩/旋转/缩放

cropper下载   https://download.csdn.net/download/dongyan3595/90970115

前端代码

<!doctype html>
<html lang="en">
<head><base href="/aishop/"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta charset="UTF-8"/><link rel="stylesheet" type="text/css" href="assets/fonts/font-awesome/css/font-awesome.css"/><link rel="stylesheet" type="text/css" href="assets/js/vendor/bootstrap/css/bootstrap.min.css"/><link rel="stylesheet" type="text/css" href="assets/js/vendor/cropper/cropper.min.css"/><style>.upload-image {height: 100%; opacity: 0;}.upload-image-preview {width: 200px;height: 200px;overflow: hidden;margin: 0 44px;display: inline-block;}#imageBox {height: 451px;overflow: auto;background-color: #F1F1F1;}#imagePreviewBox .upload-image-preview {background-color: #F1F1F1;}.cropper-container {height:432px!important;width: 529px!important;}.cropper-crop-box{max-height:430px!important;max-width:527px!important;}.mosaic-canvas {position: absolute;top: 0;left: 0;pointer-events: auto; /* 改为auto,允许鼠标事件 */z-index: 1000;}.mosaic-active {cursor: crosshair !important;}</style>
</head>
<div><div id="content" class="edit-content" style="padding: 5px; opacity: 0;"><div id="imageBox" class="col-xs-8" style="position: relative;"><img id="image" class="upload-image" src="assets/images/ruanzhu.jpg"><canvas id="mosaicCanvas" class="mosaic-canvas" style="display:none;"></canvas></div><div id="imagePreviewBox" class="col-xs-4"><div class="upload-image-preview"></div></div><div class="col-xs-4" style="text-align: center;"><button id="dragBtn" type="button" class="btn btn-danger fa fa-arrows" onclick="dragImage()" title="移动"></button><button type="button" class="btn btn-danger fa fa-search-plus" onclick="zoomPlus()" title="放大图片"></button><button type="button" class="btn btn-danger fa fa-search-minus" onclick="zoomMinus()" title="缩小图片"></button><button type="button" class="btn btn-danger fa fa-refresh" onclick="reset()" title="重置图片"></button><button id="mosaicBtn" type="button" class="btn btn-warning fa fa-th" onclick="toggleMosaic()" title="马赛克"></button><button type="button" class="btn btn-info fa fa-reply" onclick="undoEdit()" title="撤销" id="undoBtn" disabled></button></div><div class="col-xs-4" style="margin-top: 5px; text-align: center;"><div class="btn-group"><button class="btn btn-danger fa fa-undo" onclick="rateLeft()" type="button" title="向左旋转90°"> 向左旋转</button></div><div class="btn-group"><button class="btn  btn-danger fa fa-repeat" onclick="rateRight()" type="button" title="向右旋转90°"> 向右旋转</button></div></div><div class="col-xs-4" style="margin-top: 5px; text-align: center;"><div class="btn-group"><form id="uploadFileForm" action="#" style="display: none;"><input type="file" id="uploadImage" name="image" accept="image/jpeg,image/gif,image/png,image/jpg" onchange="doUploadFile()"/></form><button class="btn btn-primary btn-block fa fa-upload" type="button" onclick="openUploadImage()"> 上传图片</button></div><div class="btn-group"><button class="btn btn-primary btn-block fa fa-save" type="button" onclick="doCrop()"> 裁剪上传</button></div></div><div class="col-xs-12" style="margin-top: 5px; text-align: center;"><div class="form-group"><label for="mosaicSize">马赛克大小:</label><input type="range" id="mosaicSize" min="5" max="30" value="10" class="form-control"><span id="mosaicSizeValue">10px</span></div></div><div class="col-xs-12" style="margin-top: 5px; text-align: center;"><div class="form-group"><label for="imageSize">图片压缩:</label><input type="range" id="imageSize" min="10" max="100" value="100" class="form-control"><span id="imageSizeValue">100%</span></div></div></div>
</div>
<script type="text/javascript" src="assets/js/jquery-3.5.1.min.js"></script>
<script type="text/javascript" src="assets/js/vendor/bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript" src="assets/js/vendor/cropper/cropper.min.js"></script>
<script type="text/javascript" src="assets/js/common.js"></script>
<script src="assets/layuiadmin/layui/layui.js"></script>
<script type="text/javascript">var toggleMosaic = function() {}var undoEdit = function() {}var doCrop = function() {}var zoomPlus= function() {}var zoomMinus= function() {}var reset= function() {}var rateLeft= function() {}var rateRight= function() {}var dragImage= function() {}var openUploadImage= function() {}var  doUploadFile= function() {}layui.config({base: 'assets/layuiadmin/'}).extend({index: 'lib/index'}).use(['index', 'restajax', 'datamessage', 'dialog'], function() {var restAjax = layui.restajax;var dialog = layui.dialog;var dataMessage = layui.datamessage;function doSubmitForm() {return false;}var cropper;var isMosaicMode = false;var mosaicCanvas = document.getElementById('mosaicCanvas');var mosaicCtx = mosaicCanvas.getContext('2d');var isDrawing = false;var lastX, lastY;var editHistory = [];var currentHistoryIndex = -1;var maxHistorySteps = 10;// 放大zoomPlus = function () {cropper.zoom(0.1);}// 缩小zoomMinus = function () {cropper.zoom(-0.1);}// 逆时针90rateLeft = function () {cropper.rotate(-90);}// 顺时针90rateRight = function () {cropper.rotate(90);}// 重置reset = function () {cropper.reset();}// 图片移动var isDrag = false;dragImage = function () {if (!isDrag) {cropper.setDragMode('move');isDrag = true;$('#dragBtn').addClass('btn-default');$('#dragBtn').removeClass('btn-danger');} else {cropper.setDragMode('crop');isDrag = false;$('#dragBtn').addClass('btn-danger');$('#dragBtn').removeClass('btn-default');}}// 切换马赛克模式toggleMosaic = function() {isMosaicMode = !isMosaicMode;if (isMosaicMode) {// 进入马赛克模式$('#mosaicBtn').addClass('btn-success');$('#mosaicBtn').removeClass('btn-warning');// 保存当前状态到历史记录saveToHistory();// 显示马赛克画布setupMosaicCanvas();$('#mosaicCanvas').show();// 重要:将画布设置为可接收鼠标事件mosaicCanvas.style.pointerEvents = 'auto';// 添加鼠标事件$(mosaicCanvas).on('mousedown', startMosaic);$(document).on('mousemove', drawMosaic);$(document).on('mouseup mouseleave', stopMosaic);// 添加触摸事件$(mosaicCanvas).on('touchstart', handleTouchStart);$(document).on('touchmove', handleTouchMove);$(document).on('touchend touchcancel', handleTouchEnd);// 添加马赛克模式样式$('#imageBox').addClass('mosaic-active');} else {// 退出马赛克模式$('#mosaicBtn').addClass('btn-warning');$('#mosaicBtn').removeClass('btn-success');// 重要:将画布设置为不可接收鼠标事件mosaicCanvas.style.pointerEvents = 'none';// 移除事件监听$(mosaicCanvas).off('mousedown');$(document).off('mousemove', drawMosaic);$(document).off('mouseup mouseleave', stopMosaic);$(mosaicCanvas).off('touchstart');$(document).off('touchmove', handleTouchMove);$(document).off('touchend touchcancel', handleTouchEnd);// 移除马赛克模式样式$('#imageBox').removeClass('mosaic-active');}}// 设置马赛克画布function setupMosaicCanvas() {var cropperCanvas = $('.cropper-canvas')[0];var cropperImage = $('.cropper-canvas img')[0];if (cropperCanvas && cropperImage) {var containerRect = cropperCanvas.getBoundingClientRect();var imageBoxRect = $('#imageBox')[0].getBoundingClientRect();// 设置画布尺寸mosaicCanvas.width = containerRect.width;mosaicCanvas.height = containerRect.height;mosaicCanvas.style.width = containerRect.width + 'px';mosaicCanvas.style.height = containerRect.height + 'px';// 设置画布位置 - 相对于imageBox计算偏移mosaicCanvas.style.position = 'absolute';mosaicCanvas.style.top = (containerRect.top - imageBoxRect.top) + 'px';mosaicCanvas.style.left = (containerRect.left - imageBoxRect.left) + 'px';// 清除画布mosaicCtx.clearRect(0, 0, mosaicCanvas.width, mosaicCanvas.height);}}// 开始绘制马赛克function startMosaic(e) {e.preventDefault(); // 阻止默认行为isDrawing = true;var rect = mosaicCanvas.getBoundingClientRect();lastX = e.clientX - rect.left;lastY = e.clientY - rect.top;// 立即开始绘制一个点drawMosaicEffect(lastX, lastY, lastX, lastY);}// 处理触摸开始事件function handleTouchStart(e) {e.preventDefault();var touch = e.originalEvent.touches[0];var rect = mosaicCanvas.getBoundingClientRect();lastX = touch.clientX - rect.left;lastY = touch.clientY - rect.top;isDrawing = true;}// 处理触摸移动事件function handleTouchMove(e) {if (!isDrawing || !isMosaicMode) return;e.preventDefault();var touch = e.originalEvent.touches[0];var rect = mosaicCanvas.getBoundingClientRect();var x = touch.clientX - rect.left;var y = touch.clientY - rect.top;drawMosaicEffect(lastX, lastY, x, y);lastX = x;lastY = y;}// 处理触摸结束事件function handleTouchEnd(e) {isDrawing = false;}// 绘制马赛克function drawMosaic(e) {if (!isDrawing || !isMosaicMode) return;var rect = mosaicCanvas.getBoundingClientRect();var x = e.clientX - rect.left;var y = e.clientY - rect.top;drawMosaicEffect(lastX, lastY, x, y);lastX = x;lastY = y;}// 绘制马赛克效果function drawMosaicEffect(startX, startY, endX, endY) {var cropperImage = $('.cropper-canvas img')[0];if (!cropperImage) return;var mosaicSize = parseInt($('#mosaicSize').val());var dx = endX - startX;var dy = endY - startY;var distance = Math.sqrt(dx * dx + dy * dy);var steps = Math.max(Math.floor(distance), 1);for (var i = 0; i <= steps; i++) {var x = startX + (dx * i / steps);var y = startY + (dy * i / steps);// 计算马赛克块的左上角坐标var mosaicX = Math.floor(x / mosaicSize) * mosaicSize;var mosaicY = Math.floor(y / mosaicSize) * mosaicSize;// 从原始图像获取像素数据var cropperRect = cropperImage.getBoundingClientRect();var cropperCanvas = document.createElement('canvas');cropperCanvas.width = mosaicSize;cropperCanvas.height = mosaicSize;var cropperCtx = cropperCanvas.getContext('2d');try {// 获取马赛克区域的图像数据cropperCtx.drawImage(cropperImage,mosaicX, mosaicY, mosaicSize, mosaicSize,0, 0, mosaicSize, mosaicSize);// 计算平均颜色var imageData = cropperCtx.getImageData(0, 0, mosaicSize, mosaicSize);var data = imageData.data;var r = 0, g = 0, b = 0, a = 0, count = 0;for (var j = 0; j < data.length; j += 4) {r += data[j];g += data[j + 1];b += data[j + 2];a += data[j + 3];count++;}// 计算平均值r = Math.round(r / count);g = Math.round(g / count);b = Math.round(b / count);a = Math.round(a / count);// 绘制马赛克块mosaicCtx.fillStyle = `rgba(${r}, ${g}, ${b}, ${a / 255})`;mosaicCtx.fillRect(mosaicX, mosaicY, mosaicSize, mosaicSize);} catch (error) {console.error('马赛克绘制错误:', error);}}}// 停止绘制马赛克function stopMosaic() {if (isDrawing) {isDrawing = false;saveToHistory();}}// 保存到历史记录function saveToHistory() {// 如果当前不是最新状态,删除后面的历史if (currentHistoryIndex >= 0 && currentHistoryIndex < editHistory.length - 1) {editHistory = editHistory.slice(0, currentHistoryIndex + 1);}// 获取当前画布状态var imageData = null;if (mosaicCanvas.width > 0 && mosaicCanvas.height > 0) {try {imageData = mosaicCtx.getImageData(0, 0, mosaicCanvas.width, mosaicCanvas.height);} catch (e) {console.error('获取画布数据失败:', e);}}// 添加到历史记录if (imageData) {editHistory.push(imageData);// 限制历史记录数量if (editHistory.length > maxHistorySteps) {editHistory.shift();}currentHistoryIndex = editHistory.length - 1;// 启用撤销按钮$('#undoBtn').prop('disabled', false);}}// 撤销编辑undoEdit = function () {if (currentHistoryIndex > 0) {currentHistoryIndex--;var imageData = editHistory[currentHistoryIndex];// 恢复到之前的状态mosaicCtx.putImageData(imageData, 0, 0);} else if (currentHistoryIndex === 0) {// 恢复到初始状态(清空画布)mosaicCtx.clearRect(0, 0, mosaicCanvas.width, mosaicCanvas.height);currentHistoryIndex = -1;$('#undoBtn').prop('disabled', true);}}// 重置马赛克画布和历史记录function resetMosaicCanvas() {if (mosaicCanvas) {mosaicCtx.clearRect(0, 0, mosaicCanvas.width, mosaicCanvas.height);}editHistory = [];currentHistoryIndex = -1;$('#undoBtn').prop('disabled', true);}// 打开上传图片openUploadImage = function () {$('#uploadImage').click();}// 添加键盘快捷键支持$(document).on('keydown', function(e) {// 检测 CTRL + Zif (e.ctrlKey && e.keyCode === 90) {// 阻止浏览器默认的撤销行为e.preventDefault();// 调用撤销函数undoEdit();}});// 上传文件doUploadFile = function () {var loadLayerIndex;var formData = new FormData($('#uploadFileForm')[0]);restAjax.postFile('api/goods/upload-image', formData, {}, function (code, data) {dialog.msg('上传成功');cropper.replace('route/file/download/false/' + data.data, false);localStorage.setItem('uploadImage', data.data);// 重置马赛克画布和历史记录resetMosaicCanvas();}, function(code, data) {dialog.msg(data.msg);}, function() {loadLayerIndex = dialog.msg(dataMessage.uploading, {icon: 16, time: 0, shade: 0.3});}, function() {dialog.close(loadLayerIndex);});}// 裁剪doCrop = function () {// 获取裁剪后的画布var croppedCanvas = cropper.getCroppedCanvas();// 如果有马赛克效果,将马赛克合并到裁剪后的图像上if (mosaicCanvas.width > 0 && mosaicCanvas.height > 0) {var cropperCanvas = $('.cropper-canvas')[0];var cropBox = $('.cropper-crop-box')[0];if (cropperCanvas && cropBox) {var cropBoxRect = cropBox.getBoundingClientRect();var cropperRect = cropperCanvas.getBoundingClientRect();// 计算裁剪框相对于画布的位置var left = cropBoxRect.left - cropperRect.left;var top = cropBoxRect.top - cropperRect.top;// 获取裁剪框的尺寸var width = cropBoxRect.width;var height = cropBoxRect.height;// 在裁剪后的画布上绘制马赛克var ctx = croppedCanvas.getContext('2d');ctx.drawImage(mosaicCanvas,left, top, width, height,0, 0, croppedCanvas.width, croppedCanvas.height);}}croppedCanvas.toBlob(function (cropBlob) {var formData = new FormData();formData.append("file", cropBlob);formData.append("picturesThumbnails", $('#imageSize').val());var loadLayerIndex;restAjax.postFile('api/goods/upload-image', formData, {}, function (code, data) {dialog.msg('裁剪成功');// 完全重置马赛克画布和历史记录resetMosaicCanvas();// 替换图像cropper.replace('route/file/download/false/' + data.data, false);localStorage.setItem('uploadImage', data.data);// 在图像加载完成后重新设置马赛克画布setTimeout(function() {setupMosaicCanvas();}, 500);}, function(code, data) {dialog.msg(data.msg);}, function() {loadLayerIndex = dialog.msg(dataMessage.uploading, {icon: 16, time: 0, shade: 0.3});}, function() {dialog.close(loadLayerIndex);});});}$(function () {var image = document.getElementById('image');cropper = new Cropper(image, {aspectRatio: 1.5 / 2,viewMode: 1,minContainerHeight: 430,maxContainerHeight: 430,preview: '.upload-image-preview',crop(event) {// 如果在马赛克模式下,实时更新马赛克画布位置if (isMosaicMode) {setupMosaicCanvas();}},ready() {// 初始化马赛克画布setTimeout(function() {setupMosaicCanvas();}, 500);}});$('#content').fadeTo(1000, 1);var fileId = restAjax.params(window.location.href).fileId;if (fileId != 'undefined' && fileId != undefined && fileId.length > 1) {localStorage.setItem('uploadImage', fileId);cropper.replace('route/file/download/false/' + fileId, false);}// 马赛克大小滑块事件$('#mosaicSize').on('input', function() {var size = $(this).val();$('#mosaicSizeValue').text(size + 'px');});$('#imageSize').on('input', function() {var size = $(this).val();$('#imageSizeValue').text(size + '%');});// 确保马赛克画布初始化setTimeout(function() {setupMosaicCanvas();}, 1000); // 延迟1秒,确保cropper已完全初始化})});
</script>
</body>
</html>

后台代码

    @PostMapping({"upload-image"})public SuccessResultData<String> uploadFile(@RequestParam("file") MultipartFile file, Double picturesThumbnails) throws IOException {// 参数校验if (file.isEmpty()) {throw new SaveException("上传文件不能为空");}InputStream inputStream = file.getInputStream();BufferedImage bufferedImage = ImageIO.read(inputStream);if (bufferedImage == null) {throw new SaveException("无效的图片文件");}BufferedImage image = bufferedImage;if (picturesThumbnails != null) {try {image = Thumbnails.of(new BufferedImage[]{bufferedImage}).scale(1).outputQuality(picturesThumbnails / 100).outputFormat("jpg").asBufferedImage();} catch (IOException e) {throw new SaveException("图片压缩出现异常");}}MultipartFile file1 = new MockMultipartFile("file",            // 参数名(表单中的name)UUIDUtil.get32UUID() + ".jpg",        // 原始文件名"image/jpeg",convertToInputStream(image, "jpg")        // 文件输入流);Map<String, Object> params1 = new HashMap<>();String fileId1 = iFileService.uploadSingleByUserId(securityComponent.getCurrentUser().getUserId(), file1, UploadTypeEnum.IMAGE, params1);return new SuccessResultData(fileId1);}

相关文章:

  • 【Dv3Admin】系统视图菜单管理API文件解析
  • 阿里云服务器 篇十七:网站悬浮球
  • centos开启samba服务
  • 超低成本U型光电开关红外对射管检测电路
  • RLHF vs RLVR:对齐学习中的两种强化方式详解
  • Python 如何在Python 3.6上安装PIP
  • 【Proteus仿真】【32单片机-A011】HX711电子秤系统设计
  • 解决网页导出PDF部分内容被遮挡问题
  • Ubuntu 20.04 联网设置指南
  • wifi改ip地址有什么用?wifi改ip地址怎么改
  • 【MySQL基础】MySQL表操作全面指南:从创建到管理的深度解析
  • Linux系统:进程间通信-匿名与命名管道
  • ZYNQ学习记录FPGA(二)Verilog语言
  • MCU ADC硬件设计注意事项
  • vulnyx Blogger writeup
  • Linux学习
  • 机器学习×第五卷:线性回归入门——她不再模仿,而开始试着理解你
  • 如何手撸一个最小化操作系统:从 0 到 1 掌握汇编-文件管理-内存页表-文件系统-上下文切换算法 MIT 经典教程 结合豆包ai
  • win操作系统安装C++语言开发环境之一, vscode +MinGW ,流程
  • 【1】跨越技术栈鸿沟:字节跳动开源TRAE AI编程IDE的实战体验
  • 广州 网站建设/网页设计主要做什么
  • 建立一个网站的费用/腾讯广告
  • 动画设计工资/长沙谷歌优化
  • 手机app网站开发/seo点击软件手机
  • 美国做按摩广告的网站/百度关键词搜索排名多少钱
  • 做网站编程要学什么/站长之家权重查询