不是专门做前端的,代码写的不太好,权当抛砖引玉。
整体思路:
共有5层,除了背景颜色的div没什么用之外,canvas1用来读取图片作为背景,canvas2把文字展示出来,并记录拖拽文字的位置,canvas4 绘制拖拽后文字的位置,canvas3在最后保存的时候,把背景图片和文字重新绘制出来,canvas4用来把canvas1背景图片和canvas3拖拽后的文字给画到一个canvas上,保存图片,还有一个canvas,判断canvas1是不是空的。
除此之外,还用到了判断当前浏览器支持的字体,和颜色选择器,网络上都可以找到就不说了。
下边儿是效果和代码
代码如下
<!DOCTYPE html><html><head><meta charset="utf-8"><title></title><script type="text/javascript" src="js/jquery-1.12.3.min.js"></script><script type="text/javascript" src="js/font-ch-en.js" charset="utf-8"></script><script type="text/javascript" src="js/isSupportFontFamily.js" charset="utf-8"></script><script type="text/javascript" src="js/jquery1.4.3.js" charset="utf-8"></script> <script type="text/javascript" src="js/jquery.colorpicker.js" charset="utf-8"></script><style>td{text-align: center;}</style></head><body style="background-color: #F1F2F6;"><div><div id="canvas_box" style="overflow: hidden;position: relative;"><div style="width: 900px;height: 600px;background: #333;float: left;border-radius: 10px;margin-left: 100px;margin-top: 40px;"></div><canvas id="canvas3" style="width: 900px;height: 600px;display: block;position: absolute;margin-left: 100px;margin-top: 40px;" ></canvas><canvas id="canvas4" style="width: 900px;height: 600px;display: block;position: absolute;margin-left: 100px;margin-top: 40px;" ></canvas><canvas id="canvas1" style="width: 900px;height: 600px;display: block;position: absolute;margin-left: 100px;margin-top: 40px;" ></canvas><canvas id="canvas2" style="width: 900px;height: 600px;display: block;position: absolute;margin-left: 100px;margin-top: 40px;" ></canvas></div><div style="position: absolute;margin-left: 1100px;margin-top: -500px;"><table style="border: solid 3px #7399cd;width: 280px;height: 360px;border-radius: 10px;"><tr><td ><input type="button" value="请选择图片" onclick="javascript:$('input[name=\'file\']').click();" style="border-radius: 5px;background-color: #337AB7;color: #F2FFFF;border: none;height: 35px;width: 90px;"/><input name="fileName" readonly style="background-color: transparent;border:0;display: none;"/><input type="file" name="file" id="fileOne" accept=".jpg,.png" style="display: none;" onchange="javascript:$('input[name=\'fileName\']').val(this.files[0].name);" /></td></tr><td><div >请输入名字 <input id="name" type="text" style="border-radius: 5px;border: 1px solid #3F3F40;width: 80px;" oninput="changeFont()" /></div></td><tr><td><div >请选择字体 <select id="fontFam" style="border-radius: 5px;border-color: black;width: 88px;height: 22px;" onchange="changeFont()"><option>请选择</option></select></div></td></tr><tr><td><div >请选择样式 <select id="fontSty" style="border-radius: 5px;border-color: black;width: 88px;height: 22px;" onchange="changeFont()"><option value="normal">正常</option><option value="oblique">斜体</option></select></div></td></tr><tr><td><div >请选择粗细 <select id="fontSty" style="border-radius: 5px;border-color: black;width: 88px;height: 22px;" onchange="changeFont()"><option value="normal">常规</option><option value="600">斜体</option><option value="900">斜体</option></select></div></td></tr><tr><td><div >请选择字号 <input id="Btn1" type="button" value="+" name=""/><input id="fontSize" value="12" style="border-radius: 5px;border: 1px solid #3F3F40;width: 30px;text-align: center;height: 18px;" onchange="changeFont()"/><input id="Btn2" type="button" value="-" name=""/></div></td></tr><tr><td><div >请选择颜色 <input type="text" id="fontCol" value="#DBD71E" style="border-radius: 5px;border: 1px solid #3F3F40;width: 80px;" oninput="changeFont()" onchange="changeFont()"/></div></td></tr><tr><td><font style="color: red;" size="2">拖动左侧文字以调整位置</font></td></tr><tr><td ><input type="button" id="btn" value="下载图片" style="border-radius: 5px;background: #5CB85C;color: #fcfcf9;border: none;height: 35px;width: 90px;" onclick="downloadimg()"/></td></tr></table><div id="result"></div></div></div><script>/* canvas1显示背景图片canvas2显示文字,并记录拖拽文字的位置canvas4绘制拖拽后文字的位置canvas3最后保存的时候,把背景图片和文字重新绘制出来*/// 文字样式const fontSty = document.getElementById('fontSty');// 文字内容const name = document.getElementById("name");// 文字字体const fontFam = document.getElementById('fontFam');// 文字大小const fontSi = document.getElementById("fontSize");// 文字颜色const fontCol = document.getElementById("fontCol");const oBtn1=document.getElementById("Btn1");const oBtn2=document.getElementById("Btn2");const canvas1 = document.getElementById('canvas1');const ctx1 = canvas1.getContext('2d');const canvas2 = document.getElementById('canvas2');const ctx2 = canvas2.getContext('2d');const canvas3 = document.getElementById('canvas3');const ctx3 = canvas3.getContext('2d');const canvas4 = document.getElementById('canvas4');const ctx4 = canvas4.getContext('2d');const canvas5 = document.getElementById('canvas5');const inputOne = document.getElementById('fileOne');window.onload= function(){// 获取浏览器支持的字体loadFontFamily()}// 字号+-点击动作oBtn1.onclick = function(){num = fontSi.value;num++;fontSi.value = num;if ("createEvent" in document) {var evt = document.createEvent("HTMLEvents");evt.initEvent("change", false, true);fontSi.dispatchEvent(evt);} else {fontSi.fireEvent("onchange");}};oBtn2.onclick = function(){num = fontSi.value;num--;fontSi.value = num;if ("createEvent" in document) {var evt = document.createEvent("HTMLEvents");evt.initEvent("change", false, true);fontSi.dispatchEvent(evt);} else {fontSi.fireEvent("onchange");}}//颜色拾取器$("#fontCol").colorpicker({target:'#title',success:function(o,color){fontCol.value = colorif ("createEvent" in document) {var evt = document.createEvent("HTMLEvents");evt.initEvent("change", false, true);fontCol.dispatchEvent(evt);} else {fontCol.fireEvent("onchange");}},reset:function(o){fontCol.value = '#000000'}});// 获取浏览器支持的字体function loadFontFamily(){// 数据var arrFont = dataFont['windows'].concat(dataFont['OS X'], dataFont['office'], dataFont['open']);var option = '';arrFont.forEach(function (obj) {var fontFamily = obj.en;if (isSupportFontFamily(fontFamily)) {option = option + '<option value="'+ fontFamily +'">'+ obj.ch +'</option>';}});fontFam.innerHTML = option;fontFam.value = "STXingkai";}//读取本地文件inputOne.onchange = function () {//1.获取选中的文件列表var fileList = inputOne.files;var file = fileList[0];//读取文件内容var reader = new FileReader();reader.readAsDataURL(file);reader.onload = function (e) {//将结果显示到canvasshowCanvas(reader.result);}}//指定图片内容显示function showCanvas(dataUrl) {//加载图片var img = new Image();img.src = dataUrl;img.onload = function(){//设置宽高一定要在canvas节点添加之后canvas1.width = img.width;canvas1.height = img.height;canvas2.width = img.width;canvas2.height = img.height;ctx1.drawImage(this, 0, 0,img.width,img.height);}}//canvas2的拖拽动作var aa = 0 var bb = 0 canvas2.onmousedown = function(args){var evt = args || event;var StartX = evt.clientX;var StartY = evt.clientY;let initleft = Number((canvas2.style.left).replace('px',''))let inittop = Number((canvas2.style.top).replace('px',''))document.onmousemove = function(ev){var iEvent = ev||event; // 鼠标移动的距离let left = iEvent.clientX - StartX;let top = iEvent.clientY - StartY;// 鼠标移动的距离 + 最开始的top 或者 left 就是最终的位置canvas2.style.left = left + initleft + 'px';canvas2.style.top = top + inittop +'px';aa = (left + initleft)/900;bb = (top + inittop)/600;}document.onmouseup = function(){document.onmousedown = null; document.onmousemove = null; }; return false; }//验证canvas画布是否为空函数function isCanvasBlank(canvas) {var blank = document.createElement('canvas');//系统获取一个空canvas对象blank.width = canvas.width;blank.height = canvas.height;return canvas.toDataURL() == blank.toDataURL();//比较值相等则为空}//修改文字属性var fontStyle = ''var fontFamily = ''var fontSize = ''var fontt = ''var fontColor = ''function changeFont(){if(isCanvasBlank(canvas1)){alert("请先选择图片");return;}var text = name.value;fontStyle = fontSty.value;fontFamily = fontFam.value;fontSize = fontSi.value;fontt = fontStyle+' '+fontSize+'0px'+' '+ fontFamily;fontColor = fontCol.value;canvas2.width = canvas2.widthcanvas3.width = canvas3.widthif(canvas2.getContext){ctx2.beginPath();ctx2.fillStyle = fontColor;// 设置填充画笔颜色为红色,即字体颜色ctx2.font = fontt;// 设置字体大小ctx2.fillText(text,700,1030);// 绘制 "实心" 文字// fillText(str, x, y, maxW):str绘制的文字,(x, y)起始坐标,maxW是最大宽度,绘制文字超过该宽度则不显示。ctx2.closePath();}else{alert('不支持');}}//保存图片function downloadimg() {document.getElementById("btn").disabled = true;canvas3.getContext('2d');canvas3.width = canvas1.width;canvas3.height = canvas1.height;canvas4.width = canvas1.width;canvas4.height = canvas1.height;ctx4.beginPath();ctx4.fillStyle = fontColor;// 设置填充画笔颜色为红色,即字体颜色ctx4.font = fontt;// 设置字体大小ctx4.fillText(name.value,700+aa*canvas2.width,1030+bb*canvas2.height);// 绘制 "实心" 文字ctx4.closePath();ctx3.drawImage(canvas1, 0, 0, canvas1.width, canvas1.height);ctx3.drawImage(canvas4, 0, 0, canvas1.width, canvas1.height);// 创建一个 a 标签,并设置 href 和 download 属性const el = document.createElement('a');// 设置 href 为图片经过 base64 编码后的字符串,默认为 png 格式el.href = canvas3.toDataURL();el.download = name.value;// 创建一个点击事件并对 a 标签进行触发const event = new MouseEvent('click');el.dispatchEvent(event);canvas4.width = canvas1.width;document.getElementById("btn").disabled = false;}</script></body></html>
tips:实际应用的时候,发现判断canvas为空这个比较耗资源,会导致填写文字的时候卡卡的。