在博客园里给图片加水印(canvas + drag)

前言 想给本身的一些图片加上水印,因而就捣腾了这么个东西。
此功能没有考虑兼容性(太懒了),只在Chrome下测试经过,若是您在什么IE火狐下测试不经过就不要吐槽了。
由于应用了download属性,因此IE什么的就不用期望了,若是您是火狐浏览器的话,本身改一下兼容性应该是没问题的。
代码什么的开了F12本身拿吧,没有压缩哦。(最后吐槽一下,原本代码是贴进博客里面的,保存为草稿预览的时候也能够,结果在发布后js代码全被屏蔽了,最后只能写到页脚里了。因此获取js代码到页脚那里获取就行了)
固然你也能够访问下面这个github地址获取代码:代码地址。
另外为了弄进博客园,特地把代码从ES2015改为了ES5,因此多多少少有点乱,不过必要的注释都加上去了,这么辛苦,点个赞啊。
至于要改水印样式什么的,控制台里更改这个变量的属性便可。php

var watermarkInfo = {
  fontSize: 18, // 像素值
  fontFamily: 'cursive',
  content: '',
  color: '#fffbf0'
};

 废话就很少说了,直接上做品。
选择背景图后,设置水印文字,而后拖动水印文字到任意位置,最后点击下载文件按钮便可。css

选择背景图 设置水印
 html

实现过程当中的问题与解决方案 代码什么的就不所有贴上来了,只是讲一下其中遇到的一些问题与实现思路。
这些问题您可能已经大多了解了,不过为了兼顾全部人,因此仍是会将一些比较简单的技术点也讲一下。
整个实现过程当中遇到的问题以下
获取图片
将上传文件转换为图片
在图片上加水印
拖动文字加水印
将最后修改的图片下载下来
获取图片 获取图片实际上就是用到文件上传控件,也就是git

<input id="target_file" type="file"/>

然而原始的文件上传控件比较丑,因此隐藏此控件,并加了一个新的按钮在它前面github

<a class="btn" id="btn_select_file" href="jacascript:void(0)">选择背景图</a>
<input id="target_file" type="file" style="display:none" />

而想实现点击选择背景图按钮去选择文件,用如下代码便可canvas

// 按下选择的背景图
$('#btn_select_file').click(function () {
  $('#target_file').click();
});

选择文件后,文件上传控件会触发change事件,此时能够拿到文件。浏览器

$('#target_file').change(function (event) {
    var imgFile = event.target.files[0];
    ......
});

将文件转换为图片 文件转换为图片实际上首先须要读取文件,这里须要用到FileReader。app

function setImgIntoCanvas(imgFile) {
  var reader = new FileReader();

  reader.onloadend = function (e) {
    var dataURL = e.target.result;
    img.onload = function (event) {
      var ctx = document.getElementById('target_canvas').getContext('2d');
      //将canvas大小设置为和图片同样大
      setCanvasSize(event.target.naturalWidth, event.target.naturalHeight);
      ctx.drawImage(img, 0, 0);
      setCanvasImgToDownloadLink();
    };
    img.src = dataURL;
  };
   reader.readAsDataURL(imgFile);
   resetWatermark();
};

 
以上为核心代码,经过FileReader的readAsDataURL函数读取文件能够得到Base64格式的图片数据,将图片数据赋值给一个Image对象。
在图片上加水印 看了上面的代码,里面就有一个步骤是将图片渲染进canvas,实际上核心功能就是用canvas来给图片加水印。
操做思路就是先将图片用drawImage渲染进canvas,再在指定的位置用fillText渲染文字便可,并将最后的canvas用 toDataURL
转化为图片数据便可。
具体的用法能够参考个人代码,而后查一下canvas的API便可。
这种在新手看来很难的东西说穿了其实很简单,这里就不讲了。
 
