裁剪图片,一个超级常用的功能!,我个人非常喜欢Windows的「画图」工具。这款工具我小学二年级时非常喜欢玩。长大后,也对它爱不释手。因为「画图」占用内存非常小,可以放大8倍,方便像素级别调整细节,裁剪、移动都非常方便!,但是工作后一直在用Mac,裁剪图片没那么方便了。Mac自带的预览工具似乎有裁剪能力,但是自己总是用不惯,还是喜欢Windows「画图」的交互。,最近,每次更新51CTO文章,总是需要配个图。51CTO配图推荐是需要比例的。如果我们能提前按照比例要求准备好素材,提前查看效果,那是令强迫症最舒服的!,我不喜欢用各种APP,还需要下载,还需要学交互,而且很多时候我希望自动化实现一些功能,APP的实现成本是很高的!,网上也有很多在线裁剪的。但是也存在问题:,作为前端开发者,我打算自己写一个「图片裁剪」工具!,MVP版本暂不支持手动拖拽裁剪。有其它尺寸需求,可以先改代码实现,也很方便。,体验地址:
https://tool.hullqin.cn/img-editor.html,源码:
https://github.com/HullQin/tool-hullqin-cn,,这是实际的案例,用了我《《 合 成 大 西 瓜 》 重 制 版 !( 联 机 版 在 做 了 )》这篇文章封面做例子。可以看到:,很简单,我们定义好:,其中,img是display: none
的元素,上传后,会把img的src替换为上传图片的base64内容。它是隐藏的,因为我们用canvas来绘制最终图片,而canvas是支持对图片做裁剪操作并且可以保存的。,现在img初始值是个1*1大小的透明图片,是为了避免它初始化时触发下载行为。,此外,提前定义好JS要用到的dom元素:,借助input的onchange
,用户选择文件后会触发。,随后我们通过FileReader读取这个用户选择的文件的二进制内容,以base64编码赋值给img的src。,然后,把img画在canvas上。,当然,刚选择图片后,canvas比例要跟用户选择的img保持一致,所以还要调整canvas的尺寸。,定义一个函数,实现裁剪能力。它需要width和height作为参数。表明了裁剪目标的比例(不代表真实的数值)。,如果现在的宽高跟目标比例是一样的,那么不需要做任何事情。计算方法就是判断currentWidth / currentHeight和width / height是否相等。但是除法效率不如乘法,所以我们改成判断currentWidth * height和currentHeight * width是否相等。而且这样有个好处:后面会重复利用乘法结果,减少了代码运算次数。,如果两个比例不想等,那么要把过长的那条边裁短,重新设置canvas大小,重新绘制图片。,可以了解一下canvas这个绘图API:
Canvas: Using images。,最后添加点击事件即可:,至此,大功告成啦!我们手动实现了一个「裁剪图片」的工具!,将来,我们前端开发者,手撸一个自动化的PS指日可待!快快关注HullQin学起来~,我是HullQin,公众号
线下聚会游戏的作者,转发本文前需获得作者HullQin授权。我独立开发了
《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费没广告。还独立开发了
《合成大西瓜重制版》。还开发了
《Dice Crush》参加Game Jam 2022。喜欢可以关注我
HullQin 噢~我有空了会分享做游戏的相关技术。,借助input的onchange
,用户选择文件后会触发。,很多网站要求图片先上传,修改完再下载,如果图片包含隐私,就会有隐私泄漏风险。,那些网站往往有很多广告,速度还比较慢,体验很差!,
大家好,我是公众号「线下聚会游戏」作者HullQin,开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏。
背景
裁剪图片,一个超级常用的功能!
我个人非常喜欢Windows的「画图」工具。这款工具我小学二年级时非常喜欢玩。长大后,也对它爱不释手。因为「画图」占用内存非常小,可以放大8倍,方便像素级别调整细节,裁剪、移动都非常方便!
但是工作后一直在用Mac,裁剪图片没那么方便了。Mac自带的预览工具似乎有裁剪能力,但是自己总是用不惯,还是喜欢Windows「画图」的交互。
最近,每次更新51CTO文章,总是需要配个图。51CTO配图推荐是需要比例的。如果我们能提前按照比例要求准备好素材,提前查看效果,那是令强迫症最舒服的!
解决方案
我不喜欢用各种APP,还需要下载,还需要学交互,而且很多时候我希望自动化实现一些功能,APP的实现成本是很高的!
网上也有很多在线裁剪的。但是也存在问题:
- 很多网站要求图片先上传,修改完再下载,如果图片包含隐私,就会有隐私泄漏风险。
- 那些网站往往有很多广告,速度还比较慢,体验很差!
- 无法自动化,依然需要手动操作。
作为前端开发者,我打算自己写一个「图片裁剪」工具!
具体需求
- 允许用户手动选择本地图片文件,并展示出来。
- 不能有后端,不允许上传至服务器,减少带宽、提高速度。
- 裁剪是纯前端的过程,裁剪完毕后,用户有办法保存图片。
- 目前提供2种一键裁剪尺寸:文章封面、专栏封面。点击后,图片裁剪为对应比例,居中展示。
- 裁剪后,可以右键保存。
MVP版本暂不支持手动拖拽裁剪。有其它尺寸需求,可以先改代码实现,也很方便。
体验地址 & 源码
体验地址: https://tool.hullqin.cn/img-editor.html
源码: https://github.com/HullQin/tool-hullqin-cn
实现思路
这是实际的案例,用了我《《 合 成 大 西 瓜 》 重 制 版 !( 联 机 版 在 做 了 )》这篇文章封面做例子。可以看到:
- 用input实现了选择文件。
- 用2个button,方便一键裁剪2种尺寸。
- 用canvas展示了上传的图片和裁剪后的图片,并且右键可以「保存」或「复制」。
写代码
html的结构
很简单,我们定义好:
<label for="src">请选择图片: </label>
<input id="src" type="file" />
<div>
<button id="slice-article">切割为文章封面</button>
<button id="slice-column">切割为专栏封面</button>
</div>
<canvas id="work"></canvas>
<img id="background" class="hidden" alt="" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" />
其中,img是display: none
的元素,上传后,会把img的src替换为上传图片的base64内容。它是隐藏的,因为我们用canvas来绘制最终图片,而canvas是支持对图片做裁剪操作并且可以保存的。
现在img初始值是个1*1大小的透明图片,是为了避免它初始化时触发下载行为。
此外,提前定义好JS要用到的dom元素:
const inputEle = document.getElementById('src');
const canvasEle = document.getElementById('work');
const imgEle = document.getElementById('background');
const sliceArticleEle = document.getElementById('slice-article');
const sliceColumnEle = document.getElementById('slice-column');
const ctx = canvasEle.getContext('2d');
选择图片并展示
借助input的onchange
,用户选择文件后会触发。
随后我们通过FileReader读取这个用户选择的文件的二进制内容,以base64编码赋值给img的src。
然后,把img画在canvas上。
当然,刚选择图片后,canvas比例要跟用户选择的img保持一致,所以还要调整canvas的尺寸。
const resetCanvas = () => {
canvasEle.setAttribute('width', imgEle.width.toString());
canvasEle.setAttribute('height', imgEle.height.toString());
ctx.drawImage(imgEle, 0, 0);
};
const onFileChange = (event) => {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function () {
imgEle.onload = () => {
resetCanvas();
};
imgEle.src = this.result;
};
reader.readAsDataURL(file);
}
inputEle.addEventListener('change', onFileChange);
裁剪图片功能
定义一个函数,实现裁剪能力。它需要width和height作为参数。表明了裁剪目标的比例(不代表真实的数值)。
如果现在的宽高跟目标比例是一样的,那么不需要做任何事情。计算方法就是判断currentWidth / currentHeight和width / height是否相等。但是除法效率不如乘法,所以我们改成判断currentWidth * height和currentHeight * width是否相等。而且这样有个好处:后面会重复利用乘法结果,减少了代码运算次数。
如果两个比例不想等,那么要把过长的那条边裁短,重新设置canvas大小,重新绘制图片。
可以了解一下canvas这个绘图API:Canvas: Using images。
const setCanvasSize = (width, height) => {
const currentWidth = imgEle.width;
const currentHeight = imgEle.height;
const a = currentWidth * height;
const b = currentHeight * width;
if (a === b) return;
if (a > b) {
const newWidth = b / height;
canvasEle.setAttribute('width', newWidth.toString());
canvasEle.setAttribute('height', imgEle.height.toString());
ctx.drawImage(imgEle, (currentWidth - newWidth) / 2, 0, newWidth, currentHeight, 0, 0, newWidth, currentHeight);
return;
}
const newHeight = a / width;
canvasEle.setAttribute('width', imgEle.width.toString());
canvasEle.setAttribute('height', newHeight.toString());
ctx.drawImage(imgEle, 0, (currentHeight - newHeight) / 2, currentWidth, newHeight, 0, 0, currentWidth, newHeight);
};
最后添加点击事件即可:
const onClickSliceArticle = () => {
setCanvasSize(1303, 734);
};
const onClickSliceColumn = () => {
setCanvasSize(480, 270);
};
sliceArticleEle.addEventListener('click', onClickSliceArticle);
sliceColumnEle.addEventListener('click', onClickSliceColumn);
至此,大功告成啦!我们手动实现了一个「裁剪图片」的工具!
将来,我们前端开发者,手撸一个自动化的PS指日可待!快快关注HullQin学起来~
写在最后
我是HullQin,公众号线下聚会游戏的作者,转发本文前需获得作者HullQin授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费没广告。还独立开发了《合成大西瓜重制版》。还开发了《Dice Crush》参加Game Jam 2022。喜欢可以关注我 HullQin 噢~我有空了会分享做游戏的相关技术。
文章版权声明
1 原创文章作者:4258,如若转载,请注明出处: https://www.52hwl.com/36930.html
2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈
3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)
4 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别