2016-02-16 4 views
0

Я получил это приложение для рисования холста, и мне нужна помощь в понимании некоторых частей кода. Приложение рисует действительно гладкую линию, как инструмент рисования пера.HTML 5 Холст рисует прямой пример гладкой линии?

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

 
var radius = 10; 
 
var dragging = false; 
 

 

 
canvas.width = window.innerWidth; 
 
canvas.height = window.innerHeight; 
 
context.lineWidth = radius*2; 
 

 
var putPoint = function(e){ 
 
    if(dragging){ 
 
    context.lineTo(e.clientX, e.clientY); 
 
    context.stroke(); 
 
    context.beginPath(); 
 
    context.arc(e.clientX, e.clientY, radius, 0, Math.PI*2); 
 
    context.fill(); 
 
    context.beginPath(); 
 
    context.moveTo(e.clientX, e.clientY); 
 
    } 
 
} 
 

 
var engage = function(e){ 
 
    dragging = true; 
 
    putPoint(e); 
 
} 
 

 
var disengage = function(){ 
 
    dragging = false; 
 
    context.beginPath(); 
 
} 
 

 
canvas.addEventListener('mousedown', engage); 
 
canvas.addEventListener('mousemove', putPoint); 
 
canvas.addEventListener('mouseup', disengage);
<!DOCTYPE html> 
 
<html lang="en"> 
 
<head> 
 
    <meta charset="UTF-8"> 
 
    <title>Canvas</title> 
 
</head> 
 
<body style="margin:0"> 
 
    <canvas style="display:block;" id="canvas"> 
 
    sorry this browser does not support HTML 5 Canvas! 
 
    </canvas> 
 
    <script src="main.js"></script> 
 
</body> 
 
</html>

Я хотел бы обратить внимание на эту часть кода JS, которые у меня возникли трудности с пониманием:

var putPoint = function(e){ 
    if(dragging){ 
    context.lineTo(e.clientX, e.clientY); 
    context.stroke(); 
    context.beginPath(); 
    context.arc(e.clientX, e.clientY, radius, 0, Math.PI*2); 
    context.fill(); 
    context.beginPath(); 
    context.moveTo(e.clientX, e.clientY); 
    } 
} 

Я просто не понимаю, как части, что код относятся друг к другу и в конечном итоге создают действительно гладкую линию.

Нарушение этого кода вниз:

context.lineTo(e.clientX, e.clientY); 
context.stroke(); 

Эта часть кода проста, так как он соединяет предыдущий координируют с линией. Однако линия негладкая и выглядит грубой.

context.beginPath(); 
context.arc(e.clientX, e.clientY, radius, 0, Math.PI*2); 
context.fill(); 

Эта часть просто печатает круг, но если я двигаю мышь очень быстро круги не соединяются друг с другом.

context.beginPath(); 
context.moveTo(e.clientX, e.clientY); 

Это заключительная часть кода, которая делает рисование линии очень гладкой и эффективной. Эта часть кода, которую я не понимаю и как она имеет отношение.

Пожалуйста, объясните логику кода для всей функции и ее отношение к каждому.

Благодаря

ответ

1

Концепции в этой функции проста: сделать «гладкую» линию, которую вы в основном должны сначала сделать нормальную «грубую» линию, а затем закончить его с кругом.

разбив его, вы делаете это:

  1. Нарисуйте "грубую" строку:

    context.lineTo(e.clientX, e.clientY); 
    context.stroke(); 
    

    Какой будет выглядеть следующим образом:

    line

  2. Добавьте круг, чтобы линия была «гладкой»:

    context.beginPath(); 
    context.arc(e.clientX, e.clientY, radius, 0, Math.PI*2); 
    context.fill(); 
    

    который преобразует предыдущую строку во что-то вроде этого:

    smooth line

    Здесь вы можете спросить: вы сказали «конец это с кружком», так почему существует круг в начало линии? Ну, на самом деле есть еще больше кругов. Каждый раз, когда вызывается функция, линия выводится из предыдущей известной позиции мыши на следующую, поэтому в начале линия рисуется с нулевой длиной и создается круг. Затем мышь продолжает двигаться, и в ее конце добавляются более маленькие сегменты с кругами.Снятие всех этих (почти бесконечных) маленьких сегментов, заканчивающихся кругами, создает приятную прямую линию.

    Это также означает, что гладкость линии зависит только от разрешения, на которое оно нарисовано. Чем больше раз в секунду вызывается функция и чем медленнее мышь, тем более гладкой будет линия.

  3. Переместить текущую позицию на пути к положению мыши

    context.beginPath(); 
    context.moveTo(e.clientX, e.clientY); 
    

    Эти две строки просто убедитесь, что в следующий раз, когда вызывается функция, точка начала уже будет установлен.

+0

Привет, спасибо за ваш ответ, и я понимаю его гораздо больше. Только один вопрос относительно 3.0 в вашем ответе. Я не понимаю, почему это необходимо, поскольку строка в 2.0 выглядит уже гладкой? Спасибо – jdogdvr

+0

@jdogdvr о третьем пункте: эти две линии задают новый путь (для следующего сегмента, который нужно нарисовать), чтобы начать с текущей позиции мыши. Таким образом, пока вы рисуете, позиция снова и снова обновляется, чтобы рисовать сегменты. –

+0

Хорошо, хотя бы не lineTo (x, y) в начале функции установить координаты клиентов? Например, если функция вызвала 2 раза, тогда она будет рисовать линию от A до B. Я замечаю, что без кода в 3.0 круги необычайно больше, а перемещение мыши быстро печатает только несколько кругов. Я просто не понимаю ... – jdogdvr

Смежные вопросы