原生js 基于canvas写一个简单的前端 截图工具
先看效果


<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<style type="text/css">
* {
padding: 0;
margin: 0;
font-size: 14px;
} #box {
width: 400px;
height: 400px;
border: 1px solid red;
margin: 20px auto;
position: relative;
} #operate {
text-align: center;
;
} #operate p {
margin-bottom: 6px;
} input[type=file] {
display: none;
} label {
display: inline-block;
cursor: pointer;
background: #38f;
color: #fff;
width: 102px;
height: 38px;
line-height: 38px;
border-radius: 4px;
} #clipcanvas {
position: absolute;
top: 0;
left: 0;
z-index: 10;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="box">
<canvas id="canvas" width="400" height="400"></canvas>
<canvas id="clipcanvas"></canvas>
</div>
<div id="operate">
<p><label><input type="file" name="" id="bg" value="" />选择头像</label></p>
<p><label><input type="file" name="" id="flag" value="" />选择上层</label></p>
<p><input type="text" name="" id="posX" value="0" />请输入上层x位置</p>
<p><input type="text" name="" id="posY" value="0" />请输入上层y位置</p>
<p><label id="create">直接生成</label></p>
<p><label id="reset">重新截图</label></p>
</div>
<a href="" download="logo.png" title="点击下载" id="down">
<img src="" id="result">
</a> </body>
<script type="text/javascript">
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const baseW = 400;
const flagW = 100;
let bgConfig;
let flagConfig;
document.getElementById("bg").onchange = async function() {
const file = this.files[0];
try {
const img = await getImageObj(file);
const rate = compress(img, baseW);
bgConfig = [img, 0, 0, img.width, img.height, 0, 0, rate.w, rate.h];
drawn();
} catch (e) {
console.error(e);
}
}; document.getElementById("flag").onchange = async function() {
const file = this.files[0];
try {
const img = await getImageObj(file);
const rate = compress(img, flagW);
flagConfig = [img, 0, 0, img.width, img.height, 0, 0, rate.w, rate.h];
drawn();
} catch (e) {
console.error(e);
}
};
document.getElementById("posX").onchange = function() {
let val = Number(this.value) || 0;
flagConfig[5] = val;
drawn();
}
document.getElementById("posY").onchange = function() {
let val = Number(this.value) || 0;
flagConfig[6] = val;
drawn();
} function drawn() {
ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
if (bgConfig) {
ctx.drawImage(...bgConfig);
}
if (flagConfig) {
ctx.drawImage(...flagConfig);
}
} //图片压缩,获取等比缩放后的结果
function compress(img, base) {
let w = img.width;
let h = img.height;
if (img.width > img.height) {
if (img.width > base) {
//要将宽度缩放
w = base;
h = (w / img.width) * img.height; // 新的 宽比 高 = 旧的宽比高 h / w = img.heigth/img.width ;
}
} else {
if (img.height > base) {
h = base;
w = (h / img.height) * img.width;
}
}
return {
w,
h
};
} function getImageObj(file) {
const url = getObjectURL(file);
const img = new Image();
img.src = url;
return new Promise((resolve, reject) => {
img.onload = function() {
resolve(img);
}
img.onerror = function(e) {
reject(e);
}
});
} //取得该文件的url
function getObjectURL(file) {
var url = null;
if (window.createObjectURL != undefined) {
url = window.createObjectURL(file);
} else if (window.URL != undefined) {
url = window.URL.createObjectURL(file);
} else if (window.webkitURL != undefined) {
url = window.webkitURL.createObjectURL(file);
}
return url;
} //截图
var clipcanvas = document.getElementById("clipcanvas");
var clipctx = clipcanvas.getContext("2d"); clipcanvas.width = canvas.clientWidth;
clipcanvas.height = canvas.clientHeight;
var start = null;
var clipArea = {}; //裁剪范围
clipcanvas.onmousedown = function(e) {
start = {
x: e.offsetX,
y: e.offsetY
};
}
clipcanvas.onmousemove = function(e) {
if (start) {
fill(start.x, start.y, e.offsetX - start.x, e.offsetY - start.y)
}
}
document.addEventListener("mouseup", function() {
if (start) {
start = null;
exportImg(clipArea);
}
});
//重新截图
document.getElementById("reset").onclick = function(){
clipctx.clearRect(0, 0, clipcanvas.width, clipcanvas.height);
}
//直接生成
document.getElementById("create").onclick = function(){
exportImg({
x:0,
y:0,
w:canvas.clientWidth,
h:canvas.clientHeight,
})
}
function fill(x, y, w, h) {
clipctx.clearRect(0, 0, clipcanvas.width, clipcanvas.height);
clipctx.beginPath();
clipctx.fillStyle = 'rgba(0,0,0,0.6)';
clipctx.strokeStyle = "green";
//遮罩层
clipctx.globalCompositeOperation = "source-over";
clipctx.fillRect(0, 0, clipcanvas.width, clipcanvas.height);
//画框
clipctx.globalCompositeOperation = 'destination-out';
clipctx.fillRect(x, y, w, h);
//描边
clipctx.globalCompositeOperation = "source-over";
clipctx.moveTo(x, y);
clipctx.lineTo(x + w, y);
clipctx.lineTo(x + w, y + h);
clipctx.lineTo(x, y + h);
clipctx.lineTo(x, y);
clipctx.stroke();
clipctx.closePath();
clipArea = {
x,
y,
w,
h
};
} function startClip(area) {
var canvas = document.createElement("canvas");
canvas.width = area.w;
canvas.height = area.h;
var data = ctx.getImageData(area.x, area.y, area.w, area.h);
var context = canvas.getContext("2d");
context.putImageData(data, 0, 0);
return canvas.toDataURL("image/png");
} function exportImg(clipArea){
var url = startClip(clipArea);
document.getElementById("result").src = url;
document.getElementById("down").href = url;
} </script>
</html>
原生js 基于canvas写一个简单的前端 截图工具的更多相关文章
- 用node.js从零开始去写一个简单的爬虫
如果你不会Python语言,正好又是一个node.js小白,看完这篇文章之后,一定会觉得受益匪浅,感受到自己又新get到了一门技能,如何用node.js从零开始去写一个简单的爬虫,十分钟时间就能搞定, ...
- 用Canvas写一个简单的游戏--别踩白块儿
第一次写博客也不知怎么写,反正就按照我自己的想法来吧!怎么说呢?还是不要扯那些多余的话了,直接上正题吧! 第一次用canvas写游戏,所以挑个简单实现点的来干:别踩白块儿,其他那些怎么操作的那些就不用 ...
- 使用 js,自己写一个简单的滚动条
当我们给元素加上 overflow: auto; 的时候,就会出现滚动条,然而浏览的不同,滚动条的样式大不一样,有些甚至非常丑. 于是就想着自己写一个滚动条,大概需要弄清楚一下这几个点: 1.滚动条 ...
- 基于Blazor写一个简单的五子棋游戏
写这个五子棋游戏,其实主要目的是想尝试一下微软新作Blazor.Blazor对于那些搞.NET的程序员,又想做一些前端工作,真的挺友好,不用一句JS就可搞定前端交互,美哉.现在已经有很流行的前端框架, ...
- 第一个Three.js程序——动手写一个简单的场景
三维场景基本要素: 步骤: 代码: 源码: <!DOCTYPE html> <html lang="en"> <head> <meta c ...
- js eval函数写一个简单的计算器
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- 分享:计算机图形学期末作业!!利用WebGL的第三方库three.js写一个简单的网页版“我的世界小游戏”
这几天一直在忙着期末考试,所以一直没有更新我的博客,今天刚把我的期末作业完成了,心情澎湃,所以晚上不管怎么样,我也要写一篇博客纪念一下我上课都没有听,还是通过强大的度娘完成了我的作业的经历.(当然作业 ...
- Particles.js基于Canvas画布创建粒子原子颗粒效果
文章目录 使用方法 自定义参数 相关链接 Particles.js是一款基于HTML5 Canvas画布的轻量级粒子动画插件,可以设置粒子的形状.旋转.分布.颜色等属性,还可以动态添加粒子,效果非常炫 ...
- 原生js实现canvas气泡冒泡效果
说明: 本文章主要分为ES5和ES6两个版本 ES5版本是早期版本,后面用ES6重写优化的,建议使用ES6版本. 1, 原生js实现canvas气泡冒泡效果的插件,api丰富,使用简单2, 只需引入J ...
随机推荐
- Gerapy框架的使用
Gerapy 基于Scrapy,Scrapyd,Scrapyd-Client,Scrapyd-API,Django和Vue.js的分布式爬虫管理框架. 支持 Gerapy是在Python 3.x上开发 ...
- 如何在element-ui table 取到对应的ID的最后一个对象
来回切换3个状态值如何得到对应ID的最后一个对象 var is_push = () => { for (var i = 0; i < this.form.FaultDevices.leng ...
- 探索Visual Studio生成的.vs文件夹内部结构和作用
这里直接先将我摸索出的结果贴出来,文章后面会一一详细说明和分析:.vs目录是用来存储当前用户在解决方案中的工作配置,具体包括VS关闭前最后的窗口布局.最后打开的选项卡/操作记录/文件文档.某些自定义配 ...
- SSM框架中常用的配置文件
学习框架,刚开始的时候最烦的就是一些配置文件,有很多需要配置的东西,今天把这些配置文件信息稍微整理一下,以后说不定会用的到. web.xml文件 <?xml version="1.0& ...
- 西北地区打不开github的解决办法~
泱泱我大西北,github打不开,的确痛苦的. http://ipaddress.com/ip_lookup/ 先查github.com 可能存在打不开的情况~ 随便找一个web在线代理,就可以查到了 ...
- js中一个对象中遇到一个相同的key所对应的value值相加
如图: 变成: js原生如下: var abc=[ {typeid:1,ade:1}, {typeid:2,ade:1}, {typeid:1,ade:2}, {typeid:1,ade:2}, {t ...
- Prime Distance POJ - 2689 (数学 素数)
The branch of mathematics called number theory is about properties of numbers. One of the areas that ...
- 关于jmeter读取CSV文件的详细设置
jmeter 读取excel数据使用的方法是使用Jmeter CSV Data Set Config参数化 但是将excel文件保存成csv格式后,jmeter读取后返回的数据总是出现乱码问题, 以下 ...
- HDU 4283 You Are the One 【区间DP】
<题目链接> 题目大意: 有$n$个人排成一排要上台表演,每个人有一个屌丝值$pi$.第i个上台表演的人,他的不满意度为$(i-1)*p_i$.现在有一个类似于栈的黑屋子,你可以让某些人进 ...
- 错误解决记录-------------验证启动HDFS时遇到的错误
主要解决验证启动HDFS时: 1) jps:bash: jps: command not found... 原因:主要是java/bin 环境变量没配置好. 解决办法: 在 ~/.bash_prof ...