paintbrush.js 5.4 KB

1
  1. import EventEmitter from"./eventEmitter";class Paintbrush extends EventEmitter{constructor(t,{width:e,height:s}={}){super(),this.ctx=t,this.width=e,this.height=s,this.historyData={},this.autoId="",this.resizeFn=[],this.togglePaint.status=!0}drawFromSocket(t,e="page",s=!0){if(!t)return;(t instanceof Array?t:[t]).forEach((t=>{const{type:i,color:a,ID:r,pageId:h,clientWidth:o,clientHeight:n,autoId:c,drawID:l}=t;this.autoId=c,this.pageId=h,this.emit("resize",{clientWidth:o,clientHeight:n});const d=this._getPropObj(t);if(this.setStyle({lineWidth:d.size,strokeStyle:a}),this.drawUseData("text"===i?d:d.points,i),s){const s=`${e}${"whiteBoard"===e?"":this.autoId}${h}`;this.historyData[s]=this.historyData[s]||[],l?this.historyData[s].push(t):this.historyData[s][parseInt(r)]=t}}))}setStyle({lineWidth:t,strokeStyle:e}){t&&(this.ctx.lineWidth=t,this.lineWidth=t),e&&(this.ctx.strokeStyle=e,this.strokeStyle=e)}drawUseData(t,e){if(this.togglePaint.status){switch(e){case"freeline":case"line":this.drawLineUseData(t);break;case"straightLine":this.drawStraightLineUseData(t);break;case"arrowLine":this.drawArrowUseData(t);break;case"rect":this.drawRectUseData(t);break;case"circle":this.drawCircleUseData(t);break;case"circ":case"ellipse":this.drawEllipseUseData(t);break;case"text":this.drawTextUseData(t)}this.ctx.draw(!0)}}drawLineUseData(t){this.ctx.beginPath(),this.ctx.moveTo(t[0].x,t[0].y);const e=t.length;for(let s=1;s<e;s++){const{x:e,y:i}=t[s];this.ctx.lineTo(e,i),this.ctx.stroke(),this.ctx.beginPath(),this.ctx.moveTo(e,i)}}drawStraightLineUseData(t){const[e,s]=t;this.ctx.beginPath(),this.ctx.moveTo(e.x,e.y),this.ctx.lineTo(s.x,s.y),this.ctx.stroke()}drawArrowUseData(t){const[e,s]=t;this.drawArrow({sx:e.x,sy:e.y,ex:s.x,ey:s.y,ctx:this.ctx})}drawArrow({sx:t,sy:e,ex:s,ey:i,ctx:a,arrowAngle:r=45,arrowLen:h=30}){const o=r*Math.PI/180,n=Math.cos(o/2)*h,c=Math.sin(o/2)*h;a.beginPath(),a.fillStyle=this.strokeStyle,a.save(),a.translate(s,i);const l=Math.atan((i-e)/(s-t));let d=l;l>0?i-e<0&&(d=l-Math.PI):i-e>0&&(d=l+Math.PI),a.rotate(d),a.moveTo(-Paintbrush._getDotDistance({x:t,y:e},{x:s,y:i}),0),a.lineTo(-n,-c/2),a.lineTo(-n,-c),a.lineTo(0,0),a.lineTo(-n,c),a.lineTo(-n,c/2),a.fill(),a.closePath(),a.restore()}drawRectUseData(t){const[e,s]=t;this.ctx.strokeRect(e.x,e.y,s.x-e.x,s.y-e.y)}drawCircleUseData(t){const[e,s]=t;this.circle({sx:e.x,sy:e.y,ex:s.x,ey:s.y,ctx:this.ctx})}circle({sx:t,sy:e,ex:s,ey:i,ctx:a}){const r=(s+t)/2,h=(i+e)/2,o=Math.sqrt((s-t)**2+(i-e)**2)/2;a.beginPath(),a.arc(r,h,o,0,2*Math.PI),a.stroke()}drawEllipseUseData(t){const[e,s]=t;this.ellipse({sx:e.x,sy:e.y,ex:s.x,ey:s.y,ctx:this.ctx})}ellipse({sx:t,sy:e,ex:s,ey:i,ctx:a}){const r=(s+t)/2,h=(i+e)/2,o=Math.abs((s-t)/2),n=Math.abs((i-e)/2);a.save(),a.translate(r,h);a.beginPath(),a.moveTo(o,0);for(let t=0;t<2*Math.PI;t+=.05){const e=Math.tan(t);let s=Math.sqrt(o**2*n**2/(n**2+(o*e)**2));t>Math.PI/2&&t<3*Math.PI/2&&(s=-s);const i=e*s;a.lineTo(s,i),a.stroke(),a.beginPath(),a.moveTo(s,i)}a.lineTo(o,0),a.stroke(),a.restore()}drawTextUseData(t){const{content:e,size:s,points:i,color:a}=t;this.ctx.fillStyle=a,this.ctx.font=`${parseInt(s)}px sans-serif`,this.ctx.fillText(e,i[0].x,i[0].y)}setMeasurement({width:t,height:e,pageId:s=0,pageType:i="page",isRedraw:a=!0}){(t||e)&&(isNaN(parseInt(t))||(this.width=t),isNaN(parseInt(e))||(this.height=e),a&&this.redraw(s||0,i))}redraw(t=0,e="page",s){if(!this.togglePaint.status)return;const i=`${e}${"whiteBoard"===e?"":this.autoId}${t}`,a=this.historyData[i];return this.clear(),a?(a.forEach((t=>{(void 0===s||void 0!==s&&void 0!==t.timeStamp&&s>=t.timeStamp)&&this.drawFromSocket(t,e,!1)})),!0):void 0}clear(){this.ctx.clearRect(0,0,this.width,this.height),this.ctx.draw()}clearHistory(t,e,s,i){if(void 0===t)return this.historyData={},this.clear(),this;if(void 0===e)return Object.keys(this.historyData).forEach((t=>{-1!==t.indexOf("page")&&(this.historyData[t]=[])})),this;const a=this._getKey(t,e),r=this.historyData[a];return r?(void 0!==i&&(s=r.findIndex((t=>t.drawID===i))),!isNaN(Number(s))&&s<0||(void 0!==s?r.splice(parseInt(s),1):this.historyData[a]=[]),this):this}delete({pageId:t,ID:e,pageType:s="page",drawID:i}){const a=`${s}${"whiteBoard"===s?"":this.autoId}${t}`,r=this.historyData[a];r&&(i&&(e=r.findIndex((t=>t&&t.drawID===i))),e<0||(r.splice(e,1),this.redraw(t,s)))}_getKey(t,e){const s=0===parseInt(t);return`${s?"whiteBoard":"page"}${s?"":t}${e}`}saveHistory(t,e){const{pageId:s,autoId:i,drawID:a,ID:r}=t,h=this._getKey(i,s);this.historyData[h]=this.historyData[h]||[],a?this.historyData[h].push(Object.assign({userId:e},t)):this.historyData[h][parseInt(r)]=t}togglePaint(t){this.togglePaint.status=t,this.clear(),t&&this.redraw(this.pageId,0===parseInt(this.autoId)?"whiteBoard":"page")}static _getDotDistance(t,e){return Math.sqrt((t.x-e.x)**2+(t.y-e.y)**2)}_getPropObj(t){const{points:e,size:s,clientWidth:i}=t,a=JSON.parse(JSON.stringify(t)),r=this.width/i;return a.size=s*r,a.points=e.map((t=>({x:Math.round(t.x*r),y:Math.round(t.y*r)}))),a}showLaserPaint(t){if(clearInterval(this.showLaserPaint.interval),"close"===t.status&&0===t.points.length)return void this.emit("laserPaint",{status:!1});if(0===t.points.length)return;const{points:e,moveTime:s,status:i}=this._getPropObj(t),a=e.length,r=Math.floor(s/(a-1)),h=({x:t,y:e})=>{this.emit("laserPaint",{status:!0,x:t,y:e})};let o=0;h(e[o]);const n=this.showLaserPaint.interval=setInterval((()=>{if(o++,o>=a)return clearInterval(n),void("close"===i&&this.emit("laserPaint",{status:!1}));Promise.resolve(h(e[o]))}),r)}}export default Paintbrush;