可是接下来就麻烦了,若是是白色水印,图片上加水印的地方确定不能和图片色差过小,要否则很难发现。
因此针对不一样的图片,水印的位置确定须要可调整。
最开始的方案是给定两个输入框,而后输入位置,接着渲染水印到文本上。
可是这个方案首先就面临一个易用性的问题,我怎么得到具体的位置呢,只能一个一个去试,并非每一个用户都会用截图软件去找位置。
因此这里采用拖动文字的方案。
拖动文字加水印 canvas虽然也能捕获事件,获取鼠标位置,并实现拖动文字效果,可是实现起来太麻烦。
因此这里采用更简单的方案。
当咱们设置水印时,直接将文字渲染到canvas上,而后在文字上方安放一个颜色透明的内容为水印文字的span元素。
而后咱们在这个span元素上加drag事件。
HTML5拖动功能网上一大堆,这里就不讲了。
主要讲一下实现思路:
在开始拖动时,从新用图片渲染canvas,使得以前渲染的文字消失。
在结束拖动时,获取到具体的位置,再从新将文字渲染进canvas。
这里提及来简单,其实仍是有一些细节,包括css和js的配合,好比文字拖动到边界时的处理方式,又好比文字拖动到边界出现换行的状况。
还有一些其余的小坑点,须要你本身看代码去体会了。
这里贴出部分代码:编辑器

     // 绑定移动水印相关事件
     var bindEvent4DragWatermark = function () {
          $('#watermark').on('dragstart', function (e) {
            var ctx = document.getElementById('target_canvas').getContext('2d');
            ctx.clearRect(0, 0, $('#target_canvas').width(), $('#target_canvas').height());
            ctx.drawImage(img, 0, 0);
            // 显示可拖拽水印
            $(this).addClass('selected');
            watermarkInfo.offsetX = e.originalEvent.offsetX + canvasInfo.left;
            watermarkInfo.offsetY = e.originalEvent.offsetY + canvasInfo.top;
          });
          // 让水印跟着鼠标移动
          $('#watermark').on('drag', function (e) {
            var x = e.originalEvent.pageX;
            var y = e.originalEvent.pageY;
            if (x === 0 && y === 0) {
              return;
            }
            x -= watermarkInfo.offsetX;
            y -= watermarkInfo.offsetY;

            $('#watermark').css('left', x).css('top', y);
          });
          $('#watermark').on('dragend', function (e) {
            // 调整位置,使水印没法超出canvas边界
            var x = e.originalEvent.pageX - watermarkInfo.offsetX;
            var y = e.originalEvent.pageY - watermarkInfo.offsetY;
            if (x < 0) {
              x = 0;
            }
            if (y < 0) {
              y = 0;
            }

            var maxX = canvasInfo.width - watermarkInfo.width;
            var maxY = canvasInfo.height - watermarkInfo.height;
            if (x > maxX) {
              x = maxX;
            }
            if (y > maxY) {
              y = maxY;
            }
            $('#watermark').css('left', x).css('top', y);
            // 拖拽完水印,文本隐藏
            $('#watermark').removeClass('selected');
            setTextIntoCanvas();
          });
          // 让鼠标不显示禁用样式
          $('#canvas-container').on('dragover', function (e) {
            e.preventDefault();
          });
        }

将最后修改的图片下载下来 以前咱们已经讲到了用canvas的toDataURL函数获取最后的图片数据,而后关于下载就须要用到一个HTML5的download属性。函数

<a class="btn" id="download_file" href="#" download="水印图片">下载合成图片</a>

接下来是设置图片数据的代码

/**
 * 设置canvas图像到下载连接上
 */
function setCanvasImgToDownloadLink() {
  var imgData = document.getElementById('target_canvas').toDataURL();
  $('#download_file').attr('href', imgData);
};

将功能写进博客里 至于这部分首先要申请JS权限。
其次若是观察仔细,还能够在个人代码中看到下列代码

// 此处经过这种方式将html插入,是由于博客园自动屏蔽了canvas标签和download属性
var initHtmlConstruct = function () {
  $('#canvas-container').text('').append('<canvas id="target_canvas" width="100" height="100">浏览器不支持此功能,请升级</canvas><span draggable="true" id="watermark"></span>')
  $('#toolbar').append('<a class="btn" id="download_file" href="#" download="水印图片">下载合成图片</a>');
}

至于缘由注释里也写了,是由于博客园的编辑器屏蔽了canvas标签和download属性。
总结 总的来讲,这实际上是一个很小的功能,可是要把它作得好用一点,涉及到的知识点并很多,也不并不只仅我提到的这一点(好比canvas的透明度样式并非用图片哦,而是用css样式,仍是从《css揭秘》那本书上学到的)。
固然这个东西或多或少仍是有那么一些瑕疵,也存在一些兼容性上的问题,不过对我而言够用就好。
也但愿上面介绍的一些东西对您也有收获。

转载于猿2048:➼《在博客园里给图片加水印(canvas + drag)》

相关文章
相关标签/搜索