Fe-interview: [js] 第162天 写个给图片加水印的方法

Created on 24 Sep 2019  ·  4Comments  ·  Source: haizlin/fe-interview

第162天 写个给图片加水印的方法

js

Most helpful comment

  • 都用Canvas的方案解决

  • 情况一:水印是图片(两张图片canvas.drawImage两次重叠即可)

<input type="file" id="uploadFile" class="clip" accept="image/*">
<label class="ui-button ui-button-primary" for="uploadFile">选择图片</label>
<img id="imgCover" src="./watermark.png" class="clip">
<p id="imgUploadX"></p>

```JavaScript
var eleUploadFile = document.getElementById('uploadFile');
var eleImgCover = document.getElementById('imgCover');
var eleImgUploadX = document.getElementById('imgUploadX');

if (history.pushState) {
eleUploadFile.addEventListener('change', function (event) {
var reader = new FileReader();
var file = event.target.files[0] || event.dataTransfer.files[0];

    reader.onload = function (e) {
        var base64 = e.target.result;
        if (base64.length > 1024 * 500) {
            alert('图片尺寸请小于500K');
            return;
        } else {
            // 使用canvas合成图片,并base64化
            imgTogether(base64, function (url) {
                // 尺寸
                var size = 180 / (window.devicePixelRatio || 1);
                // 预览
                eleImgUploadX.innerHTML = '<img src="' + url + '" width="' + size + '" height="' + size + '">';
            });
        }
    };

    reader.readAsDataURL(file);
});

// canvas图片合成
var imgTogether = function (url, callback) {
    var canvas = document.createElement('canvas');
    var size = 180;
    canvas.width = size;
    canvas.height = size;

    var context = canvas.getContext('2d');

    // 这是上传图像
    var imgUpload = new Image();
    imgUpload.onload = function () {
        // 绘制
        context.drawImage(imgUpload, 0, 0, size, size, 0, 0, size, size);
        // 再次绘制
        context.drawImage(eleImgCover, 0, 0, size, size, 0, 0, size, size);
        // 回调
        callback(canvas.toDataURL('image/png'));
    };
    imgUpload.src = url;
};

} else if (eleImgUploadX) {
eleImgUploadX.className = 'remind';
eleImgUploadX.innerHTML = '本演示IE10+下才有效果';
}

* 情况二:水印是纯文字
```CSS
#wrap {
    display: inline-block;
}

``` HTML

``` JavaScript
(function () {
    // canvas 实现 watermark
    function __canvasWM({
        // 使用 ES6 的函数默认值方式设置参数的默认取值
        // 具体参见 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Default_parameters
        container = document.body,
        image,
        width = '200px',
        height = '150px',
        textAlign = 'center',
        textBaseline = 'middle',
        font = "20px microsoft yahei",
        fillStyle = 'rgba(184, 184, 184, 0.8)',
        content = '请勿外传',
        rotate = '30',
        zIndex = 1000
    } = {}) {
        var args = arguments[0];
        var canvas = document.createElement('canvas');

        canvas.setAttribute('width', image.width);
        canvas.setAttribute('height', image.height);
        var ctx = canvas.getContext("2d");

        ctx.textAlign = textAlign;
        ctx.textBaseline = textBaseline;
        ctx.font = font;
        ctx.fillStyle = fillStyle;
        ctx.rotate(Math.PI / 180 * rotate);
        ctx.fillText(content, parseFloat(image.width) / 2, parseFloat(image.height) / 2);

        var base64Url = canvas.toDataURL();
        const watermarkDiv = document.createElement("div");
        watermarkDiv.setAttribute('style', `
        position:absolute;
        top:0;
        left:0;
        width:100%;
        height:100%;
        z-index:${zIndex};
        pointer-events:none;
        background-repeat:repeat;
        background-image:url('${base64Url}')`);
        container.style.position = 'relative';
        container.insertBefore(watermarkDiv, container.firstChild);
    }

    window.__canvasWM = __canvasWM;
})();

let imgEl = document.querySelector('#xxx');

imgEl.onload = function() {
    __canvasWM({
        container: document.querySelector('#wrap'),
        image: imgEl,
        content: 'fuck'
    })
}

All 4 comments

/**
 *
 * @param {*} image 图片 img对象
 * @param {*} words 水印内容
 */
export default function(image, words) {
  const { canvas, context } = getCanvas()
  let width = image.width
  let height = image.height
  canvas.width = width
  canvas.height = height
  canvas.style.width = image.style.width
  canvas.style.height = image.style.height

  context.drawImage(image, 0, 0)

  // 重复绘制内容贴图
  const mark = getMark(words)
  for (let i = 0; i < width; i += 250) {
    for (let j = 0; j < height; j += 250) {
      context.drawImage(mark, i, j)
    }
  }
  return toImage(canvas)
}

function toImage(canvas) {
  var image = new Image()
  image.src = canvas.toDataURL('image/png')
  return image
}

