<template>
  <div class="drawing-board-wrap"
  :style="{
    'pointer-events':model==='mouse'?'none':'auto',
  }" >
  <!-- 画布 -->
    <canvas id="paint" ref="canvasRef"
      :style="{
        width:canvasWidth+'px',
        height:canvasHeight+'px',
      }" 
      @mousedown.stop="startDraw"
      @mousemove="(e)=>{mouse.x=e.clientX;mouse.y=e.clientY}"
    />
    <!-- 工具栏 -->
    <!-- 鼠标跟随-画笔和橡皮擦图标 -->
    <div class="pen"
      :style="{
        left: mouse.x - 3+ 'px',
        top: mouse.y - 22 + 3 + 'px',
        color: choosedColor,
      }"
      v-if="model==='paint'&&activeTool === 'brush'"
    ><img src="~@/assets/icons/brush.svg" :style="brushStyle({iconName:'brush'})"></div>
    
    <div 
      class="eraser"
      :style="{
        left: mouse.x - 18 + 'px',
        top: mouse.y - 18 + 'px',
        width: 36 + 'px',
        height: 36 + 'px',
      }"
      v-if="model==='paint'&&activeTool === 'eraser'"
    ></div>
  </div>
</template>

<script>
import {boardTool,colorList} from '../utils/config.js';
export default {
  components:{},
  props:{
    model:{
      type:String,
      default:'mouse'
    },
    pageList:{}
  },
  data() {
    return {
      ctx:null,//canvas上下文
      canvasWidth:0,//canvas宽
      canvasHeight:0,//canvas高
      toolEl:{left:5,top:5},//画笔工具栏位置
      paletteEl:{left:-235,top:77},//画笔工具-颜色选择器位置
      mouse:{x:0,y:0},//鼠标坐标
      isMouseDown:false,//画笔工具栏移动标识
      toolList:boardTool,//画笔工具栏
      colorList:colorList,//画笔工具栏-颜色选择
      activeTool:'brush',//选中的画笔工具
      isPalettleShow:false,//是否显示颜色选择
      choosedColor:'#000000',//画笔颜色
      movePoint:{},//画笔坐标
      isStartDraw:false,//是否在绘图中
      hasPainted:false,//当前画布是否有笔迹
      isMoved:false,//画笔是否移动过
    };
  },
  computed:{
    brushStyle(){
      return function(tool){
        if(tool.iconName==='brush'){
          return {'transform': 'translateX(44px)','filter':`drop-shadow(${this.choosedColor} -44px 0px 0px)`}
        }else if(tool.iconName==='palette'){
          return {'transform': 'translateX(44px)','filter':`drop-shadow(#000000 -44px 0px 0px)`}
        }else{
          return {'transform': 'translateX(44px)','filter':`drop-shadow(${this.hasPainted?'#000000':'#b5b5b5'} -44px 0px 0px)`}
        }
      }
    }
  },
  methods: {
    //初始化画布及工具栏
    initCanvas(){
      this.ctx = this.$refs.canvasRef.getContext('2d',{willReadFrequently: true})
      this.canvasWidth = window.screen.width
      this.canvasHeight = window.screen.height
      this.toolEl.left = window.screen.width-56-5
      //设置canvas宽高
      this.$refs.canvasRef.width=this.canvasWidth
      this.$refs.canvasRef.height=this.canvasHeight
      if(!this.ctx) return
      this.ctx.lineCap = 'round'
      this.ctx.lineJoin = 'round'
      this.ctx.lineWidth = 6
      this.ctx.strokeStyle = this.choosedColor    
    },
    //移动画布工具栏
    handleMoveStart(event){
      this.isMouseDown = true
      this.isStartDraw = false
      let startX = event.clientX
      let startY = event.clientY
      document.onmousemove=(e)=>{
        if(!this.isMouseDown) return 
        if(this.isPalettleShow) this.isPalettleShow = false
        let moveX = e.clientX - startX
        let moveY = e.clientY - startY
        const {left,top} = this.toolEl
        const toolWidth = 56
        const toolHeight = 242
        //移动边界：不超过屏幕
        this.toolEl.left = Math.min(Math.max(left+moveX,5),this.canvasWidth-toolWidth-5)
        this.toolEl.top = Math.min(Math.max(top+moveY,5),this.canvasHeight-toolHeight-5)
        //toolEl的位置决定了paletteEl的位置
        if(this.toolEl.left+220>this.canvasWidth-toolWidth){
          this.paletteEl.left=-235
        }else{
          this.paletteEl.left=57
        }
        startX = e.clientX
        startY = e.clientY
      }
      document.onmouseup = ()=>{
        this.isMouseDown = false
        document.onmousemove = null
        document.onmouseup = null
      }
    },
    //选择画布工具
    chooseBoardTool(tool){
      //在没有笔迹时,点击这两个按钮不生效
      if(['broom','eraser'].includes(tool)&&!this.hasPainted){
        return
      }
      if(tool==='palette') return
      this.activeTool = tool
      if(tool==='broom'){
        this.hasPainted&&this.clearCanvas()
        //区分清除画布的触发方式,如果是点击画布工具触发则需要将画布页面数据也一起清除
        this.$emit('salfClear')
        this.activeTool = 'brush'
      }
    },
    //是否显示颜色选择器
    checkPalettle(hoverTool,type){
      if(type==='enter'&&hoverTool!=='palette'){
        this.isPalettleShow = false
      }
      if(type==='enter'&&hoverTool==='palette'){
        this.isPalettleShow = true
      }
    },
    //点击调色盘-切换画笔颜色
    changeBrushColor(color){
      if(!this.ctx) return
      this.ctx.strokeStyle = color
      this.choosedColor = color
      this.isPalettleShow = false
      this.activeTool = 'brush'
    },
    //清空画布
    clearCanvas(){
      if (!this.ctx) return
      this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
      this.hasPainted = false
    },
    //保存画布
    saveCanvas(){
      if(!this.ctx) return 
      return this.ctx.getImageData(0,0,this.canvasWidth,this.canvasHeight)
    },
    //重新绘制画布
    reDrawCanvas(imgData){
      if(!this.ctx) return
      this.ctx.putImageData(imgData,0,0)
    },
    //canvas绘制相关
    startDraw(e){
      //console.log('click',e)
      this.isStartDraw = true
      this.isMouseDown = false
      this.movePoint.startX = e.clientX
      this.movePoint.startY = e.clientY
      this.mouse.x = e.clientX
      this.mouse.y = e.clientY
      document.onmousemove = (event)=>{
        this.moveBrush(event)
      }
      document.onmouseup = (e)=>{
        this.endDraw(e)
      }
    },
    endDraw(e){
      this.isStartDraw = false
      //如果没有移动过，只是鼠标按下抬起，则在按下的地方绘制/擦除
      if(!this.isMoved&&e.which===1){
        this.movePoint.endX = this.movePoint.startX
        this.movePoint.endY = this.movePoint.startY
        this.activeTool==='brush'&&this.draw()
        this.activeTool==='eraser'&&this.erase()
      }
      this.isMoved = false
      if(this.isCanvasEmpty()){
        this.chooseBoardTool('broom')
      }
      document.onmousemove = null
      document.onmouseup = null
    },
    moveBrush(e){
      if(!this.isStartDraw) return
      this.movePoint.endX = e.clientX
      this.movePoint.endY = e.clientY
      this.activeTool==='brush'&&e.which===1&&this.draw()
      this.activeTool==='eraser'&&e.which===1&&this.erase()
      this.movePoint.startX = e.clientX
      this.movePoint.startY = e.clientY
      if(!this.isMoved) this.isMoved = true
    },
    //绘制笔迹
    draw(){
      if(!this.ctx) return
      const {startX,startY,endX,endY} = this.movePoint
      this.ctx.beginPath()
      this.ctx.moveTo(startX,startY)
      this.ctx.lineTo(endX,endY)
      this.ctx.stroke()
      this.ctx.closePath()
      this.hasPainted = true
    },
    //擦除笔迹
    erase(){
      if(!this.ctx) return
      const {startX,startY,endX,endY} = this.movePoint
      const radius = 18 //橡皮擦半径
      //让橡皮擦笔迹平滑 参考https://github.com/pipipi-pikachu/PPTist/src/components/WritingBoard.vue
      const sinRadius = radius * Math.sin(Math.atan((endY - startY) / (endX - startX)))
      const cosRadius = radius * Math.cos(Math.atan((endY - startY) / (endX - startX)))
      const rectPoint1 = [startX + sinRadius, startY - cosRadius]
      const rectPoint2 = [startX - sinRadius, startY + cosRadius]
      const rectPoint3 = [endX + sinRadius, endY - cosRadius]
      const rectPoint4 = [endX - sinRadius, endY + cosRadius]

      this.ctx.save() //保存画布区域
      this.ctx.beginPath()
      this.ctx.arc(endX, endY, radius, 0, Math.PI * 2)
      this.ctx.clip()
      this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
      this.ctx.restore() //恢复画布区域，clip的部分

      //修正橡皮擦的笔迹
      this.ctx.save()
      this.ctx.beginPath()
      this.ctx.moveTo(...rectPoint1)
      this.ctx.lineTo(...rectPoint3)
      this.ctx.lineTo(...rectPoint4)
      this.ctx.lineTo(...rectPoint2)
      this.ctx.closePath()
      this.ctx.clip()
      this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
      this.ctx.restore()
    },
    isCanvasEmpty(){
      const blank  = document.createElement('canvas')
      blank.width = this.canvasWidth
      blank.height = this.canvasHeight
      return this.$refs.canvasRef.toDataURL() == blank.toDataURL()
    }
  },
  mounted(){
    this.initCanvas()
  }
};
</script>


