一、canvas加水印其实就是将目标图片先画在canvas上,然后再把水印(文字或者图片)画在canvas上。如下代码:
function WaterMark($markImgSrc, $text, $textAngle){ this.canvas = document.createElement('canvas'), this.context = this.canvas.getContext('2d'), this.markImg, PI=Math.PI, Tan=Math.tan, Sin=Math.sin, Cos=Math.cos, Int=parseInt, outer = this; function doMark(bkimg, originLoad, text, angle){ var W=bkimg.width, H=bkimg.height, fontSize='40px'; angle = (angle || 0)*PI/180; outer.canvas.width=W, outer.canvas.height=H; outer.context.drawImage(bkimg, 0, 0, W, H); !!$markImgSrc && outer.context.drawImage(outer.markImg, 10, 10, outer.markImg.width, outer.markImg.height); if(typeof text!=='undefined'){ outer.context.save(); outer.context.textAlign='start';//start,left,right,end,center outer.context.textBaseline='top'; outer.context.font=fontSize+" 黑体"; outer.context.fillStyle="red"; //计算文字位置 var txtWidth=+outer.context.measureText(text).width,/*获得文本宽度*/ txtHeight=Int(fontSize), x=W-txtWidth, y=H-txtHeight, centerX=txtWidth/2+x,centerY=txtHeight/2+y; outer.context.translate(centerX, centerY);//由于rotate的旋转中心是画布左上角,要使旋转围绕目标元素中心,则需要将画布原点移动到元素中心位置,而translate就能使我们达到目的。 outer.context.rotate(angle);//注意顺序,一定是在translate将画布原点平移了之后,才可应用rotate. outer.context.fillText(text,-txtWidth/2,-txtHeight/2);//此时目标元素的左上角坐标是相对于平移之后的画布来算的 outer.context.rotate(-angle);//还原旋转 outer.context.translate(-centerX, -centerY);//记得将画布移动回原来的位置。 outer.context.save(); } bkimg.src = outer.canvas.toDataURL('image/jpeg'); bkimg.onload = originLoad; } function randStr(){ return ''+Math.random()+(new Date).getTime(); } function log(obj){ console.log(obj+Math.random()); } this.setImage = function(img){ img.crossOrigin = "Anonymous";//此行代码的作用请看二 img.crossOrigin = "*";//此行代码的作用请看二 return { mainImg:img, create:function(){ if(!document.createElement('canvas').getContext) return; if(typeof this.mainImg ==='undefined') return alert('未绑定图片对象'); var oldload = this.mainImg.onload, me=this; if(!!$markImgSrc){ outer.markImg=new Image(); outer.markImg.onload = function(){ me.mainImg.onload = function(){ typeof oldload === 'function' && oldload(); doMark(me.mainImg, oldload, $text, $textAngle); } me.mainImg.src=me.mainImg.src+'?'+randStr(); } outer.markImg.src=$markImgSrc+'?'+randStr(); }else{ me.mainImg.onload = function(){ typeof oldload === 'function' && oldload(); doMark(me.mainImg, oldload, $text, $textAngle); } me.mainImg.src=me.mainImg.src+'?'+randStr(); } } } }; } var obj = new WaterMark('text.png', 'Hellow world, 不错'); //obj.setImage(image).create(); //obj.setImage(image2).create(); //obj.setImage(image3).create(); $(function(){ $('#container img').each(function(){ obj.setImage(this).create(); }); });二、上面的代码只能处理本域的图片,对于跨域图片应该做些特殊处理。首先,将目标图片的crossOrigin属性设置成*或者 Anonymous。然后,我们还要在目标图片的服务器上做些文章(如果没有权限修改目标图片所在的web服务配置,那就只能歇菜。),以apache为图片服务器为例,我们需要在web目录或者图片目录下添加一个.htaccess文件,其内容为:
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
<FilesMatch "\.(cur|gif|ico|jpg|jpe?g|png|svgz?|webp)$">
SetEnvIf Origin ":" IS_CORS
Header set Access-Control-Allow-Origin "*" env=IS_CORS
</FilesMatch>
</IfModule>
</IfModule>
设置好之后,就可以将此域名下的图片进行处理了。
三、前端加水印应用场景有限,为了使本文有更多的干货,特附上php给图片加水印的代码:
/** *@author yiqingpeng @2016-09-27 *功能:给jpg图片加文本水印。 *本类也可通过继承重载createImgSource方法可扩展成针对png,tmp图像类型加水印 */ class WaterMark{ protected $imgfile; protected $text; protected $imgSource; protected $fontSize=30; protected $fontColor=array(255,0,0);//array(r,g,b) public function __construct($imgfile, $text){ $this->imgfile = $imgfile; $this->text = $text; $this->createImgSource(); } public function create(){ $this->addText(); } protected function createImgSource(){ try{ $this->imgSource=imagecreatefromjpeg($this->imgfile); return true; }catch(Exception $e){ return false; } } public function setFontSize($fontSize){ $this->fontSize = (int)$fontSize; return $this; } public function setFontColor(array $rgb){ $this->fontColor = $rgb; return $this; } protected function addText(){ try{ $fontColor=imagecolorallocate($this->imgSource, $this->fontColor[0], $this->fontColor[1], $this->fontColor[2]); $fontAngle = 0; $imgWidth = imagesx($this->imgSource); $imgHeight = imagesy($this->imgSource); $fontType = 'simsun.ttc'; $fontbbox = imagettfbbox($this->fontSize, $fontAngle, $fontType, $this->text); $x = $imgWidth - $fontbbox[4]-5; $y = $imgHeight - $fontbbox[3]-3; imageTTFtext($this->imgSource, $this->fontSize, $fontAngle, $x, $y, $fontColor, $fontType, $this->text); }catch(Exception $e){ exit($e->getMessage()); return false; } } public function out(){ header("Pragma:no-cache\r\n"); header("Cache-Control:no-cache\r\n"); header("Expires:0\r\n"); header("Content-type:Image/jpeg\r\n"); imagejpeg($this->imgSource); } public function __destruct(){ imagedestroy($this->imgSource); } } $wm = new WaterMark('image.jpg','中国第一no1..'); $wm->create(); $wm->out();