zoukankan      html  css  js  c++  java
  • 原生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 {
    				 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;
    				 102px;
    				height: 38px;
    				line-height: 38px;
    				border-radius: 4px;
    			}
    
    			#clipcanvas {
    				position: absolute;
    				top: 0;
    				left: 0;
    				z-index: 10;
    				 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>
    

      

  • 相关阅读:
    Bottle python
    mongodb python pymongo
    Directory常用
    File类常用
    Path类的常用方法
    winfrom的单例模式
    325工厂模式和面向对象知识点总结(有点乱凑合看)
    音乐播放器自动播放下一首歌记录
    c#分页类(转)
    c# 简历生成器
  • 原文地址:https://www.cnblogs.com/muamaker/p/10717224.html
Copyright © 2011-2022 走看看