<style scoped lang="scss">
.drawing-board-wrap{
  position: absolute;
  left:0;
  right:0;
  top:0;
  bottom:0;
  z-index: 999;
 /*  background-color: pink; */
  canvas{
    position: absolute;
    left:0;
    top:0;
    cursor: none;
  }
  .tools{
    position:absolute;
    border: 1px solid #999999;
    background-color: white;
    width:56px;
    height:242px;
    padding:8px;
    border-radius: 8px;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    .move-area{
      position:absolute;
      top:0;
      left:0;
      right:0;
      height:8px;
      cursor:move;
      .move-line{
        width:23px;
        height:2px;
        background-color: #333333;
        cursor:move;
      }
    }
    .tool-item{
      width:40px;
      height:40px;
      cursor: pointer;
      position:relative;
      overflow: hidden;
      img{
        display: block;
        width: 22px;
        height: 22px;
      }
      &:hover,&.active{
        background-color: #E9F4FF;
      }
    }
    .color-box{
        position:absolute;
        width:230px;
        height:30px;
        background-color: white;
        border:1px solid #999999;
        padding:5px;
        border-radius: 2px;
        display: flex;
        justify-content: space-around;
        .color-item{
          display: inline-block;
          width:17px;
          height: 17px;
          border: 1px solid #DCDFE6;
        }
      }
  }
  .pen,.eraser{
    position:absolute;
    pointer-events: none;
    z-index: 3;
    overflow: hidden;
    user-select: none;
    img{
      display: block;
      width: 22px;
      height: 22px;
    }
  }
  .eraser {
    display: flex;
    justify-content: center;
    align-items: center;
    border-radius: 50%;
    border: 4px solid rgba(85, 85, 85, 0.685);
  }
}
</style>
