【问题标题】:HTML5 Canvas How To Fill A Mouse Drawn TriangleHTML5 Canvas 如何填充鼠标绘制的三角形
【发布时间】:2021-10-31 20:19:33
【问题描述】:

我正在尝试在通过拖动鼠标绘制的 HTML5 画布上填充三角形。

我对圆形、矩形也有类似的效果。

显示工作 drawCircle 和不工作 drawTriangle 函数的代码如下。绘制了三角形的轮廓,但未填充。我试过爱context.stroke线到各个地方的顺序没有效果。

<style>
#divContainer {
    width: 100%;
    height: 80%;
    background: #ddd;
}

#divContentArea {
    left: 0px;
    top: 0px;
    right: 0px;
    bottom: 0px;
}


.canvas {
   cursor: crosshair;
   position:relative;
   left:0px;
   top:0px;
}

</style>

   <div>
      Click the button to select the shape type then click and drag mouse on the canvas below.
      <BR>
      
      <button type="button" onClick='shapetype="circle";'>Draw Circle</button>
      <button type="button" onClick='shapetype="triangle";'>Draw Triangle</button>
      <BR>

   </div>
   
<div id="divContainer">
   
   <div id="divContentArea">

            <canvas id="canvas" class='canvas'>
            Sorry, your browser does not support a canvas object.
            </canvas>

   </div>

</div>

<script>
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

var canrect = canvas.getBoundingClientRect();

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

var lastPoint;
var startPoint;

var isDrawing = false;

var shapetype = 'triangle';

canvas.onmousedown = function(e) {

   isDrawing = true;   
   if ( shapetype == 'circle' ) {
      canvas.removeEventListener("mousemove", drawTriangle, false);
      canvas.addEventListener("mousemove", drawCircle, false);
   } else {
      canvas.removeEventListener("mousemove", drawCircle, false);
      canvas.addEventListener("mousemove", drawTriangle, false);
   }
      
   lastPoint = { x: e.offsetX, y: e.offsetY };
   startPoint = lastPoint;      
};

function drawTriangle(e) {

   // This doesn't work - triangle is not filled
   
   e.preventDefault();
   e.stopPropagation();

   if (!isDrawing) return;

   mx = e.offsetX;
   my = e.offsetY;

   // clear the canvas
   context.clearRect(0, 0, canvas.width, canvas.height);

   // calculate the rectangle width/height based
   // on starting vs current mouse position
   var twidth = Math.abs(mx - startPoint.x) ;
   var theight = Math.abs(my - startPoint.y) ;

   // draw a new rect from the start position 
   // to the current mouse position
   context.beginPath();
   context.lineWidth = 3;
   context.lineJoin = context.lineCap = 'round';
   context.setLineDash([0, 0]);
   context.globalAlpha = 1.0;


   if ( mx >= startPoint.x ) {
      context.moveTo(startPoint.x, startPoint.y );
      context.lineTo(mx, my);
      context.moveTo(mx-(2*twidth), my );
      context.lineTo(mx, my);
      context.moveTo(startPoint.x, startPoint.y );
      context.lineTo(mx-(2*twidth), my );
   } else {
      context.moveTo(startPoint.x, startPoint.y );
      context.lineTo(mx, my);
      context.moveTo(mx+(2*twidth), my );
      context.lineTo(mx, my);
      context.moveTo(startPoint.x, startPoint.y );
      context.lineTo(mx+(2*twidth), my );
   }

   context.closePath();
   context.strokeStyle = 'red';
   context.stroke();
   context.fillStyle = 'rgba(25,50,75,0.5)';
   context.fill();

}

function drawCircle(e) {

   // This works

   e.preventDefault();
   e.stopPropagation();

   if (!isDrawing) return;

   mx = e.offsetX;
   my = e.offsetY;

   // clear the canvas
   context.clearRect(0, 0, canvas.width, canvas.height);

   // calculate the rectangle width/height based
   // on starting vs current mouse position
   var cradius = Math.abs(mx - startPoint.x) ;

   // draw a new rect from the start position 
   // to the current mouse position
   context.beginPath();
   context.lineWidth = 3;
   context.lineJoin = context.lineCap = 'round';
   context.setLineDash([0, 0]);
   context.globalAlpha = 1.0;

   context.strokeStyle = 'red';
   context.arc(startPoint.x, startPoint.y, cradius, 0, 2 * Math.PI, false);

   context.fillStyle = 'rgba(25,50,75,0.5)';
   context.fill();
   context.stroke();


}

canvas.onmouseup = function() {
   isDrawing = false;
};

canvas.onmouseleave = function() {
   isDrawing = false;
};

</script>

