canvas实现你画我猜(入门级别)
初学canvas做的一个小功能,大佬勿喷
之前一直没有去了解canvas 最近玩steam你画我猜感觉很有意思 就打算自己实现一个单机版的
成果图:
预备工作: vs code,及几张图片


因为考虑到体积问题没有用上jquery 先说一下这次使用到的基本的几个canvas方法
moveTo绘制心线条起点
lineTo绘制线条的末尾
stroke绘制线条结束
clearRect 清除一个正方形出来
fillRect 填充一个正方形
beginPath 重新绘制一条新的线条
beginPath这个方法比较关键 同一条线条的情况下换颜色,所有线条都变颜色了,回放自己画图时候也会出问题
canvas中文文档:www.canvasapi.cn/CanvasRende…
Hmtl部分
      <img src="./huabu.jpg"  id="scream" class="img" >
      <canvas class="canvas"  id="canvas" width="800" height="800"></canvas>
    </div>
    <div class="function">
      <div></div>
      <div>
        <button onclick="start()">清除绘制</button>
      </div>
      <div>
        <button onclick="reset()">回放绘制</button>
      </div>
      <div>
        <input type="radio" name="mode" id="canvasMode" onChange="modeChange(1)"> <label for="canvasMode">画布模式</label>
        <input type="radio" name="mode" id="backgroundMode" onChange="modeChange(2)"> <label for="backgroundMode">背景颜色模式</label>
      </div>
      <div class="button">
        <input type="color" id="color"> 背景颜色
      </div>
      <div class="button">
        <input type="color" id="fontColor"> 画笔颜色
      </div>
      <div class="button lineWidth">
        <input type="range" value="1" min="1" id="fontWidth"><span style="margin-left:12px;width:95px">画笔粗细:</span>
        <div class="widthPercentage" id="percentage">
        </div>
        <div  class="button">
          <span id="lineNum">1</span>
        </div>
      </div>
      <div class="button lineWidth">
        <input type="range" value="15" min="1" id="rubberWidth"><span style="margin-left:12px;width:95px">橡皮大小:</span>
        <div  class="button">
          <span id="rubberNum">15</span>
        </div>
      </div>
      <div>
      <button onclick="eraserClick()" id='eraser'>橡皮擦 </button>
      </div>
    </div>
  </div>
css部分
  body {
    margin: 0;
  }
  .canvasBox {
    display: flex;
  }
  button,.button {
    margin: 12px;
  }
  .function {
    margin: auto 0;
  }
  .lineWidth {
    position: relative;
    display: flex;
    align-items: center;
  }
  .widthPercentage{
    position: absolute;
    top: 34px;
    left: 30%;
    height: 20px;
    border: 1px dashed #aaa;
    display: none;
    padding: 4px;
  }
  .img {
    top: 0;
    left: 0;
    width: 800px;
    height: 800px;
    position: absolute;
    pointer-events: none;
    z-index: -1;
  }
  .imgbox{
    width: auto;
    position: relative;
  }
  .canvas {
    cursor: url('./brush.ico'), auto;
    opacity: 1;
  }
