最近做了個播放頁面,標題和一個iframe;需要對這個iframe可以進行網頁塗鴉。
網頁塗鴉肯定是canvas了。網上找了個差不多的,實驗下來問題很多,干脆自己一步步修改,學習。
效果:
本項目沒有引入其他的任何工具庫,復制代碼可以直接運行,下面貼出代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>小小英語-閱讀</title> <meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="format-detection" content="telephone=no"> <meta name="description" content="數千冊優質分級閱讀繪本"> <style> *{ padding:0;margin:0; } li{ list-style-type:none; } html,body{ height:100%; } .content-page{ min-width:1500px; min-height: 100%; background:#f6f6f6; } #page{ position:relative; width:1200px; margin:0 auto; border-top:1px solid rgba(0,0,0,0) } h3{ position: relative; margin:40px 0; color:#ff8e5d; font-size:30px; text-align:center; } .back{ position:absolute; left:0; top:50%; transform:translate(0,-50%); font-family:PingFang-SC-Regular; font-size:20px; padding-left:20px; background:url('../assets/images/icon_back-red.png') no-repeat; background-size:20px 20px; } #content-iframe{ width:100%; background: #ccc; min-height: 800px; border:none; } #canvas{ position:absolute; left:0; top:0; z-index:100; cursor:default; top:120px; left:50%; transform:translate(-50%,0); display: none;/*canvas剛進來是隱藏的,需要選顏色激活*/ } .right-bar{ width:100px; position: absolute; right:-120px; top:120px; color:#000; z-index:1; } .word{ font-size:24px; font-family:FredokaOne-Regular; color:rgba(255,142,93,1); text-align:center; } .right-bar>span{ display: block; width:90px; height:40px; color:#fff; font-size:16px; padding:0; line-height: 40px; border:none; background: #FF8E5D; margin:18px auto; text-align: center; cursor: pointer; } .btn-active{background:#ED723D !important} #color{ padding-left:8px; margin-top:10px; } #color>i{ position:relative; display:inline-block; width:34px; height:34px; border-radius: 50%; margin-right:8px; margin-bottom:5px; border:none; cursor: pointer; z-index:50; } .color-active{ position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); display: block; border: 1px solid #FF8E5D; border-radius: 50%; width:40px; height:40px; z-index:40; display: none; } .i1{ background:#DF4BFF; } .i2{ background:#9CCB68; } .i3{ background:#3DC1FF; } .i4{ background:#FFD338; } .i5{ background:#FF6262; } .i6{ background: #000000; } </style> </head> <body> <div class="content-page"> <div id="page"> <h3> 標題 <p class="back" @click="goBack()"> 返回上一級 </p> </h3> <iframe id="content-iframe" :src="iframeUrl"> </iframe> <div class="right-bar"> <div class="word">color</div> <div id="color"> <i class="i1"><span class="color-active"></span></i> <i class="i2"><span class="color-active"></span></i> <i class="i3"><span class="color-active"></span></i> <i class="i4"><span class="color-active"></span></i> <i class="i5"><span class="color-active"></span></i> <i class="i6"><span class="color-active"></span></i> </div> <span id="eraser">橡皮擦</span> <span id="revocation">撤銷</span> <span id="clear">清除</span> <span id="hide" class="btn-active">關閉</span> </div> </div> <canvas id="canvas" width="740" height="420">您的<u>瀏覽器</u>不支持 canvas 標簽</canvas> </div> <script type="text/javascript"> var paint={ load:function(){ this.x=[];//記錄鼠標移動是的X坐標 this.y=[];//記錄鼠標移動是的Y坐標 this.clickDrag=[]; this.lock=false;//鼠標移動前,判斷鼠標是否按下 this.isEraser=false; this.storageColor="#f00"; this.eraserRadius=15;//擦除半徑值 this.color=["#DF4BFF","#9CCB68","#3DC1FF","#FFD338","#FF6262","#000000"];//畫筆顏色 this.$=function(id){return typeof id=="string"?document.getElementById(id):id;}; this.canvas=this.$("canvas"); this.canvas.width=this.$('content-iframe').offsetWidth;//設定canvas的寬度 this.canvas.height=this.$('content-iframe').offsetHeight;//設定canvas的高度 if (!this.canvas.getContext) { alert("您的瀏覽器不支持 canvas 標簽"); return; } this.cxt=this.canvas.getContext('2d'); this.cxt.lineJoin = "round";//context.lineJoin - 指定兩條線段的連接方式 this.cxt.lineWidth = 5;//線條的寬度 this.iptClear=this.$("clear"); this.revocation=this.$("revocation"); this.hide = this.$('hide'); this.eraser = this.$('eraser'); this.colorSpan = this.$('color').getElementsByTagName('span');//顏色的外框的span集合 this.imgArr = [];//保存每個狀態,撤銷的時候用到 this.touch =("createTouch" in document);//判定是否為手持設備 this.StartEvent = this.touch ? "touchstart" : "mousedown";//支持觸摸式使用相應的事件替代 this.MoveEvent = this.touch ? "touchmove" : "mousemove"; this.EndEvent = this.touch ? "touchend" : "mouseup"; this.bind(); }, bind:function(){ var t=this; this.hide.onclick = function(){ t.canvas.style.display = 'none'; t.eraser.className = ""; t.hide.className = 'btn-active' t.hideColorSpan(); } /*清除畫布*/ this.iptClear.onclick=function(){ t.cxt.clearRect(0, 0, t.canvas.width, t.canvas.height-1); }; /*鼠標按下事件,記錄鼠標位置,並繪制,解鎖lock,打開mousemove事件*/ this.canvas['on'+t.StartEvent]=function(e){ // debugger; t.imgArr.push(t.cxt.getImageData(0, 0,t.canvas.width,t.canvas.height)); var touch=t.touch ? e.touches[0] : e; var box = t.canvas.getBoundingClientRect(); var _x = (touch.clientX - box.left) * t.canvas.width / box.width var _y = (touch.clientY - box.top) * t.canvas.height / box.height if(t.isEraser){ t.resetEraser(_x,_y,touch); }else{ t.movePoint(_x,_y);//記錄鼠標位置 t.drawPoint();//繪制路線 } t.lock=true; }; /*鼠標移動事件*/ this.canvas['on'+t.MoveEvent]=function(e){ // console.log(t.touch); var touch=t.touch ? e.touches[0] : e; //var touch = e; if(t.lock){ var touch=t.touch ? e.touches[0] : e; var box = t.canvas.getBoundingClientRect(); var _x = (touch.clientX - box.left) * t.canvas.width / box.width var _y = (touch.clientY - box.top) * t.canvas.height / box.height if(t.isEraser){ t.resetEraser(_x,_y,touch); } else{ t.movePoint(_x,_y,true);//記錄鼠標位置 t.drawPoint();//繪制路線 } } }; this.canvas['on'+t.EndEvent]=function(e){ /*重置數據*/ t.lock=false; t.x=[]; t.y=[]; t.clickDrag=[]; clearInterval(t.Timer); t.Timer=null; }; this.revocation.onclick=function(){ if(t.imgArr.length>0){ t.cxt.putImageData(t.imgArr[t.imgArr.length-1], 0, 0); t.imgArr.pop(); } }; this.changeColor(); /*橡皮擦*/ this.$("eraser").onclick=function(e){ if(t.hide.className ===''){ t.hideColorSpan();//這里是 t.isEraser=true; t.eraser.className = 'btn-active'; } }; }, movePoint:function(x,y,dragging){ // debugger; /*將鼠標坐標添加到各自對應的數組里*/ this.x.push(x); this.y.push(y); this.clickDrag.push(y); }, drawPoint:function(x,y,radius){ for(var i=0; i < this.x.length; i++){ this.cxt.beginPath();//context.beginPath() , 准備繪制一條路徑 if(this.clickDrag[i] && i){//當是拖動而且i!=0時,從上一個點開始畫線。 this.cxt.moveTo(this.x[i-1], this.y[i-1]);//context.moveTo(x, y) , 新開一個路徑,並指定路徑的起點 }else{ this.cxt.moveTo(this.x[i]-1, this.y[i]); } this.cxt.lineTo(this.x[i], this.y[i]);//context.lineTo(x, y) , 將當前點與指定的點用一條筆直的路徑連接起來 this.cxt.closePath();//context.closePath() , 如果當前路徑是打開的則關閉它 this.cxt.stroke();//context.stroke() , 繪制當前路徑 } }, preventDefault:function(e){ /*阻止默認*/ var touch=this.touch ? e.touches[0] : e; if(this.touch)touch.preventDefault(); else window.event.returnValue = false; }, changeColor:function(){ /*為按鈕添加事件*/ var t=this,iptNum=this.$("color").getElementsByTagName("i"); for(let i=0,l=iptNum.length;i<l;i++){//這里要么用let,要么用閉包 iptNum[i].index=i; iptNum[i].onclick=function(){ t.hideColorSpan();//隱藏所有顏色的選中 t.colorSpan[i].style.display = 'block'//選中點擊的顏色 t.canvas.style.display = 'block'; // debugger; t.cxt.save(); t.cxt.strokeStyle = t.color[this.index]; t.storageColor=t.color[this.index]; t.$("hide").className = ''; t.$("eraser").className = '';//清除橡皮擦選中狀態 t.cxt.strokeStyle = t.storageColor; t.isEraser=false; } } }, resetEraser:function(_x,_y,touch){ var t=this; //this.cxt.lineWidth = 30; /*source-over 默認,相交部分由后繪制圖形的填充(顏色,漸變,紋理)覆蓋,全部瀏覽器通過*/ t.cxt.globalCompositeOperation = "destination-out"; t.cxt.beginPath(); t.cxt.arc(_x, _y, t.eraserRadius, 0, Math.PI * 2); t.cxt.strokeStyle = "rgba(250,250,250,0)"; t.cxt.fill(); t.cxt.globalCompositeOperation = "source-over" }, hideColorSpan:function(){//隱藏顏色的選中狀態 for(var i =0,length = this.colorSpan.length;i<length;i++){ this.colorSpan[i].style.display = 'none' } } }; paint.load(); </script> </body> </html>