【问题讨论】:

    标签: html5-canvas fill onmousemove


    【解决方案1】:
        function drawTriangle(e) {
            e.preventDefault();
            e.stopPropagation();
    
            if (!isDrawing) return;
            
            // clear the canvas
            context.clearRect(0, 0, canvas.width, canvas.height);
    
            // draw a new rect from the start position
            // to the current mouse position
            context.strokeStyle = 'red';
            context.fillStyle = 'rgba(25,50,75,0.5)';
            context.lineWidth = 3;
            context.lineJoin = context.lineCap = 'round';
            context.setLineDash([0, 0]);
            context.globalAlpha = 1.0;
            context.beginPath();
    
    
            context.moveTo(startPoint.x, startPoint.y);
            context.lineTo(e.offsetX, e.offsetY);
            context.lineTo(startPoint.x * 2 - e.offsetX, e.offsetY);
            context.closePath();
            context.stroke();
            context.fill();
    
        }
    

    【讨论】:

    • 谢谢。所以问题是额外的moveTo 我打破了路径,所以没有封闭的路径可以填充。
    【解决方案2】:

    CanvasRenderingContext2D 的fill() 方法用给定的颜色填充路径。为了能够填充这样的路径,它必须至少包含三个点 - 这在您的情况下已满足。

    问题在于您创建路径的方式:

      context.moveTo(startPoint.x, startPoint.y );
      context.lineTo(mx, my);
      context.moveTo(mx-(2*twidth), my );
      context.lineTo(mx, my);
      context.moveTo(startPoint.x, startPoint.y );
      context.lineTo(mx-(2*twidth), my );
    

    通过再次调用moveTo(),您实际上是在开始一条新路径 - 因此您只有三行单行,因此无需填写任何内容。

    尝试一次完成路径:

      context.moveTo(startPoint.x, startPoint.y );
      context.lineTo(mx, my);
      context.lineTo(mx-(2*twidth), my );
    

    var canvas = document.getElementById('canvas');
    var context = canvas.getContext('2d');
    
    var canrect = canvas.getBoundingClientRect();
    
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    
    var lastPoint;
    var startPoint;
    
    var isDrawing = false;
    
    var shapetype = 'triangle';
    
    canvas.onmousedown = function(e) {
    
      isDrawing = true;
      if (shapetype == 'circle') {
        canvas.removeEventListener("mousemove", drawTriangle, false);
        canvas.addEventListener("mousemove", drawCircle, false);
      } else {
        canvas.removeEventListener("mousemove", drawCircle, false);
        canvas.addEventListener("mousemove", drawTriangle, false);
      }
    
      lastPoint = {
        x: e.offsetX,
        y: e.offsetY
      };
      startPoint = lastPoint;
    };
    
    function drawTriangle(e) {
    
      // This doesn't work - triangle is not filled
    
      e.preventDefault();
      e.stopPropagation();
    
      if (!isDrawing) return;
    
      mx = e.offsetX;
      my = e.offsetY;
    
      // clear the canvas
      context.clearRect(0, 0, canvas.width, canvas.height);
    
      // calculate the rectangle width/height based
      // on starting vs current mouse position
      var twidth = Math.abs(mx - startPoint.x);
      var theight = Math.abs(my - startPoint.y);
    
      // draw a new rect from the start position 
      // to the current mouse position
      context.beginPath();
      context.lineWidth = 3;
      context.lineJoin = context.lineCap = 'round';
      context.setLineDash([0, 0]);
      context.globalAlpha = 1.0;
    
    
      if (mx >= startPoint.x) {
        context.moveTo(startPoint.x, startPoint.y);
        context.lineTo(mx, my);
        context.lineTo(mx - (2 * twidth), my);
    
      } else {
        context.moveTo(startPoint.x, startPoint.y);
        context.lineTo(mx, my);
        context.lineTo(mx + (2 * twidth), my);
      }
    
      context.closePath();
      context.strokeStyle = 'red';
      context.stroke();
      context.fillStyle = 'rgba(25,50,75,0.5)';
      context.fill();
    
    }
    
    function drawCircle(e) {
    
      // This works
    
      e.preventDefault();
      e.stopPropagation();
    
      if (!isDrawing) return;
    
      mx = e.offsetX;
      my = e.offsetY;
    
      // clear the canvas
      context.clearRect(0, 0, canvas.width, canvas.height);
    
      // calculate the rectangle width/height based
      // on starting vs current mouse position
      var cradius = Math.abs(mx - startPoint.x);
    
      // draw a new rect from the start position 
      // to the current mouse position
      context.beginPath();
      context.lineWidth = 3;
      context.lineJoin = context.lineCap = 'round';
      context.setLineDash([0, 0]);
      context.globalAlpha = 1.0;
    
      context.strokeStyle = 'red';
      context.arc(startPoint.x, startPoint.y, cradius, 0, 2 * Math.PI, false);
    
      context.fillStyle = 'rgba(25,50,75,0.5)';
      context.fill();
      context.stroke();
    
    
    }
    
    canvas.onmouseup = function() {
      isDrawing = false;
    };
    
    canvas.onmouseleave = function() {
      isDrawing = false;
    };
    #divContainer {
      width: 100%;
      height: 80%;
      background: #ddd;
    }
    
    #divContentArea {
      left: 0px;
      top: 0px;
      right: 0px;
      bottom: 0px;
    }
    
    .canvas {
      cursor: crosshair;
      position: relative;
      left: 0px;
      top: 0px;
    }
    <div>
      Click the button to select the shape type then click and drag mouse on the canvas below.
      <BR>
    
      <button type="button" onClick='shapetype="circle";'>Draw Circle</button>
      <button type="button" onClick='shapetype="triangle";'>Draw Triangle</button>
      <BR>
    
    </div>
    
    <div id="divContainer">
    
      <div id="divContentArea">
    
        <canvas id="canvas" class='canvas'>
                Sorry, your browser does not support a canvas object.
                </canvas>
    
      </div>
    </div>

    【讨论】:

    • 谢谢。我已经接受了答案,但我也感谢您的解释和回答。 +1。
    • 没问题 TenG - 我写得太慢了,没有注意到其他人已经回答了。 ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多