canva绘制(二次、三次)贝塞尔曲线并且图片在曲线上运动

下图为实现效果(图片在三次贝塞尔曲线中运动)
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    html,
    body,
    canvas {
      margin: 0;
      padding: 0;
      height: 100%;
      width: 100%;
    }
  </style>
</head>

<body>
  <canvas id="canvas" ></canvas>
</body>
<script>
  const canvas = document.getElementById('canvas')
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
  const ctx = canvas.getContext('2d');
  //起点
//   var [x1, y1] = [10, 10];
//   //小球起点
//   var [x, y] = [10, 10];
//   //控制点 如果是二次贝塞尔曲线用的控制点是cx,cy
// //   var [cx, cy] = [100, 0];
//   //终点
//   var [x2, y2] = [200, 200]
//  三次贝塞尔曲线用的控制点是cx1,cx2,cy1,cy2
//   var [cx1, cy1] = [100, 0];
//   var [cx2, cy2] = [100, 250]
var t = 0
// 由于本示例为三次贝尔赛曲线所以控制点有两个
  var pointarr = [
    {
      start:{x:10,y:10},//小球起点
      begin:{x:10,y:10},//起点      这两个的区别是小球的起点一直随着运动轨迹在发生变化
      control1:{x:100,y:0},  //控制点1       
      control2:{x:100,y:250},  //控制点2
      end:{x:200,y:200}  //终点
    }
  ]
  //画一条线
  function draw() {
    ctx.beginPath()
    
    // ctx.moveTo(10, 10)
    // 二次贝塞尔曲线的绘制   与上边的 ctx.moveTo()连用 ,三次的也是
    // ctx.quadraticCurveTo(cx, cy, x2, y2)
    // 三次贝尔赛曲线的绘制
    // ctx.bezierCurveTo(cx1, cy1, cx2, cy2, x2, y2)

    // 此次示例的是三次贝塞尔曲线
    ctx.moveTo(pointarr[0].begin.x, pointarr[0].begin.y);
    ctx.bezierCurveTo(pointarr[0].control1.x, pointarr[0].control1.y, pointarr[0].control2.x, pointarr[0].control2.y, pointarr[0].end.x, pointarr[0].end.y);

    ctx.stroke()
    ctx.closePath()
  }

  /*贝塞尔曲线上点位的控制*/
  function computedPosition() {

    // 二次贝塞尔曲线上运动轨迹的运算方式
    // x = Math.pow(1 - t, 2) * x1 + 2 * t * (1 - t) * cx + Math.pow(t, 2) * x2
    // y = Math.pow(1 - t, 2) * y1 + 2 * t * (1 - t) * cy + Math.pow(t, 2) * y2

    // 三次的贝塞尔曲线运动轨迹的计算方式
    // x = x1 * Math.pow((1 - t), 3) + 3 * cx1 * t * Math.pow((1 - t), 2) + 3 * cx2 * Math.pow(t, 2) * (1 - t) + x2 * Math.pow(t, 3)
    // y = y1 * Math.pow((1 - t), 3) + 3 * cy1 * t * Math.pow((1 - t), 2) + 3 * cy2 * Math.pow(t, 2) * (1 - t) + y2 * Math.pow(t, 3)
    // 根据开始到结束的大小判断,控制时间 
    if (pointarr[0].start.x > pointarr[0].end.x) {
        t = 0;
        pointarr[0].start.x = pointarr[0].begin.x;
        pointarr[0].start.y = pointarr[0].begin.y;
    }


    pointarr[0].start.x = pointarr[0].begin.x * Math.pow((1 - t), 3) + 3 * t * pointarr[0].control1.x * Math.pow((1 - t), 2) + 3 * pointarr[0].control2.x * Math.pow(t, 2) * (1 - t) + pointarr[0].end.x * Math.pow(t, 3);
    pointarr[0].start.y = pointarr[0].begin.y * Math.pow((1 - t), 3) + 3 * t * pointarr[0].control1.y * Math.pow((1 - t), 2) + 3 * pointarr[0].control2.y * Math.pow(t, 2) * (1 - t) + pointarr[0].end.y * Math.pow(t, 3);
    
  }

  function drawPoint() {
    computedPosition()
    // 下面四行为红色小球的运动轨迹但是需要加requestAnimationFrame(loopDraw)下面的代码cleaReact()
    // ctx.beginPath()
    // ctx.fillStyle = "red"
    // ctx.arc(pointarr[0].start.x, pointarr[0].start.y, 10, 0, 2 * Math.PI)
    // ctx.fill()

    let leftimgrun1 = new Image()
    leftimgrun1.src = './img/网络设备.png';
    leftimgrun1.onload = function () {
        ctx.clearRect(0, 0,pointarr[0].end.x+leftimgrun1.width,pointarr[0].end.y+leftimgrun1.width)

        ctx.drawImage(leftimgrun1,pointarr[0].start.x-15,pointarr[0].start.y-15, 25, 25)

    }

    
  }

  let loopDraw = () => {
    requestAnimationFrame(loopDraw);//这个是由浏览器调度的  而 setTimeout 只能设置一个固定的时间间隔,这个时间不一定和屏幕的刷新时间相同。
    // ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
    draw()
    drawPoint()
    t += 0.007//控制动画移动速度
  }
  loopDraw()//启动动画
</script>
</html>

二次贝塞尔曲线的绘制:

ctx.quadraticCurveTo(cx, cy, x2, y2)

三次贝尔赛曲线的绘制:

ctx.bezierCurveTo(cx1, cy1, cx2, cy2, x2, y2)

二次贝尔赛曲线的运动的x,y

x = Math.pow(1 - t, 2) * x1 + 2 * t * (1 - t) * cx + Math.pow(t, 2) * x2
y = Math.pow(1 - t, 2) * y1 + 2 * t * (1 - t) * cy + Math.pow(t, 2) * y2

三次贝尔赛曲线的运动的x,y

x = x1 * Math.pow((1 - t), 3) + 3 * cx1 * t * Math.pow((1 - t),2) + 3 * cx2 * Math.pow(t, 2) * (1 - t) + x2 * Math.pow(t, 3)
y = y1 * Math.pow((1 - t), 3) + 3 * cy1 * t * Math.pow((1 - t), 2) + 3 * cy2 * Math.pow(t, 2) * (1 - t) + y2 * Math.pow(t, 3)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值