今天学习了一下水印的生成方案
转自:https://juejin.im/entry/5b55db355188251b11097366
主要学习的是通过canvas生成水印,加上MutationObserve监视DOM的变动
修改了一些代码如下:
import React from 'react'
const watermark = ({
container = document.body, //容器
width = '300px', //水印的大小
height = '200px',
textAlign = 'center', //文字对齐
textBaseline = 'middle', //基准线
font = "20px Microsoft Yahei", //字体大小及样式
fillStyle = 'rgba(184, 184, 184, 0.4)',//自定义水印的颜色以及透明度
content = 'Open Components',//内容
rotate = '24',//文字旋转角度
zIndex = 1000,//元素堆叠顺序,-1是在最下面
} = {}) => {
const args = arguments[0];
const canvas = document.createElement('canvas');
//HTML5 <canvas> 元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
const ctx = canvas.getContext("2d");//当前唯一的合法值是 "2d",它指定了二维绘图
ctx.textAlign = textAlign;
ctx.textBaseline = textBaseline;
ctx.font = font;
ctx.fillStyle = fillStyle;
ctx.rotate(Math.PI / 180 * rotate);
ctx.fillText(content, parseFloat(width) / 2, parseFloat(height) / 2);
const base64Url = canvas.toDataURL();
//返回一个包含图片展示的 data URI 。可以使用 type 参数其类型,默认为 PNG 格式。
const __wm = document.querySelector('.__wm');//选择器
const watermarkDiv = __wm || document.createElement("div");
const styleStr = `
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
z-index:${zIndex};
pointer-events:none;
background-repeat:repeat;
background-image:url('${base64Url}')`;
watermarkDiv.setAttribute('style', styleStr);
watermarkDiv.classList.add('__wm');//在元素中添加类名,可以加载CSS样式
if (!__wm) {
container.style.position = 'relative';
container.insertBefore(watermarkDiv, container.firstChild);//添加元素
}
const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
//检查浏览器是否支持这个API
if (MutationObserver) {
let mo = new MutationObserver(function () {
const __wm = document.querySelector('.__wm');
// 只在__wm元素变动才重新调用 __canvasWM
if ((__wm && __wm.getAttribute('style') !== styleStr) || !__wm) {
// 避免一直触发
mo.disconnect();
mo = null;
watermark(JSON.parse(JSON.stringify(args)));
}
});
mo.observe(container, {
attributes: true,//观察目标节点的属性节点
subtree: true,//观察目标节点的所有后代节点
childList: true,//观察目标节点的子节点
})
}
}
export default watermark;
这样我们就可以在界面里面引用生成水印的方法啦!
但是,在引用时我发现,引用这一方法只能在生命周期中写,如果我用的是stateless写法,在使用getElementById等获取dom对象的方法时无效,获取的是NULL。这是因为我们的方法应当在react加载完所有dom后再使用。所以要写进生命周期中
import watermark from ‘ ’
componentDidMount() {
watermark({ content: 'Open Components' ,
container: document.getElementById('waterbody')
});
}
如果有其他想覆盖的属性只要在方法里面覆盖就好啦!
接下来试了一下给图片加水印
export const picWaterMark = ({
url = '',
textAlign = 'center',
textBaseline = 'middle',
font = "20px Microsoft Yahei",
fillStyle = 'rgba(255, 255, 255, 0.8)',
content = '请勿外传',
cb = null,
textX = 500,
textY = 500,
} = {}) => {
const img = new Image();
img.src = url;
img.crossOrigin = 'anonymous';
img.onload = function () {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
ctx.textAlign = textAlign;
ctx.textBaseline = textBaseline;
ctx.font = font;
ctx.fillStyle = fillStyle;
ctx.fillText(content, img.width - textX, img.height - textY);
const base64Url = canvas.toDataURL();
cb && cb(base64Url);
}
}
接下来在要添加水印的图片里这么写:
import React from 'react'
import { picWaterMark } from '../../utils/shuiyin'
class MyImage extends React.Component {
componentDidMount() {
picWaterMark({
url: document.getElementById('myimage').src,
content: 'QQMusicFE',
cb: (base64Url) => {
document.querySelector('img').src = base64Url
},
});
//console.log( document.getElementById('myimage').src)
}
render() {
return (
<div>
<img id={"myimage"} src={require("../../../assets/85456383705460.jpg")} style={{ width: 1200, height: 800 }} />
</div>
);
}
}
export default MyImage
一开始遇到了困难是调用方法中的URL是不对的,但我明明写的是../../../assets/85456383705460.jpg,
最后console了一下发现URL已经变成
http://localhost:8000/static/85456383705460.846d9ef5.jpg
于是换了方法,改成
url: document.getElementById('myimage').src,
显示出来啦,不过不细看是真的看不出在哪
【完】
如果有不对的地方希望大家能帮我指出三克斯