逻辑:利用canas画图,参数为员工编号+姓名+本地图片,将传过来的图,画上水印
效果图为附件图
/** * 设置水印的样式 * @param employeeIdimg 身份证照片 * @param employeeNumber 员工编号 * @param employeeName 员工姓名 * @param basUrl http://local.cbs.bacic5i5j.com:8080/base/ * @return {string} */ function watermark(employeeIdimg,employeeNumber,employeeName,callback){ console.log("watermark--start"); var watermark = document.createElement('canvas'); var repeatWatermark = document.createElement('canvas'); watermark.width = 230; watermark.height = 143; watermark.style.display = 'none'; repeatWatermark.style.visibility = 'hidden'; var imglogo = new Image(); var IDimg = new Image(); imglogo.src = basePath+'/static/resources/img/5i5j_logo.png'; var src=basePath + '/system/water.htm?fileUrl=' + encodeURIComponent(employeeIdimg); loadImg(src, function(IDimg){ document.body.appendChild(watermark); document.body.appendChild(repeatWatermark); var fillEmployeeInfo=employeeNumber+" "+employeeName; //var width = 460,height = 286; var width= IDimg.naturalWidth || IDimg.width; var height = IDimg.naturalHeight || IDimg.height; repeatWatermark.width = width; repeatWatermark.height = height; var ctx = watermark.getContext("2d"); var ctxr = repeatWatermark.getContext("2d"); ctx.font="18px 黑体"; ctx.rotate(-20*Math.PI/110); ctx.fillStyle = "rgba(0,0,0,.41)"; ctx.fillText(fillEmployeeInfo, -10, 115); //ctx.fillText("我爱我家", 25, 132); ctx.drawImage(imglogo, -8, 120, 122, 33); ctx.font="12px 黑体"; //ctx.fillText("www.5i5j.com", 28, 142); ctx.rotate('20*Math.PI/110'); ctxr.clearRect(0,0,width,height); //清除整个画布 ctxr.drawImage(IDimg, 0, 0,width,height); var pat = ctxr.createPattern(watermark, "repeat"); //在指定的方向上重复指定的元素 ctxr.fillStyle = pat; ctxr.fillRect(0, 0, width, height); callback && callback(repeatWatermark.toDataURL('image/png')); document.body.removeChild(watermark); document.body.removeChild(repeatWatermark); console.log("watermark--end"); }) } /** * 加载图片 * @param src * @param callback */ function loadImg(src, callback) { var img = new Image(); var loaded = false; var pollingTimer; var onload = img.onload = function () { if (!loaded) {// 确保图片加载完成的回调只会触发一次 callback(img); loaded = true; clearTimeout(pollingTimer);// 清除轮训器 } }; img.src = src; function polling() { if (img.complete) {// 图片加载成功后,该属性为true,否则为false onload();// 这里主动触发 img.load,防止在某些浏览器中因为缓存的原因未触发load } else { pollingTimer = setTimeout(polling, 13);// 轮训器 } } polling(); }
最开始的时候,火狐,谷歌浏览器都可以,ie也可以,后来发现某些ie版本下不支持,所以改成loadImg这个方法,本人对js不太熟悉,这是借鉴了高手的经验才研究出来
另外,使用src=连接,这种方式其实是调用了后台的逻辑,用后来将图片转化成流的方式
后台代码为:
@RequestMapping("/water")
@ResponseBody
public Object getWaterUrl(HttpServletRequest request, HttpServletResponse response, String fileUrl)throws Exception {
BufferedInputStream dis = null;
BufferedOutputStream fos = null;
String fileName = fileUrl.substring(fileUrl.lastIndexOf("/"));
String ext = fileName.indexOf(".") > -1 ? "" : fileUrl.substring(fileUrl.lastIndexOf('.'));
try {
URL url = new URL(fileUrl);
response.setContentType("applicatoin/octet-stream");
response.setHeader("Content-disposition", "attachment; filename=" + fileName + ext);
response.setHeader("Content-Length", String.valueOf(url.openConnection().getContentLength()));
dis = new BufferedInputStream(url.openStream());
fos = new BufferedOutputStream(response.getOutputStream());
byte[] buff = new byte[2048];
int bytesRead;
while (-1 != (bytesRead = dis.read(buff, 0, buff.length))) {
fos.write(buff, 0, bytesRead);
}
} catch (Exception e) {
LOGGER.error(e.getMessage());
LOGGER.error("下载图片异常,参数:{},异常:{}", ReflectionToStringBuilder.toString(fileUrl), e.getMessage());
throw new BusinessException( "下载异常,请稍后再试");
} finally {
if (dis != null)
dis.close();
if (fos != null)
fos.close();
}
return null;
}