不是专门做前端的,代码写的不太好,权当抛砖引玉。

整体思路:
共有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 >请输入名字&nbsp;<input id="name" type="text" style="border-radius: 5px;border: 1px solid #3F3F40;width: 80px;" oninput="changeFont()" /></div></td><tr><td><div >请选择字体&nbsp;<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 >请选择样式&nbsp;<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 >请选择粗细&nbsp;<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 >请选择字号&nbsp;<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 >请选择颜色&nbsp;<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为空这个比较耗资源,会导致填写文字的时候卡卡的。

canvas读取图片,输入文字,调整文字属性,拖拽文字位置,并保存图片相关推荐

  1. canvas在图片上绘制标记,可拖拽、缩放,基于ZRender

    如下图所示,在图片上做标记,如圆形.矩形等. 该demo实现画布在页面布局中缩放后居中显示,可拖拽.缩放.做标记说明. 项目下载地址:https://gitlab.com/zhangcw66/draw ...

  2. canva画图 图片居中裁剪_Canvas裁剪图片(截选框可拖拽)

    利用Canvas实现图片裁剪 效果图 实现思路 打开图片并将图片绘制到canvas中: 利用canvas的drawImage()函数来裁剪图片: 将canvas转化为Image即可. HTML代码: ...

  3. 图片img或者含有img元素拖拽时,或者scale缩放时产品的阴影效应问题

    图片img或者含有img元素拖拽时,或者用scale缩放时产品的阴影效应问题 html中有图片img或者含有img元素拖拽时,或者scale缩放时产品的阴影效应问题,也就是图片重影, 另外使用scal ...

  4. Android 7.0 分屏拖拽文字和图片的研究

    一 前提 二 实测一 三 实测二 四 分析 1 分屏拖拽实现分析-Activity间 ViewstartDragAndDrop 实现拖拽图片的例子 2 拖拽实现分析-Activity内 一. 前提 1 ...

  5. vue 移动到图片浮动_基于Vue实现拖拽升级(九宫格拖拽)

    前言 在本文中将会用Vue完成九宫格拖拽效果,同时介绍一下网格布局.具体代码以及demo可以点以下超链接进入 效果实例 Demo 简单了解Grid布局(网格布局) 什么是网格布局 CSS网格布局(又称 ...

  6. 图片多选上传拖拽切换位置

    html文件 <!DOCTYPE html> <html> <head>     <meta charset="UTF-8">   ...

  7. C# 图片盖章功能实现,支持拖拽-旋转-放缩-保存

    实现图片盖章功能,在图片上点击,增加"图章"小图片,可以拖拽"图章"到任意位置,也可以点击图章右下角园框,令图片跟着鼠标旋转和放缩. 操作方法:1.点击增加&q ...

  8. Vue实现图片预览(放大缩小拖拽)纯手写

    这张图是显示的图片放大的一个预览情况,这里是参考预览操作实现的一个背景为黑色的部分,上层的图片可实现滚轮放大或者点击上部的放大镜图标进行放大,代码是基于Ant Design Vue框架的基础上 这里先 ...

  9. 微信小程序图片上传、多图拖拽排序功能

    基于movable-view实现的拖拽功能 可以建一个 dragImg的文件 wxml的代码 <view class="container"><movable-a ...

最新文章

  1. spark 执行流程及各组件执行
  2. 贫血模型,充血模型(领域驱动设计)
  3. Python 引用全局变量提示:local variable referenced before assignment. 问题解决办法,global使用方法介绍
  4. 大牛深入浅出讲解c语言do{...}while(0)功能及用法
  5. 【C++学习】String类的基本用法
  6. WPF实现拟物旋转按钮
  7. JavaScript中的arguments对象
  8. python 操作excel 教程_Python学习笔记(十六)—Python操作Excel
  9. Pseudo code:伪代码
  10. minikube start 使用Hyper-V
  11. IAR编译器中函数智能提示
  12. 多线程之终止线程的四种方法
  13. docker 搭建nginx php mysql_docker搭建nginx+mysql+php
  14. 尚硅谷html+css小米官网
  15. Python中的图像处理(第十一章)Python图像锐化及边缘检测(2)
  16. 【FinE】债券久期和凸性
  17. linux 拼音输出繁体_解决rime仓颉拼音反查为繁体的问题
  18. EGO Planner代码解析bspline_optimizer部分(3)
  19. 桌上游戏(桌面游戏)入门指南
  20. Linux中将4块10T新硬盘合并成一个,挂载到Resource目录下

热门文章

  1. python installer 在 mac 运行_python – 如何在Mac OS X 10.7中的virtualenv中安装PyAudio
  2. C++虚函数的实现原理(最通俗但并不想专业的解释)
  3. Python读取文本文件
  4. DPDK examples cmdline完全注释(添加quit功能)
  5. Django:ORM基本操作-CRUD,管理器对象objects,----->聚合查询、原生数据库操作
  6. VUE3(template使用)
  7. sklearn之Multiclass 估计器
  8. 三类测量血压原理 - 智能手环测血压原理详解
  9. 3项目里面全局用less变量 cli vue_vue-cli3全局载入scss变量或less变量配置
  10. mysql作业是什么意思_MySQL 作业七