Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[js] 第162天 写个给图片加水印的方法 #1257

Open
haizhilin2013 opened this issue Sep 24, 2019 · 5 comments
Open

[js] 第162天 写个给图片加水印的方法 #1257

haizhilin2013 opened this issue Sep 24, 2019 · 5 comments
Labels
js JavaScript

Comments

@haizhilin2013
Copy link
Collaborator

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

@haizhilin2013 haizhilin2013 added the js JavaScript label Sep 24, 2019
@HCLQ
Copy link

HCLQ commented Sep 25, 2019

/**
 *
 * @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')
  }
}

@vkboo
Copy link

vkboo commented Sep 25, 2019

  • 都用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>
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+下才有效果';
}
  • 情况二:水印是纯文字
#wrap {
    display: inline-block;
}
<div id="wrap">
    <img src="http://placekitten.com/600/600" id="xxx" />
</div>
<script src="js/app.js"></script>
(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'
    })
}

@ZindexYG
Copy link

小tips:使用canvas在前端实现图片水印合成

https://www.zhangxinxu.com/wordpress/2017/05/canvas-picture-watermark-synthesis/#comment

@xiaoqiangz
Copy link

可以利用canvas来加水印,ctx.drawImage(img),最后在加上水印 ctx.fillText('水印').

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
js JavaScript
Projects
None yet
Development

No branches or pull requests

6 participants
@haizhilin2013 @HCLQ @xiaoqiangz @vkboo @ZindexYG and others