fe-interview
fe-interview copied to clipboard
[js] 第162天 写个给图片加水印的方法
trafficstars
第162天 写个给图片加水印的方法
/**
*
* @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>
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'
})
}
小tips:使用canvas在前端实现图片水印合成
https://www.zhangxinxu.com/wordpress/2017/05/canvas-picture-watermark-synthesis/#comment
可以利用canvas来加水印,ctx.drawImage(img),最后在加上水印 ctx.fillText('水印').