python贝塞尔曲线_n阶贝塞尔曲线(bezier)javascript 实现解析

最近学习canvas,看到bezier曲线,所以补充了下知识,另外相关的数学定律都忘光了~

需要了解的

前期需要了解相关的知识,可以看下维基百科

绘制

canvas本身只提供了二次和三次的绘制函数,如果更高阶级的怎么办呢~要对起进行降阶拆分。

我们来看下这个案例的js,这个demo并没有像我们的方程式写的那样来进行计算,但是它用了递归的操作,递归调用draw方法,来实现层层的绘制

var input = document.getElementsByTagName('input')[0]

var span = document.getElementsByTagName('span')[0]

var div = document.getElementsByTagName('div')[0]

var ctx1 = document.getElementsByTagName('canvas')[0].getContext('2d')

var ctx2 = document.getElementsByTagName('canvas')[1].getContext('2d')

var ctx3 = document.getElementsByTagName('canvas')[2].getContext('2d')

var points = [], colors = [], running = true, steps = 200, interval = 16, num

ctx1.font = '16px consolas'

ctx1.fillStyle = ctx1.strokeStyle = 'hsl(0, 0%, 50%)'

ctx1.lineWidth = ctx2.lineWidth = 2

ctx3.strokeStyle = 'hsl(0, 90%, 70%)'

function count() {

num = parseInt(input.value)

span.innerHTML = num

}

function toggle() {

input.disabled = running = !running

}

function draw(per, arr, color) {

var ary = []

var node

ctx2.strokeStyle = ctx2.fillStyle = colors[color]

node = arr.reduce(function(previous, current, index) {

// 从第二个元素开始,第二个点,这时候index为1,计算得到p点,index为1的时候,p点为bezier开始点到第一个控制点的插值

// 第三个元素的时候,第三个点,index为2,计算得到p点,index为2的时候,p点为第一个控制点向第二个控制点移动的插值

var p = {x: arr[index - 1].x + (arr[index].x - arr[index - 1].x) * per, y: arr[index - 1].y + (arr[index].y - arr[index - 1].y) * per}

if(index > 1) {

// 当达到第二个控制点的时候,获取从开始点到第一个控制点的p,进行line

ctx2.beginPath()

ctx2.moveTo(previous.x, previous.y)

ctx2.lineTo(p.x, p.y)

ctx2.stroke()

ctx2.closePath()

}

// 绘制当前的插值点

ctx2.beginPath()

ctx2.arc(p.x, p.y, 3, 0, Math.PI * 2, true)

ctx2.fill()

ctx2.closePath()

// 将坐标点push到新的坐标数组中

ary.push(p)

return p

})

if(ary.length > 1) {

// 将插值作为新的开始点和控制点进行绘制,就这样递归下去

draw(per, ary, color + 1)

} else {

// 如果插值的数组只有1个值,绘制的就是bezier曲线上的点,从起点一点一点连到结束点

ctx3.lineTo(node.x, node.y)

ctx3.stroke()

}

}

var drawAsync = eval(Wind.compile("async", function () {

toggle()

ctx3.beginPath()

ctx3.moveTo(points[0].x, points[0].y)

for(var i = 0; i <= steps; i++) {

draw(i / steps, points, 0)

$await(Wind.Async.sleep(interval))

ctx2.clearRect(0, 0, 800, 600)

}

ctx3.closePath()

points = []

toggle()

}))

div.addEventListener('click', function(e) {

if(running) {

return

}

var point = {x: e.pageX - div.offsetLeft, y: e.pageY - div.offsetTop}

if(points.length == 0) {

ctx1.clearRect(0, 0, 800, 600)

ctx2.clearRect(0, 0, 800, 600)

ctx3.clearRect(0, 0, 800, 600)

} else {

ctx1.beginPath()

ctx1.moveTo(point.x, point.y)

ctx1.lineTo(points[points.length - 1].x, points[points.length - 1].y)

ctx1.stroke()

ctx1.closePath()

}

ctx1.beginPath()

ctx1.fillText('[' + point.x + ', ' + point.y + ']', 15, 25 * (points.length + 1))

ctx1.arc(point.x, point.y, 4, 0, Math.PI * 2, true)

ctx1.fill()

ctx1.closePath()

points.push(point)

if(points.length == num) {

drawAsync().start()

}

}, false)

input.addEventListener('change', count, false)

window.addEventListener('load', function() {

for(var i = 0; i < parseInt(input.max); i++) {

colors[i] = 'hsl(' + 60*(i + 1) + ', 60%, 60%)'

}

count()

toggle()

}, false)

总结

让我自己写还真写不出来。。。对array.reduce的用法真的炉火纯青了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值