画布绘制边距修正

时间:2016-12-17 23:45:51

标签: javascript css3 canvas

我正在尝试在此网址中找到的一些绘制技巧:

http://perfectionkills.com/exploring-canvas-drawing-techniques/

我刚注意到更高级别的css属性未应用于canvas元素鼠标事件。有没有一种简单的方法来解决这个问题?

<head>

    <meta charset="utf-8">
    <title>Spray Can</title>

    <style>

    body {
        margin: 0;
        padding: 0;
    }

    #container {
        border: 1px solid #ccc;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
    }

    #canvas {
    }

    </style>

    <script>

        document.addEventListener('DOMContentLoaded', function () {

            var canvas = document.getElementById('canvas');
            var context = canvas.getContext('2d');
            var isDrawing;

            canvas.onmousedown = function(e) {
                isDrawing = true;
                context.moveTo(e.clientX, e.clientY);
            };

            canvas.onmousemove = function(e) {

                if (isDrawing) {

                    var k = 4;

                    var radgrad = context.createRadialGradient(e.clientX, e.clientY, k, e.clientX, e.clientY, k * 2);

                    radgrad.addColorStop(0, 'rgba(0,0,0,1)');
                    radgrad.addColorStop(0.5, 'rgba(0,0,0,0.5)');
                    radgrad.addColorStop(1, 'rgba(0,0,0,0)');
                    context.fillStyle = radgrad;

                    context.fillRect(e.clientX - k * 2, e.clientY - k * 2, k * 2 * 2, k * 2 * 2);

                }

            };

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

        });

    </script>

</head>

<body>

    <div id="container">
        <canvas id="canvas" width="400" height="400"></canvas>
    </div>

</body>

https://jsfiddle.net/crpq8t5q/1/

1 个答案:

答案 0 :(得分:1)

您需要将鼠标事件的坐标转换为相对于画布的坐标。

由于此处您无法触及比例或旋转,因此这只是一个简单的canvasX = mouseX - canvas.offsetLeftcanvasY = mouseY - canvas.offsetTop

这些offsetXXX属性在画布上可用,但您也可以使用getBoundingClientRect(),如果您的css更复杂(例如,具有不同可滚动区域的嵌套元素),它将返回更好的结果。

但是,每次滚动页面或调整页面大小时,此偏移量都会更改,您需要更新这些值。

此外,在鼠标事件中创建readialGradient是一个非常糟糕的主意。此事件可以以非常高的速率发射,并且创建渐变会占用记忆 然后最好创建一个渐变,并修改整个上下文的矩阵,以便将渐变放在鼠标坐标处:

&#13;
&#13;
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var isDrawing;

var k = 4;
// create the gradient only once
var radgrad = context.createRadialGradient(0, 0, k, 0, 0, k * 2);
radgrad.addColorStop(0, 'rgba(0,0,0,1)');
radgrad.addColorStop(0.5, 'rgba(0,0,0,0.5)');
radgrad.addColorStop(1, 'rgba(0,0,0,0)');
// get our canvas margins;
var rect;

function getRect() {
  rect = canvas.getBoundingClientRect();
}

canvas.onmousedown = function(e) {
  isDrawing = true;
  context.moveTo(e.clientX, e.clientY);
};

canvas.onmousemove = function(e) {

  if (isDrawing) {
    // normalize our mouse event's coordinates
    var x = e.clientX - rect.left;
    var y = e.clientY - rect.top;
    // change the canvas matrix coordinates so we draw at mouse positions
    context.setTransform(1, 0, 0, 1, x, y)
    context.fillStyle = radgrad;
    context.fillRect(-k * 2, -k * 2, k * 2 * 2, k * 2 * 2);
  }
};

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

function resizeHandler() {
  debouncing = false;
  getRect();
}
window.onscroll = window.onresize = function() {
  // debounce the events
  if (!debouncing) {
    requestAnimationFrame(resizeHandler);
  }
  debouncing = true;
}

getRect();
&#13;
body {
  margin: 0;
  padding: 0;
}
#container {
  border: 1px solid #ccc;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
#canvas {}
&#13;
<div id="container">
  <canvas id="canvas" width="400" height="400"></canvas>
</div>
&#13;
&#13;
&#13;