2016-08-06 10 views
3

Наконец-то я узнал, как оживить рисование кривой Безье. Я видел другие решения, которые используют квадратные кривые для этого, но мне нужно было 4 балла за то, что я делал, и b-сплайн был слишком сложным, чтобы найти случайные сюжеты, плюс это именно то, как я хочу это сделать; с Безье Кувес.Как сохранить гладкие линии при вытягивании анимированных кривых Безье в холсте html5

Моя проблема: я не могу найти хорошую, быструю скорость, не видя точек или линий. Я должен что-то упустить. Может ли кто-нибудь указать мою ошибку или более эффективный способ добиться этого в любое время и в любой момент? Мне это нужно, чтобы быть устойчивым и быстрее, чем в примере ниже, но если я больше пробелов получить больше и больше ...

скрипку с кодом: https://jsfiddle.net/qzsy8aL7/

//B(t) = (1 - t)^3P0 + 3t(1 - t)^2 P1 + 3t^2(1 - t)P2 + t^3P3 
function animatedBSpline(context, points, t) { 
    // Draw curve segment 
    context.beginPath(); 
    context.moveTo(
    Math.pow(1 - t, 3) * points[0].x + 
    3 * t * Math.pow(1 - t, 2) * points[1].x + 
    3 * Math.pow(t, 2) * (1 - t) * points[2].x + 
    Math.pow(t, 3) * points[3].x, 

    Math.pow(1 - t, 3) * points[0].y + 
    3 * t * Math.pow(1 - t, 2) * points[1].y + 
    3 * Math.pow(t, 2) * (1 - t) * points[2].y + 
    Math.pow(t, 3) * points[3].y 
); 

    // Draw spline segemnts 
    context.lineTo(
    Math.pow((1 - t) + 0.001, 3) * points[0].x + 
    3 * (t + 0.001) * Math.pow((1 - t) + 0.001, 2) * points[1].x + 
    3 * Math.pow(t + 0.001, 2) * (1 - (t + 0.001)) * points[2].x + 
    Math.pow(t + 0.001, 3) * points[3].x, 

    Math.pow((1 - t) + 0.001, 3) * points[0].y + 
    3 * (t + 0.001) * Math.pow((1 - t) + 0.001, 2) * points[1].y + 
    3 * Math.pow(t + 0.001, 2) * (1 - (t + 0.001)) * points[2].y + 
    Math.pow(t + 0.001, 3) * points[3].y 
); 

    //33d4ff 
    context.strokeStyle="#35bb23"; 
    context.lineJoin="round"; 
    context.lineWidth=2; 
    context.fillStyle = "black"; 
    context.stroke(); 
    context.fill(); 

    // Keep going until t = 1 
    if (t < 1) requestAnimationFrame(function() { 
    animatedBSpline(context, points, t + 0.01); 
    }); 
    else 
    context.closePath(); 
} 

Если требуется больше информации пожалуйста, дай мне знать. Я был здесь весь день.

Чтобы добавить: Если я просто прямо рисую это с этими участками, и не анимируем его, это выглядит отлично, очевидно, но просто хотел указать на это. Его что-то с тем, как я оживляю, я просто не знаю.

+0

Ну, я заметил, что на каждом сегменте вы вызываете 'context.beginPath()' и 'context.moveTo (...)', что приведет к тому, что сегменты станут непересекающимися. Вы должны называть эти два метода только в начале кривой, а не в каждой точке. –

+0

где еще я бы это сказал? Если я помещу его где-нибудь еще, это будет либо черным, либо несколькими небольшими строками (я думаю), либо ничего не сделаю. – Grant

+0

https://jsfiddle.net/qzsy8aL7/1/ Я не уверен, что это то, что вы собираетесь делать, но я сделал линию непрерывной и удалил этот противный 'eval', превратив« точки »в массив. –

ответ

2

Вот полный обновленный код с анимацией зеленой кривой Безье:

