本文介绍如何使用JavaScript和HTML5 Canvas元素来移动、调整大小和裁剪图像,这些技术适用于图片编辑器、照片分享等应用场景。借助HTML5 Canvas绘图功能,可以在浏览器端以比较简单的方式来实现图像预处理以减少文件上传流量。
代码和在线演示地址:http://wow.techbrood.com/fiddle/2580,可以先操作下,有个整体印象。
构建界面布局和元素
HTML页面由源图片、Crop操作按钮、裁剪矩形框以及图片容器(含4个角的调整小方块)组成,主体代码如下:
<div class="component"> <div class="overlay"> <div class="overlay-inner"> </div> </div> <img class="resize-p_w_picpath" src="/assets/beauty.jpg" alt="p_w_picpath for resizing"> <button class="btn-crop js-crop">Crop<img class="icon-crop" src="/assets/crop.svg"> </button> </div>
img[class=resize-p_w_picpath] 元素为本服务器图片资源,是要进行调整和裁剪的图片。注意出于安全策略,不能在浏览器中跨域操作图片,否则会出现类似下面的报错信息:
Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
button[class=btn-crop] 是SVG矢量图标按钮。
div[class=overlay] 元素是裁剪矩形框。
此外图片容器使用JavaScript动态包装在 img[class=resize-p_w_picpath] 元素外部:
// Wrap the p_w_picpath with the container and add resize handles $('.resize-p_w_picpath').wrap('<div class="resize-container"></div>') .before('<span class="resize-handle resize-handle-nw"></span>') .before('<span class="resize-handle resize-handle-ne"></span>') .after('<span class="resize-handle resize-handle-se"></span>') .after('<span class="resize-handle resize-handle-sw"></span>');
实现大小调整的功能
大小调整通过先在Canvas上绘制一个对应大小的图像,接着通过Canvas的toDataURL方法转化为base64编码的字符串形式的图片数据。
最后把该data:URL通过设置为img的src属性,附着到目标图像元素上。
resizeImage = function(width, height){ resize_canvas.width = width; resize_canvas.height = height; resize_canvas.getContext('2d').drawImage(orig_src, 0, 0, width, height); $('.resize-p_w_picpath').attr('src', resize_canvas.toDataURL("p_w_picpath/png")); };
实现移动功能
通过mouseup事件获取新的位置,然后通过jQuery的offset方法来完成元素偏移。
moving = function(e){ var mouse={}; e.preventDefault(); e.stopPropagation(); mouse.x = (e.clientX || e.pageX) + $(window).scrollLeft(); mouse.y = (e.clientY || e.pageY) + $(window).scrollTop(); $container.offset({ 'left': mouse.x - ( event_state.mouse_x - event_state.container_left ), 'top': mouse.y - ( event_state.mouse_y - event_state.container_top ) }); };
实现裁剪功能
这个主要是实现一个居中的覆盖矩形(overlay),接着通过计算背景图片和该覆盖矩形的偏移来获取图片裁剪区域的坐标,
然后再通过Canvas的drawImage和toDataURL完成裁剪图的绘制。
crop = function(){ var crop_canvas, left = $('.overlay').offset().left - $container.offset().left, top = $('.overlay').offset().top - $container.offset().top, width = $('.overlay').width(), height = $('.overlay').height(); crop_canvas = document.createElement('canvas'); crop_canvas.width = width; crop_canvas.height = height; crop_canvas.getContext('2d').drawImage(p_w_picpath_target, left, top, width, height, 0, 0, width, height); window.open(crop_canvas.toDataURL("p_w_picpath/png")); }
最后再加上一些移动功能,如触摸事件(Touch)和手势(Gesture)检测的支持。