社区精选|前端实现图片旋转功能

SegmentFault

共 7969字,需浏览 16分钟

 · 2023-09-26

今天小编为大家带来的是社区作者 linong 的文章,让我们一起来学习前端实现图片旋转功能。




前两天遇到一个小需求,需要将横屏图片转为竖屏展示。整理一下相关内容。


通过 css

transform rotate 来控制展示时显示效果

一般是在图片审核等场景,实现一个类似的功能。方便审核人员查看图片

测试传送门:https://stackblitz.com/edit/vue-sdrnue?file=src%2FApp.vue



transform scale 来控制展示时显示效果

测试传送门:https://stackblitz.com/edit/vue-pj9puy?file=src%2FApp.vue



通过 canvas 来控制展示是显示效果

这种一般就是在生成的时候处理,落库就是直接是竖屏图片。

测试传送门:https://jsrun.net/Q7JKp



rotate 来实现旋转效果


orientation = 0 // 0    orientation = 3 // 180    orientation = 8 // 270    orientation = 6 // 90if (orientation === 6) {        canvas4.width = canvas1.height;        canvas4.height = canvas1.width;        ctx4.rotate(Math.PI / 2);        ctx4.drawImage(canvas1, 0, -canvas1.height);    } else if (orientation === 3) {        canvas4.width = canvas1.width;        canvas4.height = canvas1.height;        ctx4.rotate(Math.PI);        ctx4.drawImage(canvas1, -canvas1.width, -canvas1.height);    } else if (orientation === 8) {        canvas4.width = canvas1.height;        canvas4.height = canvas1.width;        ctx4.rotate(-Math.PI / 2);        ctx4.drawImage(canvas1, -canvas1.width, 0);    } else {// 如果没有旋转,直接绘制图片        canvas4.width = canvas1.width;        canvas4.height = canvas1.height;        ctx4.drawImage(canvas1, 0, 0);    }

translate + rotate 来简化旋转

https://www.canvasapi.cn/CanvasRenderingContext2D/rotate#&syntax
了解 CanvasRenderingContext2D.rotate()
CanvasRenderingContext2D.rotate() 给Canvas画布添加旋转矩阵,顺时针方向,单位是弧度。
默认旋转中心点是 Canvas 的左上角 
(0, 0) 坐标点,如果希望改变旋转中心点,例如以Canvas 画布的中心旋转,需要先使用 translate() 位移旋转中心点。
角度转弧度计算公式是:radian = degree Math.PI / 180。例如,旋转45°,旋转弧度就是45 Math.PI / 180。

通过移动中心点,可以比较简单的理解旋转。(好像也没简单多少)

<canvas id="canvas5"></canvas><script>var context = canvas5.getContext('2d');    canvas5.width=canvas1.height;    canvas5.height=canvas1.width;var width = canvas5.width;var height = canvas5.height;// 先位移坐标到中心    context.translate(width / 2, height / 2);// 旋转90度    context.rotate(90 * Math.PI / 180);// 此时按照旋转后的尺寸// 把定位中心移动到左上角    context.translate(-1 * height / 2, -1 * width / 2);// 绘制图片    context.drawImage(canvas1, 0, 0, height, width);// 坐标系还原到初始    context.setTransform(1, 0, 0, 1, 0, 0);</script>


通过 exif 来控制图片方向

我们知道有个 exifjs 的库可以读取 exif 信息,这里我们使用另一个库 piexifjs 来修改 exif 信息。

测试传送门:https://jsrun.net/MdJKp/edit