// 构造内容
function getMark(content = '') {
  const { canvas, context } = getCanvas()
  canvas.width = 200
  canvas.height = 200
  context.translate(100, 100)
  context.rotate((45 * Math.PI) / 180)
  context.font = '30px 微软雅黑'
  context.textAlign = 'center'
  // 隐形水印, 肉眼不可见,图片被人下载后可用ps查看
 // content 一般是登录的信息,用以内部截图外泄后查清截图人身份用
  context.fillStyle = 'rgba(220,20,60, 0.005)' 

  const words = content.split('\n') // 以\n为换行
  const lines = words.length
  const fontHeight = context.measureText('田').width * 1.1
  const wordsHeight = fontHeight * lines
  const start = -wordsHeight / 2
  for (let i = 0; i < lines; i++) {
    context.fillText(words[i], 0, start + i * fontHeight)
  }
  return canvas
}

function getCanvas() {
  const canvas = document.createElement('canvas')
  return {
    canvas,
    context: canvas.getContext('2d')
  }
}

想到最简单的就是直接插入一个div通过绝对定位来实现水印显示

<body>
  <img id='a' src='.\r.jpg'>

</body>
<script>
  let imgdom = document.getElementById('a')
  let imgtop = imgdom.offsetTop;
  let imgleft = imgdom.offsetLeft;
  let styleString = 'color:white;width:300px;height:50px;display:block;position:absolute;left:' + (imgleft + 50) + 'px;top:' + (imgtop + 20) + 'px;';
  let dom = document.createElement("DIV")
  let textnode = document.createTextNode('水印');
  dom.appendChild(textnode)
  dom.style = styleString;
  document.body.appendChild(dom)
</script>
  • 都用Canvas的方案解决

  • 情况一:水印是图片(两张图片canvas.drawImage两次重叠即可)

<input type="file" id="uploadFile" class="clip" accept="image/*">
<label class="ui-button ui-button-primary" for="uploadFile">选择图片</label>
<img id="imgCover" src="./watermark.png" class="clip">
<p id="imgUploadX"></p>

```JavaScript
var eleUploadFile = document.getElementById('uploadFile');
var eleImgCover = document.getElementById('imgCover');
var eleImgUploadX = document.getElementById('imgUploadX');

if (history.pushState) {
eleUploadFile.addEventListener('change', function (event) {
var reader = new FileReader();
var file = event.target.files[0] || event.dataTransfer.files[0];

    reader.onload = function (e) {
        var base64 = e.target.result;
        if (base64.length > 1024 * 500) {
            alert('图片尺寸请小于500K');
            return;
        } else {
            // 使用canvas合成图片,并base64化
            imgTogether(base64, function (url) {
                // 尺寸
                var size = 180 / (window.devicePixelRatio || 1);
                // 预览
                eleImgUploadX.innerHTML = '<img src="' + url + '" width="' + size + '" height="' + size + '">';
            });
        }
    };

    reader.readAsDataURL(file);
});

// canvas图片合成
var imgTogether = function (url, callback) {
    var canvas = document.createElement('canvas');
    var size = 180;
    canvas.width = size;
    canvas.height = size;

    var context = canvas.getContext('2d');

    // 这是上传图像
    var imgUpload = new Image();
    imgUpload.onload = function () {
        // 绘制
        context.drawImage(imgUpload, 0, 0, size, size, 0, 0, size, size);
        // 再次绘制
        context.drawImage(eleImgCover, 0, 0, size, size, 0, 0, size, size);
        // 回调
        callback(canvas.toDataURL('image/png'));
    };
    imgUpload.src = url;
};

} else if (eleImgUploadX) {
eleImgUploadX.className = 'remind';
eleImgUploadX.innerHTML = '本演示IE10+下才有效果';
}

* 情况二:水印是纯文字
```CSS
#wrap {
    display: inline-block;
}

``` HTML

``` JavaScript
(function () {
    // canvas 实现 watermark
    function __canvasWM({
        // 使用 ES6 的函数默认值方式设置参数的默认取值
        // 具体参见 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Default_parameters
        container = document.body,
        image,
        width = '200px',
        height = '150px',
        textAlign = 'center',
        textBaseline = 'middle',
        font = "20px microsoft yahei",
        fillStyle = 'rgba(184, 184, 184, 0.8)',
        content = '请勿外传',
        rotate = '30',
        zIndex = 1000
    } = {}) {
        var args = arguments[0];
        var canvas = document.createElement('canvas');

        canvas.setAttribute('width', image.width);
        canvas.setAttribute('height', image.height);
        var ctx = canvas.getContext("2d");

        ctx.textAlign = textAlign;
        ctx.textBaseline = textBaseline;
        ctx.font = font;
        ctx.fillStyle = fillStyle;
        ctx.rotate(Math.PI / 180 * rotate);
        ctx.fillText(content, parseFloat(image.width) / 2, parseFloat(image.height) / 2);

        var base64Url = canvas.toDataURL();
        const watermarkDiv = document.createElement("div");
        watermarkDiv.setAttribute('style', `
        position:absolute;
        top:0;
        left:0;
        width:100%;
        height:100%;
        z-index:${zIndex};
        pointer-events:none;
        background-repeat:repeat;
        background-image:url('${base64Url}')`);
        container.style.position = 'relative';
        container.insertBefore(watermarkDiv, container.firstChild);
    }

    window.__canvasWM = __canvasWM;
})();

let imgEl = document.querySelector('#xxx');

imgEl.onload = function() {
    __canvasWM({
        container: document.querySelector('#wrap'),
        image: imgEl,
        content: 'fuck'
    })
}
Was this page helpful?
0 / 5 - 0 ratings