말도 안 되는 일의 시작: 워터마크를 덮는 간단한 기능을 구현하세요. 일반적으로 사진에 워터마크를 추가한 다음 처리된 사진을 직접 로드합니다. url 사진은 수정되지 않고 워터마크가 직접 추가됩니다. 캔버스 마스크를 dom에 착용하세요.
1. 효과
처리 전
DIV
IMG
처리 후
DIV
IMG
여기에 "워터마크 추가" " "(사실 실제 워터마크는 아닙니다.) DIV에 도달하면 마스크로 인해 버튼 클릭 이벤트가 취소되지 않습니다.
2. JS 코드
class WaterMark{ //水印文字 waterTexts = [] //需要添加水印的dom集合 needAddWaterTextElementIds = null //保存添加水印的dom saveNeedAddWaterMarkElement = [] //初始化 constructor(waterTexts,needAddWaterTextElementIds){ if(waterTexts && waterTexts.length != 0){ this.waterTexts = waterTexts } else { this.waterTexts = ['水印文字哈哈哈哈','2022-12-08'] } this.needAddWaterTextElementIds = needAddWaterTextElementIds } //开始添加水印 startWaterMark(){ const self = this if(this.needAddWaterTextElementIds){ this.needAddWaterTextElementIds.forEach((id)=>{ let el = document.getElementById(id) self.saveNeedAddWaterMarkElement.push(el) }) } else { this.saveNeedAddWaterMarkElement = Array.from(document.getElementsByTagName('img')) } this.saveNeedAddWaterMarkElement.forEach((el)=>{ self.startWaterMarkToElement(el) }) } //添加水印到到dom对象 startWaterMarkToElement(el){ let nodeName = el.nodeName if(['IMG','img'].indexOf(nodeName) != -1){ //图片,需要加载完成进行操作 this.addWaterMarkToImg(el) } else { //普通,直接添加 this.addWaterMarkToNormalEle(el) } } //给图片添加水印 async addWaterMarkToImg(img){ if(!img.complete){ await new Promise((resolve)=>{ img.onload = resolve }) } this.addWaterMarkToNormalEle(img) } //给普通dom对象添加水印 addWaterMarkToNormalEle(el){ const self = this let canvas = document.createElement('canvas') canvas.width = el.width ? el.width : el.clientWidth canvas.height = el.height ? el.height : el.clientHeight let ctx = canvas.getContext('2d') let maxSize = Math.max(canvas.height, canvas.width) let font = (maxSize / 25) ctx.font = font + 'px "微软雅黑"' ctx.fillStyle = "rgba(195,195,195,1)" ctx.textAlign = "left" ctx.textBaseline = "top" ctx.save() let angle = -Math.PI / 10.0 //进行平移,计算平移的参数 let translateX = (canvas.height) * Math.tan(Math.abs(angle)) let translateY = (canvas.width - translateX) * Math.tan(Math.abs(angle)) ctx.translate(-translateX / 2.0, translateY / 2.0) ctx.rotate(angle) //起始坐标 let x = 0 let y = 0 //一组文字之间间隔 let sepY = (font / 2.0) while(y < canvas.height){ //当前行的y值 let rowCurrentMaxY = 0 while(x < canvas.width){ let totleMaxX = 0 let currentY = 0 //绘制水印 this.waterTexts.forEach((text,index)=>{ currentY += (index * (sepY + font)) let rect = self.drawWater(ctx,text,x,y + currentY) let currentMaxX = (rect.x + rect.width) totleMaxX = (currentMaxX > totleMaxX) ? currentMaxX: totleMaxX rowCurrentMaxY = currentY }) x = totleMaxX + 20 } //重置x,y值 x = 0 y += (rowCurrentMaxY + (sepY + font + (canvas.height / 5))) } ctx.restore() //添加canvas this.addCanvas(canvas,el) } //绘制水印 drawWater(ctx,text,x,y){ //绘制文字 ctx.fillText(text,x,y) //计算尺度 let textRect = ctx.measureText(text) let width = textRect.width let height = textRect.height return {x,y,width,height} } //添加canvas到当前标签的父标签上 addCanvas(canvas,el){ //创建div(canvas需要依赖一个div进行位置设置) let warterMarDiv = document.createElement('div') //关联水印dom对象 el.warterMark = warterMarDiv //添加样式 this.resetCanvasPosition(el) //添加水印 warterMarDiv.appendChild(canvas) //添加到父标签 el.parentElement.insertBefore(warterMarDiv,el) } //重新计算位置 resetCanvasPosition(el){ if(el.warterMark){ //设置父标签的定位 el.parentElement.style.cssText = `position: relative;` //设施水印载体的定位 el.warterMark.style.cssText = 'position: absolute;top: 0px;left: 0px;pointer-events:none' } } }
Usage
<div> <!-- 待加水印的IMG --> <img style="max-width:90%" src="" alt=""> </div> let waterMark = new WaterMark() waterMark.startWaterMark();
ctx. save() 및 ctx.restore()는 실제로 여기서는 그다지 유용하지 않지만 여전히 추가됩니다. 목적은 워터마크를 추가하기 전에 컨텍스트를 저장하고 그리기를 마친 후에 워터마크 이전의 컨텍스트를 복원하는 것입니다. , 이 이탤릭체 단어는 이 두 코드 줄 사이에만 적용됩니다. 아래에 다른 줄을 그리면 영향을 받지 않습니다.
마스크 워터마크가 기본 버튼이나 기타 이벤트를 차단하는 것을 방지하려면 마스크 라벨에 pointer-events:none 속성을 추가해야 합니다.
워터마크를 추가하려면 라벨 외에 부모 태그를 추가해야 합니다. 이 부모 태그의 기능은 마스크 캔버스의 위치에 제약 조건을 추가하는 것입니다. 여기서는 MutationObserver를 사용하고 싶습니다. body의 변경 사항을 관찰하여 마스크 버전 캔버스를 업데이트하려는 시도는 실패했습니다. 이 콜백에서 복잡한 레이아웃 변경이 트리거되기 때문입니다. 따라서 워터마크가 추가된 라벨 바로 바깥에 부모 태그를 추가해야 하며, 이 부모 태그를 사용하여 마스크 캔버스의 위치를 자동으로 제한해야 합니다.
MutationObserver 로직은 다음과 같습니다. 청취 콜백에서 시간에 맞춰 레이아웃이나 기타 작업을 수정할 수 있습니다(일시적으로 포기).
var MutationObserver = window.MutationObserver || window.webkitMutationObserver || window.MozMutationObserver; var mutationObserver = new MutationObserver(function (mutations) { //修改水印位置 }) mutationObserver.observe(document.getElementsByTagName('body')[0], { childList: true, // 子节点的变动(新增、删除或者更改) attributes: true, // 属性的变动 characterData: true, // 节点内容或节点文本的变动 subtree: true // 是否将观察器应用于该节点的所有后代节点 })
이미지 크기는 로딩이 완료된 후에만 결정될 수 있으므로 IMG 작업을 위해서는 complete 이벤트를 관찰해야 합니다.
3. 요약 및 생각
canvas ctx.drawImage(img, 0, 0)을 사용하여 그린 다음 canvas.toDataURL('image/png')에서 생성된 url을 로드합니다. 이전 사진에서는 그런 방법도 있습니다. 그러나 때로는 사진으로 인해 최종 합성 사진의 base64 데이터가 비어 있기 때문에 마스크를 직접 추가하는 것은 실제 생성이 아닌 표시용일 뿐입니다. 합성 사진. 간단한 의사 워터마크가 구현되었습니다. 특별히 복잡한 코드는 없습니다. 신은 웃으면 안 됩니다. [주먹 쥐기][주먹 쥐기]
추천 학습: "JavaScript 비디오 튜토리얼 "
위 내용은 오버레이 워터마크 효과를 얻기 위해 JS를 사용하는 방법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!