有了HTML5的FileReader&canvas这两个方法 不需要走后台服务就可以编辑生成图片了,插件只能在支持HTML5的浏览器上使用!!
简单制作过程和思路
1.创建画布
2.上传图片预览到画布
3.创建input参数控制样式
4.输出图片
=============================================
用到了两个知识点
1.html5 FileReader可以本地读取FILE文件
2.html5 Canvas用来绘图toDataURL生成图片
=============================================
参考学习资料
FileReader详解与实例---读取并显示图像文件
http://www.jsmix.com/blog/html5/file-reader.html
HTML5 Canvas 初步:字符串,路径,背景,图片
http://blog.csdn.net/sadfishsc/article/details/6873637
在线效果预览:http://jsfiddle.net/dtdxrk/m42VP/embedded/result/
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>原生Js基于HTML5 canvas制作的banner广告图片插件</title> 6 </head> 7 <style type="text/css"> 8 *{margin: 0;padding: 0;font:13px Arial;list-style: none;} 9 #warp{border: 1px solid #ccc;border-radius: 5px;width: 380px;background-color: #ececec;margin: 10px;line-height: 1.5;} 10 #warp li{margin: 10px;} 11 #warp li.line{background-color: #ccc;height: 1px;padding: 0;line-height: 1;font-size: 0;} 12 #warp li span{text-align: right;width: 120px;display: inline-block;} 13 #warp li #bt{padding: 5px 20px;margin:5px 0 5px 130px;} 14 #warp li a{display:inline-block;cursor: pointer;border: 1px solid #fff;text-indent: -9999px;width: 15px;height: 15px;} 15 #warp li a.active{border: 3px solid #000;} 16 #warp input[type=text]{border-radius: 3px; border: 1px solid #ccc; height: 23px;padding-left: 3px;margin: 0 5px;} 17 #warp input.short{width:40px;} 18 #warp input.w80{width:80px;} 19 #mark{position: absolute;top: 10px;left:420px;} 20 #worng{border-bottom: 1px solid red; display: none; background-color: #ffb2b2; text-align: center;font-size: 14px; font-weight: bold; padding: 5px 0;} 21 #showImg{display:none;position: absolute;top: 400px;left:420px;} 22 #showImg h1{color: red;font-weight: bold;font-family: "微软雅黑";font-size: 16px;} 23 24 .white{background-color: white;} 25 .gray{background-color: gray;} 26 .yellow{background-color: yellow;} 27 .green{background-color: green;} 28 .blue{background-color: blue;} 29 .red{background-color: red;} 30 .coffee{background-color: #632f00;} 31 .orange{background-color: orange;} 32 .purple{background-color: purple;} 33 </style> 34 <body> 35 <div id="worng">很抱歉,你的浏览器不支持FileReader方法!请安装Firefox或者Chrome浏览器</div> 36 37 <div id="warp"> 38 <ul> 39 <li><span>图片上传:</span><input type="file" name="file" id="file" /></li> 40 <li class="line"></li> 41 <li><span>广告宽度:</span><input type="text" id="adWidth" class="short" value="580" />px</li> 42 <li><span>广告高度:</span><input type="text" id="adHeight" class="short" value="180" />px</li> 43 <li class="line"></li> 44 <li><span>文字背景颜色:</span> 45 <a class="gray active" rgb="37,37,37">黑色</a> 46 <a class="white" rgb="255,255,255">白色</a> 47 <a class="yellow" rgb="244,179,0">黄色</a> 48 <a class="green" rgb="120,186,0">绿色</a> 49 <a class="blue" rgb="37,115,236">蓝色</a> 50 <a class="red" rgb="174,17,61">红色</a> 51 <a class="coffee" rgb="46,23,0">咖啡</a> 52 <a class="orange" rgb="176,30,0">橙色</a> 53 <a class="purple" rgb="114,0,172">紫色</a> 54 </li> 55 <li><span>文字背景透明度:</span><input type="text" id="bgOpacity" class="short" value="0.5" /></li> 56 <li><span>文字背景距离Top:</span><input type="text" id="bgTop" class="short" value="110" />px</li> 57 <li><span>文字背景高度:</span><input type="text" id="bgHeight" class="short" value="70" />px</li> 58 <li class="line"></li> 59 <li><span>标题文字:</span><input type="text" id="titleCon" value="标题文字" /></li> 60 <li><span>标题字号:</span><input type="text" id="titleSize" class="short" value="25" />px</li> 61 <li><span>标题颜色:</span><input type="text" id="titleColor" class="short w80" value="#fff" /></li> 62 <li><span>标题距离Top:</span><input type="text" id="titleTop" class="short" value="140" />px</li> 63 <li><span>标题距离Left:</span><input type="text" id="titleLeft" class="short" value="10" />px</li> 64 <li class="line"></li> 65 <li><span>描述文字:</span><input type="text" id="txtCon" value="描述文字描述描述描述描述" /></li> 66 <li><span>描述字号:</span><input type="text" id="txtSize" class="short" value="15" />px</li> 67 <li><span>描述颜色:</span><input type="text" id="txtColor" class="short w80" value="#fff" /></li> 68 <li><span>描述距离Top:</span><input type="text" id="txtTop" class="short" value="170" />px</li> 69 <li><span>描述距离Left:</span><input type="text" id="txtLeft" class="short" value="10" />px</li> 70 <li><button id="bt">生成图片</button></li> 71 </ul> 72 </div> 73 <canvas id="mark"></canvas> 74 <div id="showImg"> 75 <h1>这里是生成的图片 可以点击右键另存</h1> 76 <img src="" id="asImg" /> 77 </div> 78 79 <script type="text/javascript"> 80 81 var _CalF = { 82 $ : function(object){//选择器 83 if(object === undefined ) return; 84 var getArr = function(name,tagName,attr){ 85 var tagName = tagName || \'*\', 86 eles = document.getElementsByTagName(tagName), 87 clas = (typeof document.body.style.maxHeight === "undefined") ? "className" : "class";//ie6 88 attr = attr || clas, 89 Arr = []; 90 for(var i=0;i<eles.length;i++){ 91 if(eles[i].getAttribute(attr)==name){ 92 Arr.push(eles[i]); 93 } 94 } 95 return Arr; 96 }; 97 98 if(object.indexOf(\'#\') === 0){ //#id 99 return document.getElementById(object.substring(1)); 100 }else if(object.indexOf(\'.\') === 0){ //.class 101 return getArr(object.substring(1)); 102 }else if(object.match(/=/g)){ //attr=name 103 return getArr(object.substring(object.search(/=/g)+1),null,object.substring(0,object.search(/=/g))); 104 }else if(object.match(/./g)){ //tagName.className 105 return getArr(object.split(\'.\')[1],object.split(\'.\')[0]); 106 } 107 }, 108 addHandler:function(node, type, handler){ 109 node.addEventListener ? node.addEventListener(type, handler, false) : node.attachEvent(\'on\'+ type, handler); 110 }, 111 removeHandler: function (node, type, handler) { 112 node.removeEventListener ? node.removeEventListener(type, handler, false) : node.detachEvent("on" + type, handler); 113 }, 114 getPosition : function(obj) { //获取元素在页面里的位置和宽高 115 var top = 0, 116 left = 0, 117 width = obj.offsetWidth, 118 height = obj.offsetHeight; 119 120 while(obj.offsetParent){ 121 top += obj.offsetTop; 122 left += obj.offsetLeft; 123 obj = obj.offsetParent; 124 } 125 126 return {"top":top,"left":left,"width":width,"height":height}; 127 }, 128 addClass:function(c,node){ // 添加样式名 129 node.className = node.className + \' \' + c; 130 }, 131 removeClass:function(c,node){ // 移除样式名 132 var reg = new RegExp("(^|\\s+)" + c + "(\\s+|$)","g"); 133 node.className = node.className.replace(reg, \'\'); 134 }, 135 stopPropagation:function(event){ // 阻止冒泡 136 var event = event || window.event; 137 event.stopPropagation ? event.stopPropagation() : event.cancelBubble = true; 138 }, 139 ie6 : function(){ 140 return !!window.ActiveXObject && !window.XMLHttpRequest; 141 } 142 143 }; 144 145 (function(){ 146 var adWidth,adHeight, 147 bgRGB,bgColor="0,0,0",bgOpacity,bgTop,bgHeight, 148 titleCon,titleSize,titleColor,titleTop,titleLeft, 149 txtCon,txtSize,txtColor,txtTop,txtLeft; 150 151 var regex = { 152 reg0:/^([1-9]\d*)$/, // 验证正整数 153 reg1:/^-?(0|[1-9]\d*)$/, // 验证零正负整数 154 reg2:/^(0|0\.\d*|1)$/, // 验证透明度0-1 155 reg3:/^([1-9]|10|0\.\d*)$/, // 缩放比例0-10,不包含0 156 reg4:/^#([0-9a-zA-Z]{3}|[0-9a-zA-Z]{6})$/ // 验证颜色值 157 } 158 159 var tips = [ 160 \'宽高只能为大于0的整数\', 161 \'偏移量只能为零和正负整数\', 162 \'透明度值在0-1之间,包括0和1\', 163 \'字号只能为正整数\', 164 \'颜色值格式不正确,为#fff或#ffffff格式\' 165 ]; 166 167 var warp = _CalF.$("#warp"), 168 canvas = _CalF.$("#mark"), 169 image = new Image(), 170 inputs = warp.getElementsByTagName("input"), 171 inputsLen = inputs.length, 172 a = warp.getElementsByTagName("a"), 173 aLen = a.length, 174 onloadIMG = false; 175 176 //input事件 177 for(var i=0;i<inputsLen;i++){ 178 if(inputs[i].type != \'button\' && inputs[i].type != \'file\'){ 179 inputs[i].onchange = getValue; 180 } 181 } 182 183 //文字背景颜色 184 for(var h =0; h<aLen;h++){ 185 a[h].onclick = function(){ 186 for(var j=0;j<aLen;j++){ 187 _CalF.removeClass("active",a[j]); 188 } 189 bgColor = this.getAttribute("rgb"); 190 _CalF.addClass("active",this); 191 getValue(); 192 } 193 } 194 195 _CalF.$("#bt").onclick = createIMG; 196 197 if(typeof FileReader === \'undefined\' ){ //兼容判断 198 _CalF.$("#worng").style.display = "block"; 199 }else{ 200 _CalF.addHandler(_CalF.$("#file"),"change",readFile); 201 } 202 203 //选择图片 204 function readFile(){ 205 var file = this.files[0], 206 reader = new FileReader(), 207 fileFilter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i; 208 if(!fileFilter.test(file.type)){ 209 alert("请选择图像文件!"); 210 return false; 211 } 212 reader.readAsDataURL(file); 213 reader.onload = function(event){ 214 image.src = event.target.result; 215 onloadIMG = true; 216 image.onload = getValue; 217 }; 218 } 219 220 //创建画布 221 function createCanvas(){ 222 var dome = canvas.getContext(\'2d\'); 223 canvas.width = adWidth; 224 canvas.height = adHeight; 225 226 //绘制画布 227 dome.fillStyle=\'#ffffff\'; 228 dome.drawImage(image,0,0); 229 230 // 绘制描述背景 231 dome.fillStyle = bgRGB; 232 dome.fillRect(0, bgTop, adWidth, bgHeight); 233 234 // 绘制标题文字 235 dome.fillStyle = titleColor; 236 dome.font = "bold "+ titleSize + "px 微软雅黑"; 237 dome.fillText(titleCon, titleLeft, titleTop); 238 239 // 绘制描述文字 240 dome.fillStyle = txtColor; 241 dome.font = "normal " + txtSize + "px 微软雅黑"; 242 dome.fillText(txtCon, txtLeft, txtTop); 243 } 244 245 //获取input值 246 function getValue(){ 247 adWidth = _CalF.$("#adWidth").value; 248 adHeight = _CalF.$("#adHeight").value; 249 250 bgOpacity = _CalF.$("#bgOpacity").value; 251 bgTop = _CalF.$("#bgTop").value; 252 bgHeight = _CalF.$("#bgHeight").value; 253 bgRGB = "rgba("+ bgColor +","+bgOpacity+")"; 254 255 titleCon = _CalF.$("#titleCon").value; 256 titleSize = _CalF.$("#titleSize").value; 257 titleColor = _CalF.$("#titleColor").value; 258 titleTop = _CalF.$("#titleTop").value; 259 titleLeft = _CalF.$("#titleLeft").value; 260 261 txtCon = _CalF.$("#txtCon").value; 262 txtSize = _CalF.$("#txtSize").value; 263 txtColor = _CalF.$("#txtColor").value; 264 txtTop = _CalF.$("#txtTop").value; 265 txtLeft = _CalF.$("#txtLeft").value; 266 267 if(!checkFormat("adWidth",regex.reg0,tips[0],580)) return false; 268 if(!checkFormat("adHeight",regex.reg0,tips[0],180)) return false; 269 270 if(!checkFormat("bgOpacity",regex.reg2,tips[2],0.5)) return false; 271 if(!checkFormat("bgHeight",regex.reg0,tips[0],70)) return false; 272 if(!checkFormat("bgTop",regex.reg1,tips[1],110)) return false; 273 274 if(!checkFormat("titleColor",regex.reg4,tips[4],"#fff")) return false; 275 if(!checkFormat("titleSize",regex.reg0,tips[3],25)) return false; 276 if(!checkFormat("titleTop",regex.reg1,tips[1],140)) return false; 277 if(!checkFormat("titleLeft",regex.reg1,tips[1],10)) return false; 278 279 if(!checkFormat("txtColor",regex.reg4,tips[4],"#fff")) return false; 280 if(!checkFormat("txtSize",regex.reg0,tips[3],15)) return false; 281 if(!checkFormat("txtTop",regex.reg1,tips[1],170)) return false; 282 if(!checkFormat("txtLeft",regex.reg1,tips[1],10)) return false; 283 284 createCanvas(); 285 } 286 287 function checkFormat(id,reg,tip,defaultValue){ 288 var node = _CalF.$(\'#\'+id), 289 value = node.value; 290 if(!reg.test(value)){ 291 alert(tip); 292 node.value = defaultValue; 293 node.focus(); 294 return false; 295 } 296 return true; 297 } 298 299 //生成图片 300 function createIMG(){ 301 if(onloadIMG){showImg 302 var imgSrc = canvas.toDataURL("image/png"); 303 _CalF.$("#showImg").style.display = "block"; 304 _CalF.$("#asImg").src = imgSrc; 305 }else{ 306 alert("请选择图片!"); 307 } 308 } 309 310 })(); 311 312 313 </script> 314 </body> 315 </html>