(function() { 
 
    var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; 
 

 
    $(function() { 
 
    var canvas = $('#drawings')[0]; 
 
    var context = canvas.getContext('2d'); 
 
    var lineLength = 0; 
 
    var lineLengthMax = 7; 
 
    var timer; 
 

 
    // Define points 
 
    var points = [[{ 
 
     x: 600, 
 
     y: 200 
 
    }, { 
 
     x: 550, 
 
     y: 100 
 
    }, { 
 
     x: 350, 
 
     y: 100 
 
    }, { 
 
     x: 300, 
 
     y: 250 
 
    }], 
 
    [{ 
 
     x: 350, 
 
     y: 250 
 
    }, { 
 
     x: 75, 
 
     y: 225 
 
    }, { 
 
     x: 30, 
 
     y: 400 
 
    }, { 
 
     x: 120, 
 
     y: 450 
 
    }], 
 
    [{ 
 
     x: 200, 
 
     y: 450 
 
    }, { 
 
     x: 5, 
 
     y: 380 
 
    }, { 
 
     x: 25, 
 
     y: 750 
 
    }, { 
 
     x: 175, 
 
     y: 610 
 
    }], 
 
    [{ 
 
     x: 200, 
 
     y: 520 
 
    }, { 
 
     x: 150, 
 
     y: 560 
 
    }, { 
 
     x: 175, 
 
     y: 750 
 
    }, { 
 
     x: 325, 
 
     y: 605 
 
    }], 
 
    [{ 
 
     x: 400, 
 
     y: 395 
 
    }, { 
 
     x: 275, 
 
     y: 450 
 
    }, { 
 
     x: 250, 
 
     y: 750 
 
    }, { 
 
     x: 565, 
 
     y: 655 
 
    }], 
 
    [{ 
 
     x: 515, 
 
     y: 540 
 
    }, { 
 
     x: 500, 
 
     y: 695 
 
    }, { 
 
     x: 660, 
 
     y: 675 
 
    }, { 
 
     x: 675, 
 
     y: 560 
 
    }], 
 
    [{ 
 
     x: 600, 
 
     y: 400 
 
    }, { 
 
     x: 790, 
 
     y: 315 
 
    }, { 
 
     x: 1005, 
 
     y: 500 
 
    }, { 
 
     x: 675, 
 
     y: 585 
 
    }], 
 
    [{ 
 
     x: 500, 
 
     y: 250 
 
    }, { 
 
     x: 700, 
 
     y: 100 
 
    }, { 
 
     x: 775, 
 
     y: 350 
 
    }, { 
 
     x: 700, 
 
     y: 380 
 
    }]]; 
 

 
    //33d4ff 
 
    context.strokeStyle="#35bb23"; 
 
    context.lineJoin="round"; 
 
    context.lineWidth=2; 
 

 
    doLineDraw(); 
 
    //animatedBSpline(context, points, 0); 
 

 
    function doLineDraw() { 
 
     if (lineLength <= lineLengthMax) { 
 
     clearTimeout(timer); 
 

 
     // Kick things off at t = 0 
 
     context.beginPath(); 
 
     animatedBSpline(context, points[lineLength], 0); 
 
     //animatedBSpline(context, eval('points'+(lineLength)), 0); 
 

 
     lineLength++; 
 
     if (lineLength <= lineLengthMax) 
 
      timer = setTimeout(doLineDraw, 2000); 
 
     } 
 
    } 
 

 
    //B(t) = (1 - t)^3P0 + 3t(1 - t)^2 P1 + 3t^2(1 - t)P2 + t^3P3 
 
    function animatedBSpline(context, points, t) { 
 
     // Draw curve segment 
 
     if (t == 0) 
 
     context.moveTo(
 
      Math.pow(1 - t, 3) * points[0].x + 
 
      3 * t * Math.pow(1 - t, 2) * points[1].x + 
 
      3 * Math.pow(t, 2) * (1 - t) * points[2].x + 
 
      Math.pow(t, 3) * points[3].x, 
 

 
      Math.pow(1 - t, 3) * points[0].y + 
 
      3 * t * Math.pow(1 - t, 2) * points[1].y + 
 
      3 * Math.pow(t, 2) * (1 - t) * points[2].y + 
 
      Math.pow(t, 3) * points[3].y 
 
     ); 
 
     
 
     // Draw spline segemnts 
 
     context.lineTo(
 
     Math.pow((1 - t) + 0.001, 3) * points[0].x + 
 
     3 * (t + 0.001) * Math.pow((1 - t) + 0.001, 2) * points[1].x + 
 
     3 * Math.pow(t + 0.001, 2) * (1 - (t + 0.001)) * points[2].x + 
 
     Math.pow(t + 0.001, 3) * points[3].x, 
 

 
     Math.pow((1 - t) + 0.001, 3) * points[0].y + 
 
     3 * (t + 0.001) * Math.pow((1 - t) + 0.001, 2) * points[1].y + 
 
     3 * Math.pow(t + 0.001, 2) * (1 - (t + 0.001)) * points[2].y + 
 
     Math.pow(t + 0.001, 3) * points[3].y 
 
    ); 
 
\t \t \t 
 
     
 
     //context.fillStyle = "black"; 
 
     context.stroke(); 
 
     //context.fill(); 
 
\t \t \t 
 
     // Keep going until t = 1 
 
     if (t < 1) requestAnimationFrame(function() { 
 
     animatedBSpline(context, points, t + 0.01); 
 
     }); 
 
    } 
 
    }); 
 
}());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<section> 
 
    <article> 
 
    <canvas id="drawings" width="1000" height="1000" /> 
 
    </article> 
 
</section>

несколько ключевых точек, некоторые из которых были по касательной к вопросу.

  • Избегайте использования eval для ссылок на имена переменных, которые имеют номера после исправления. Просто используйте массив.
  • Причина, по которой вы были нарисованы точками вместо линий, состояла в том, что вы вызывали context.beginPath() и context.moveTo() перед каждой новой вершиной, что заставляет «забыть» предыдущие инструкции context.stroke() и context.fill().

Я переехал context.beginPath() вне animatedBSpline() и конкретизирован context.moveTo() работать на t==0 в этой функции, таким образом нет бессвязных точек. Надеюсь, это поможет.

+0

Большое вам спасибо и объясните. На этом не было тонны с кривыми Безье и приходилось копать, как сумасшедший. – Grant

+0

protip: просто используйте прямое умножение, а не 'Math.pow', так как мы имеем дело с более низкими полномочиями. «Пусть t2 = t * t, mt = 1-t, mt2 = mt * mt, t3 = t2 * t, mt3 = mt * mt2', и теперь вы также не постоянно вызываете служебные вызовы функции. То же самое для этого размера шага: сделайте его var, чтобы вы могли легко его изменить, вместо того, чтобы «0.001» был жестко запрограммирован везде (для небольших кривых 0.001, вероятно, на порядок больше, чем вам на самом деле) –

+0

@ Mike'Pomax'Kamermans благодарит. Я буквально скопировал и вставил математику, все, о чем я говорил, это вопрос, который был задан (и «eval») –