2015-07-01 16 views
5

Bir proje için tuval üzerine javascript içinde nth order bezier kodlamaya çalışılıyor. Kullanıcının her bir son noktayı ve kontrol noktalarını seçmek için 'b' şeklinde bir düğmeye basmasını istiyorum. Şimdiye kadar, tuşa basmada fare koordinatlarını alıp yerleşik fonksiyonları kullanarak kuadratik ve bezier eğrileri oluşturabiliyorum. İlk sipariş için nasıl kod yazabilirim?nth order Bezier eğrisi kodlama

+0

Bir dizi yapın ve her satırı içinde saklayın. – user2072826

cevap

5

İşte inci mertebeden Bezier eğrilerinin bir JavaScript uygulaması var:

// setup canvas 
 
var canvas = document.getElementById('canvas'); 
 
var ctx = canvas.getContext('2d'); 
 

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

 
ctx.fillText("INSTRUCTIONS: Press the 'b' key to add points to your curve. Press the 'c' key to clear all points and start over.", 20, 20); 
 

 
// initialize points list 
 
var plist = []; 
 

 
// track mouse movements 
 
var mouseX; 
 
var mouseY; 
 

 
document.addEventListener("mousemove", function(e) { 
 
    mouseX = e.clientX; 
 
    mouseY = e.clientY; 
 
}); 
 

 
// from: http://rosettacode.org/wiki/Evaluate_binomial_coefficients#JavaScript 
 
function binom(n, k) { 
 
    var coeff = 1; 
 
    for (var i = n - k + 1; i <= n; i++) coeff *= i; 
 
    for (var i = 1; i <= k; i++) coeff /= i; 
 
    return coeff; 
 
} 
 

 
// based on: https://stackoverflow.com/questions/16227300 
 
function bezier(t, plist) { 
 
    var order = plist.length - 1; 
 

 
    var y = 0; 
 
    var x = 0; 
 

 
    for (i = 0; i <= order; i++) { 
 
    x = x + (binom(order, i) * Math.pow((1 - t), (order - i)) * Math.pow(t, i) * (plist[i].x)); 
 
    y = y + (binom(order, i) * Math.pow((1 - t), (order - i)) * Math.pow(t, i) * (plist[i].y)); 
 
    } 
 

 
    return { 
 
    x: x, 
 
    y: y 
 
    }; 
 
} 
 

 
// draw the Bezier curve 
 
function draw(plist) { 
 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
 
    var accuracy = 0.01; //this'll give the 100 bezier segments 
 
    ctx.beginPath(); 
 
    ctx.moveTo(plist[0].x, plist[0].y); 
 

 
    for (p in plist) { 
 
    ctx.fillText(p, plist[p].x + 5, plist[p].y - 5); 
 
    ctx.fillRect(plist[p].x - 5, plist[p].y - 5, 10, 10); 
 
    } 
 

 
    for (var i = 0; i < 1; i += accuracy) { 
 
    var p = bezier(i, plist); 
 
    ctx.lineTo(p.x, p.y); 
 
    } 
 

 
    ctx.stroke(); 
 
    ctx.closePath(); 
 
} 
 

 
// listen for keypress 
 
document.addEventListener("keydown", function(e) { 
 
    switch (e.keyCode) { 
 
    case 66: 
 
     // b key 
 
     plist.push({ 
 
     x: mouseX, 
 
     y: mouseY 
 
     }); 
 
     break; 
 
    case 67: 
 
     // c key 
 
     plist = []; 
 
     break; 
 
    } 
 
    draw(plist); 
 
});
html, 
 
body { 
 
    height: 100%; 
 
    margin: 0 auto; 
 
}
<canvas id="canvas"></canvas>

Bu this implementation of cubic Bezier curves dayanmaktadır. Uygulamanızda, kullanıcı tanımlı noktalar ile points dizisini doldurmak istediğiniz gibi geliyor.

+0

Teşekkür ederim. Takip eden soru: Kullanıcı tanımlı noktalara eklemenin en iyi yolu nedir? Son gün deney yaptım, ama işe yaramayacak bir şey bulamadım. İstediğim şey, kullanıcının 'b' tuşuna basması ve ardından her basıştan sonra çizim yapmasıdır. Bu nedenle, satır için iki kez 'b' tuşuna, ikinci dereceden ise 3'e basarsınız. – Adam

+2

[İşte bir keman] (http: // jsfiddle .net/rphv/3jkt16Ly/3 /) yardımcı olabilir. 'B' tuşuna basıldığında fare imlecinin altına yeni bir nokta ekler ve 'c' tuşuna bastığınızda puan listesini temizler. Ayrıca (numbererd) noktaları eklendikçe görüntüler. Bunu yapmak için çizim kodunu "draw()" kendi işlevine yeniden çizdim, "plist" i global kapsama taşıdım ve fare konumunu izlemek için bir "mousemove" dinleyicisi ekledim. Bu size yardımcı olsaydı lütfen yukarıdaki cevabı kaldırmayı düşünün. – rphv

+0

Çok teşekkür ederim! Yapabilseydim, ama yine de beni temsil etmeme izin vermezdim. Hesabım çok yeni – Adam