</style>
js部分
  let record = []
  let bkgColor = document.getElementById('color')
  let eraser = document.getElementById('eraser')
  let img = document.getElementById("scream");
  let fontWidth = document.getElementById('fontWidth')
  let rubberWidth = document.getElementById('rubberWidth')
  let lineNum = document.getElementById('lineNum')
  let rubberNum = document.getElementById('rubberNum')
  let fontColor = document.getElementById('fontColor')
  let canvas = document.getElementById('canvas')
  let percentage = document.getElementById('percentage')
  let  body = document.document || document.body
  let clientX,clientY,c,lineWidth,rubberSize,eraserFlag,mode=1,color
  let flag,fColor='#000'
  c = canvas.getContext('2d')
  init()
  modeChange = function(e) {
    mode = e
    init({color})
    resetHui(false)
  }
  eraser.onclick = function() { // 橡皮擦点击事件
    eraserFlag = !eraserFlag
    if(eraserFlag) {
      eraser.innerText='画笔'
      canvas.style.cursor = "url('./xp1.ico'), auto"
    } else {
      eraser.innerText='橡皮擦'
      canvas.style.cursor = "url('./brush.ico'), auto"
      c.strokeStyle = fColor
    }
    c.beginPath();
  }
  bkgColor.onchange = function(e) { // 背景颜色
    color = e.target.value
    init({color})
    resetHui(false)
  }
  fontColor.onchange = function(e) { // 画笔颜色
    fColor = e.target.value
    c.beginPath();
    c.strokeStyle = fColor
  }
  fontWidth.onchange = function(e) { // 画笔粗细 选择之后
    lineWidth = e.target.value
    c.beginPath();
    c.lineWidth = lineWidth
  }
  rubberWidth.onmousemove = function(e) { // 橡皮大小 移动滑块
    rubberSize = e.target.value
    percentage.innerText = rubberSize+' %'
    rubberNum.innerText = rubberSize
  }
  fontWidth.onmousemove = function(e) { // 画笔粗细 移动滑块
    lineWidth = e.target.value
    percentage.style.display = 'block'
    percentage.innerText = lineWidth+' %'
    lineNum.innerText = lineWidth
  }
  fontWidth.onmouseleave = function(e) { // 画笔粗细 移除滑块
    lineWidth = e.target.value
    percentage.style.display = 'none'
  }
  canvas.onmouseenter = function(e) {
    if(!eraserFlag) return
    // canvas.style.cursor = 'none'
  }
  canvas.onmousedown = function(e) { // 鼠标按下开始画图
    flag = true
    if(!eraserFlag) {
      c.moveTo(e.clientX,e.clientY)
    }
    // console.log(e.clientX,e.clientY,'开始');
    canvas.onmousemove = function(event) { //鼠标按下移动画图
      if(!flag) return
      clientX = event.clientX;
      clientY = event.clientY
      if(!eraserFlag) {
        c.lineTo(clientX,clientY)
        c.stroke();
        // console.log(clientX,clientY,'结束');
        // console.log(e.clientX,e.clientY,clientX, clientY, '重回');
        record.push({
          start: [e.clientX,e.clientY],
          end: [clientX, clientY],
          strokeStyle: fColor,
          lineWidth: lineWidth
        })
      }else {
        if(mode===1) {
          c.clearRect(clientX, clientY, rubberSize, rubberSize);
        } else {
          c.strokeStyle = color
          c.fillRect(clientX,clientY,rubberSize,rubberSize);
        }
        
      }
    }
  }
  canvas.onmouseup = function() { // 鼠标松开 结束画图
    flag = false
    c.stroke();
    // console.log(record);
  }
  function start(){
    record = []
    init()
    lineNum.innerText = 0
    fontWidth.value = 0
  }
  function reset(){
    init()
    resetHui()
  }
  async function resetHui(needDelay = true) {
    let old = []
    let strokeStyle,setLineWidth
    for(let i=0; i<record.length;i++) {
      let item = record[i]
      if(!old || (old[0] !== item.start[0] && old[1] !== item.start[1])) {
        old[0] = item.start[0]
        old[1] = item.start[1]
        c.beginPath();
        if(!strokeStyle || (strokeStyle !== item.strokeStyle)){
          strokeStyle = item.strokeStyle
          c.strokeStyle = strokeStyle
        }
        if(!setLineWidth || (setLineWidth !== item.lineWidth)) {
          setLineWidth = item.lineWidth
          c.lineWidth = setLineWidth
        }
        c.moveTo(item.start[0],item.start[1])
      }
      c.lineTo(item.end[0],item.end[1])
      c.stroke();
      needDelay && await delay()
    }
  }
  function delay(time = 10) {
    return new Promise((res,rej)=>{
      setTimeout(function(){
        res('随便什么数据');
      }, time);
    })
  }
  function init({color='#fff'}={}) {
    canvas.width = canvas.width
    c.strokeStyle = fontColor // 线条颜色
    c.rect(0,0,800,800); // 矩形
    c.stroke(); // 线条结束
    if (mode===1) { // 模式1为画布模式
      c.fillStyle = 'rgba(255, 255, 255, 0)'
    } else {
      c.fillStyle = color; // 填充颜色 背景色
    }
    c.fillRect(0,0,800,800); // 填充矩形
    c.stroke(); // 线条结束
    c.strokeStyle = '#000' // 线条颜色
    c.lineWidth = 1 // 线条粗细
    c.lineCap = 'square'; // 线条头部形状 扁平 凸起 凹进
  }
</script>
第一步: 实现你画我猜画布功能
很简单通过canvas标签和img图片放在div里,img图片和父元素position的定位,然后canvas填充背景色为透明,这样我们就可以获得一个画布背景图了
具体的步骤:

(虽然图片在canvas下方但是为了以防万一我还是加了pointer-events: none;防止图片被点击)

let canvas = document.getElementById('canvas')
  c = canvas.getContext('2d')  // 创建一个2d的canvas画布
  canvas.width = canvas.width // 重新赋值一遍宽度 可以刷新画布
  c.strokeStyle='#000' // 线条颜色
  c.rect(0,0,800,800); // 绘制矩形
  c.fillStyle = 'rgba(255, 255, 255, 0)' // 填充颜色为透明
  c.fillRect(0,0,800,800); // 填充颜色大小
  c.stroke(); // 线条结束
这样就可以获得一个这样的图片了,现在我们canvas的线条就可以在这个背景上为所欲为了

第二步:开始画画
给canvas加上鼠标点击时候的事件并且再触发鼠标移动的事件,并且通过一个数组记录鼠标的坐标信息(record),通过一个状态记录鼠标是否松开(flag),如果松开了鼠标移动事件就不再执行,通过一个状态来控制是橡皮擦还是画笔(eraserFlag),通过一个状态来控制展示的是背景图还是背景颜色(mode)
record的目的 是回放我们刚刚画的图感觉就像动画一样重新画图
flag的目的 实现点击并且移动才能画画 松开的时候清除
eraserFlag目的 实现橡皮擦和画笔的切换


回放画图过程

常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
 - 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
 
- 提示下载完但解压或打开不了?
 
- 找不到素材资源介绍文章里的示例图片?
 
- 模板不会安装或需要功能定制以及二次开发?
 
                    
    
发表评论
还没有评论,快来抢沙发吧!