原生Js基于HTML5 FileReader&canvas制作的banner广告图片插件

时间:2024-02-18 16:13:56

有了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>