function handleFileSelect(Orientation = 1,file) {console.log('file', file)var zeroth = {};var exif = {};var gps = {};    zeroth[piexif.ImageIFD.Make] = "Make";    zeroth[piexif.ImageIFD.XResolution] = [777, 1];    zeroth[piexif.ImageIFD.YResolution] = [777, 1];    zeroth[piexif.ImageIFD.Software] = "Piexifjs";    exif[piexif.ExifIFD.DateTimeOriginal] = "2010:10:10 10:10:10";    exif[piexif.ExifIFD.LensMake] = "LensMake";    exif[piexif.ExifIFD.Sharpness] = 777;    exif[piexif.ExifIFD.LensSpecification] = [[1, 1], [1, 1], [1, 1], [1, 1]];    gps[piexif.GPSIFD.GPSVersionID] = [7, 7, 7, 7];    gps[piexif.GPSIFD.GPSDateStamp] = "1999:99:99 99:99:99";var exifObj = {"0th":zeroth, "Exif":exif, "GPS":gps};   // 获取当前图片的方向值(通常在 '0th' IFD 中)// 设置新的方向值,例如将方向设置为正常(1)    exifObj['0th'][piexif.ImageIFD.Orientation] = Orientation;//正常// exifObj['0th'][piexif.ImageIFD.Orientation] = 2;//var exifStr = piexif.dump(exifObj);
var reader = new FileReader(); reader.onload = function(e) {var inserted = piexif.insert(exifStr, e.target.result);
var image = new Image(); image.src = inserted;// image.width = 200;
var el = document.createElement('div'); el.style.border='1px solid #0cc' el.style.padding = '20px' el.innerHTML = Orientation el.appendChild(image);document.body.appendChild(el);
}; reader.readAsDataURL(file);}
canvas1.toBlob(handleFileSelect.bind(window,1), 'image/jpeg')canvas1.toBlob(handleFileSelect.bind(window,2), 'image/jpeg')canvas1.toBlob(handleFileSelect.bind(window,3), 'image/jpeg')canvas1.toBlob(handleFileSelect.bind(window,4), 'image/jpeg')canvas1.toBlob(handleFileSelect.bind(window,5), 'image/jpeg')canvas1.toBlob(handleFileSelect.bind(window,6), 'image/jpeg')canvas1.toBlob(handleFileSelect.bind(window,7), 'image/jpeg')canvas1.toBlob(handleFileSelect.bind(window,8), 'image/jpeg')


使用类库实现

Cropper.js

https://fengyuanchen.github.io/cropperjs/

Cropper.js 是一个流行的用于图片裁剪和编辑的 JavaScript 类库。它的实现原理主要是 canvas
Cropper.js 使用 Canvas 来处理图片的渲染和编辑。Canvas 允许动态生成和修改图像,包括裁剪、旋转、缩放等操作
通过捕获用户的鼠标或触摸事件来实现用户与裁剪框的交互
也支持 api 式调用,可以方便开发者二开
Cropper.js 可以生成裁剪后的图像数据,可以作为 Blob 对象、Base64 编码的字符串或其他格式输出。用户可以使用这些数据进行保存、上传或其他后续处理

konvajs

https://konvajs.org/

Konva.js 是一个用于 Canvas 上图形渲染和交互的 JavaScript 类库。它的实现原理也是 Canvas,但是会有图形、图层等概念
提供了多种用户操作的回调,如拖拽、缩放、旋转、点击、双击等。允许为图形对象添加事件监听器,以便在用户与图形对象交互时触发自定义逻辑。

react-image-magnify

https://ethanselzer.github.io/react-image-magnify/#/lens

openseadragon

https://openseadragon.github.io/#examples-and-features


panzoom

https://timmywil.com/panzoom/demo/


SmartPhoto

https://appleple.github.io/SmartPhoto/#group=animal&photo=camel



总结

如果只是显示效果,可以通过 transform 修改 rotate,可以很快的实现效果

exif 的 Orientation 也是一个思路,但是 exif 支持也不一定稳定
如果为了兼容性,可以考虑使用 cavnas 直接将原图修改并落库
最后,如果是为了审核者查看,可以使用一些开源的库,基本上都会比较完善的支持图片的放大、缩小、旋转、拖动,当然有一些也会支持图集。
讲完了,选择适合自己的就好



点击左下角阅读原文,到 SegmentFault 思否社区 和文章作者展开更多互动和交流,公众号后台回复“ 入群 ”即可加入我们的技术交流群,收获更多的技术文章~

- END -



往期推荐


社区精选|原来 Canvas 也能直接绘制圆角矩形了


社区精选|裁剪的 3 种方式,CSS 如何隐藏移动端的滚动条?


写给小白的地理信息的表示法:GeoJSON



浏览 337
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报