【问题标题】:Hatching effect inside HTML canvas rectangleHTML画布矩形内的阴影效果
【发布时间】:2022-01-12 03:07:53
【问题描述】:

背景

我正在使用浏览器 HTML5 画布元素。

我有代码(我在网上找到)可以在此画布上绘制一个矩形。

问题

我想在触发鼠标移动事件时应用如图所示的“阴影”效果。如何实现?

当前方法

我当前的方法是在触发 mouseMove 事件处理程序时检查鼠标的 x 和 y 坐标。如果 x 和 y 坐标与原始坐标相比的差异大于某个预定义的增量或与矩形宽度和高度的比率,我将尝试在 x 和 y 方向上的等距坐标之间绘制直线

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    #canvas{border:1px solid red;}
</style>

<script>
$(function(){

    // get references to the canvas and context
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    // style the context
    ctx.strokeStyle = "blue";
    ctx.lineWidth=3;

    // calculate where the canvas is on the window
    // (used to help calculate mouseX/mouseY)
    var $canvas=$("#canvas");
    var canvasOffset=$canvas.offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;
    var scrollX=$canvas.scrollLeft();
    var scrollY=$canvas.scrollTop();

    // this flage is true when the user is dragging the mouse
    var isDown=false;

    // these vars will hold the starting mouse position
    var startX;
    var startY;


    function handleMouseDown(e){
      e.preventDefault();
      e.stopPropagation();

      // save the starting x/y of the rectangle
      startX=parseInt(e.clientX-offsetX);
      startY=parseInt(e.clientY-offsetY);

      // set a flag indicating the drag has begun
      isDown=true;
    }

    function handleMouseUp(e){
      e.preventDefault();
      e.stopPropagation();

      // the drag is over, clear the dragging flag
      isDown=false;
    }

    function handleMouseOut(e){
      e.preventDefault();
      e.stopPropagation();

      // the drag is over, clear the dragging flag
      isDown=false;
    }

    function handleMouseMove(e){
      e.preventDefault();
      e.stopPropagation();

      // if we're not dragging, just return
      if(!isDown){return;}

      // get the current mouse position
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);

      // Put your mousemove stuff here

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

      // calculate the rectangle width/height based
      // on starting vs current mouse position
      var width=mouseX-startX;
      var height=mouseY-startY;

      // draw a new rect from the start position 
      // to the current mouse position
      ctx.strokeRect(startX,startY,width,height);

    }

    // listen for mouse events
    $("#canvas").mousedown(function(e){handleMouseDown(e);});
    $("#canvas").mousemove(function(e){handleMouseMove(e);});
    $("#canvas").mouseup(function(e){handleMouseUp(e);});
    $("#canvas").mouseout(function(e){handleMouseOut(e);});

}); // end $(function(){});
</script>
</head>
<body>
    <h4>Drag the mouse to create a rectangle</h4>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

【问题讨论】:

    标签: javascript html html5-canvas rectangles


    【解决方案1】:

    您可以通过使用类似于红色/白色旋转图案的填充填充矩形描绘的区域来实现您想要做的事情。但是我们如何实际创建这种模式呢?

    (1) 创建图块

    图块基本上是一种可以在任一方向无缝重复的形状。在您的情况下,这样的事情应该可以完成:

    可以使用线性渐变动态创建:

        let tile = document.createElement('canvas');
        tile.width = tile.height = 10;
        let ctx = tile.getContext('2d');
        let gradient = ctx.createLinearGradient(0, 0, tile.width, tile.height);
        let colorStops = [
            [0, 'white'],
            [0.35, 'white'],
            [0.35, 'red'],
            [0.5, 'red'],
            [0.5, 'white'],
            [0.85, 'white'],
            [0.85, 'red'],
            [1, 'red']
        ];
        colorStops.forEach(element => {
            gradient.addColorStop(element[0], element[1]);
        });
    
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, tile.width, tile.height);
    

    如果我们在水平和垂直方向上重复该图块 10 次,我们会得到:

    (2) 使用瓦片填充矩形

    其实这并不难,因为你已经有了矩形的位置和大小。因此,我们所要做的就是使步骤 (1) 中的图块成为我们想要使用它的上下文的可重用模式。

    let tilePattern=ctx.createPattern(tile, 'repeat');
    

    所以剩下的就是对你的 mouseMove 处理程序的轻微修改:

    ctx.fillStyle = tilePattern;
    ctx.fillRect(startX, startY, width,height);
    ctx.strokeRect(startX, startY, width, height);
    

    现在,如果我们将所有内容放在一起,我们会得到:

    $(function() {
      let tile = document.createElement('canvas');
      tile.width = tile.height = 10;
      let ctx = tile.getContext('2d');
      let gradient = ctx.createLinearGradient(0, 0, tile.width, tile.height);
      let colorStops = [
        [0, 'white'],
        [0.35, 'white'],
        [0.35, 'red'],
        [0.5, 'red'],
        [0.5, 'white'],
        [0.85, 'white'],
        [0.85, 'red'],
        [1, 'red']
      ];
      colorStops.forEach(element => {
        gradient.addColorStop(element[0], element[1]);
      });
    
      ctx.fillStyle = gradient;
      ctx.fillRect(0, 0, tile.width, tile.height);
    
    
      let canvas = document.getElementById("canvas");
      ctx = canvas.getContext("2d");
      let tilePattern = ctx.createPattern(tile, 'repeat');
      ctx.strokeStyle = "blue";
      ctx.lineWidth = 3;
    
      let $canvas = $("#canvas");
      let canvasOffset = $canvas.offset();
      let offsetX = canvasOffset.left;
      let offsetY = canvasOffset.top;
      let scrollX = $canvas.scrollLeft();
      let scrollY = $canvas.scrollTop();
    
      let isDown = false;
    
      let startX, startY, width, height;
    
      function handleMouseDown(e) {
        e.preventDefault();
        e.stopPropagation();
    
        startX = parseInt(e.clientX - offsetX);
        startY = parseInt(e.clientY - offsetY);
        width = 0;
        height = 0;
        isDown = true;
      }
    
      function handleMouseUp(e) {
        e.preventDefault();
        e.stopPropagation();
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.strokeRect(startX, startY, width, height);
        isDown = false;
      }
    
      function handleMouseOut(e) {
        e.preventDefault();
        e.stopPropagation();
    
        isDown = false;
      }
    
      function handleMouseMove(e) {
        e.preventDefault();
        e.stopPropagation();
    
        if (!isDown) {
          return;
        }
    
        mouseX = parseInt(e.clientX - offsetX);
        mouseY = parseInt(e.clientY - offsetY);
    
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    
        width = mouseX - startX;
        height = mouseY - startY;
    
    
        ctx.fillStyle = tilePattern;
        ctx.fillRect(startX, startY, width, height);
        ctx.strokeRect(startX, startY, width, height);
      }
    
      $("#canvas").mousedown(function(e) {
        handleMouseDown(e);
      });
      $("#canvas").mousemove(function(e) {
        handleMouseMove(e);
      });
      $("#canvas").mouseup(function(e) {
        handleMouseUp(e);
      });
      $("#canvas").mouseout(function(e) {
        handleMouseOut(e);
      });
    
    });
    body {
      background-color: ivory;
    }
    
    #canvas {
      border: 1px solid red;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <h4>Drag the mouse to create a rectangle</h4>
    <canvas id="canvas" width=300 height=300></canvas>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-13
      • 1970-01-01
      相关资源
      最近更新 更多