实现功能:通过canvas给图片添加水印
web后台项目
import React, { useEffect, useRef, useState } from 'react'
import ImageBox from '@apps/components/src/web/ImageBox'
interface Props {
watermarkText?: string
imageUrl: string
imgWidth: number
imgHeight: number
}
function ImageWithWatermark(props: Props) {
const { watermarkText = '仅***平台备案使用', imageUrl, imgWidth, imgHeight } = props
const canvasRef = useRef(null)
const [imageSrc, setImageSrc] = useState<any>('')
useEffect(() => {
const canvas = canvasRef.current
const ctx = canvas.getContext('2d')
let img = new Image()
img.crossOrigin = 'Anonymous'
img.src = imageUrl
img.onload = function () {
const radio = String(img.width > 1000 ? img.width / 500 : 1)?.split('.')[0] || 1
const currentWidth = String(img.width / Number(radio))?.split('.')[0] || 1
const currentHeight = String(img.height / Number(radio))?.split('.')[0] || 1
canvas.width = currentWidth
canvas.height = currentHeight
let scaleWidth = canvas.width / img.width
let scaleHeight = canvas.height / img.height
let scale = Math.max(scaleWidth, scaleHeight)
let newWidth = img.width * scale
let newHeight = img.height * scale
let posX = (canvas.width - newWidth) / 2
let posY = (canvas.height - newHeight) / 2
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.drawImage(img, posX, posY, newWidth, newHeight)
ctx.font = 'italic bold 15px Arial'
ctx.fillStyle = 'rgba(128, 128, 128, 0.9)'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.globalAlpha = 0.9
const spacing = 140
const textWidth = ctx.measureText(watermarkText).width
const textHeight = parseInt(ctx.font.split(' ')[0], 10)
for (let x = -canvas.width; x <= 2 * canvas.width; x += spacing) {
for (let y = -canvas.height; y <= 2 * canvas.height; y += spacing) {
ctx.save()
ctx.translate(x + canvas.width / 4, y + canvas.height / 4)
ctx.rotate(-Math.PI / 6)
ctx.fillText(watermarkText, 0, 0)
ctx.restore()
}
}
const dataURL = canvas.toDataURL('image/png')
setImageSrc(dataURL)
}
}, [imageUrl, watermarkText])
return (
<>
{imageSrc ? (
<ImageBox src={imageSrc} preview width={imgWidth} height={imgHeight} style={{ objectFit: 'cover' }} />
) : (
<canvas className={'canvas'} ref={canvasRef} />
)}
</>
)
}
export default ImageWithWatermark
Taro小程序
import React, { useEffect, useState, useRef } from 'react';
import { View, Canvas } from '@tarojs/components';
import Taro from '@tarojs/taro';
const ImageWithWatermark = (props) => {
const { imageUrl, watermarkText = '仅****平台备案使用', canvasId, imgWidth = 300, imgHeight=300 } = props
const canvasNodeRef = useRef(null);
const [image, setImage] = useState<any>(null);
useEffect(() => {
Taro.getImageInfo({
src: imageUrl,
success: res => {
console.log('图片加载成功', res);
setImage(res.path);
}
});
}, []);
useEffect(() => {
if (image) {
drawImageWithWatermark(image);
}
}, [image]);
const drawImageWithWatermark = (info) => {
let ctx = Taro.createCanvasContext(canvasId);
ctx.drawImage(info, 0, 0, imgWidth, imgHeight);
ctx.font = "italic bold 15px Arial";
ctx.fillStyle = "rgba(128, 128, 128, 0.9)";
ctx.setTextAlign("center");
ctx.setTextBaseline("middle");
ctx.globalAlpha = 0.9;
const spacing = 140;
for (let x = -imgWidth; x <= 2 * imgWidth; x += spacing) {
for (let y = -imgHeight; y <= 2 * imgHeight; y += spacing) {
ctx.save();
ctx.translate(x + imgWidth / 4, y + imgHeight / 4);
ctx.rotate(-Math.PI / 6);
ctx.fillText(watermarkText, 0, 0);
ctx.restore();
}
}
ctx.draw(false, () => {
console.log('绘图完成');
});
};
return (
<View>
<Canvas
canvasId={canvasId}
style={{ width: imgWidth, height: imgHeight }}
ref={canvasNodeRef}
/>
</View>
);
};
export default ImageWithWatermark;