• 线性插值编写可视化代码


    线性插值

    处于创意编码,游戏开发,数据可视化和生成创意的功能

    [start,end] 在范围内插值,t通常在[0,1] 范围内

    function lerp (start, end, t) {
      return start * (1 - t) + end * t;
    }
    //虽然这样,但是我感觉现在这样,更容易理解
    start+(end-start)*t 
    // 当 t 为 50%的时候,结果为50
    lerp(0, 100, 0.5); // 50  
    // 当 t 为 0% 的时候,结果20
    lerp(20, 80, 0); // 20
    // 当t 为1 的时候,结果为5
    lerp(30, 5, 1); // 5
    lerp(-1, 1, 0.5); // 0
    lerp(0.5, 1, 0.5); // 0.75
    

    案例

    lerp(20, 50, t)逐渐增大圆的半径或lerp(20, 10, t)逐渐减小其线的粗细

    关键代码

          // 半径20-50
          const radius = lerp(20, 50, t);
    
          // 线宽 20-10
          const lineWidth = lerp(20, 10, t);
    
      const canvasSketch = require('canvas-sketch');
      function lerp (start, end, t) {
        return start * (1 - t) + end * t;
      }
    
      const settings = {
        dimensions: [ 512, 512 ],
        animate: true,
        duration: 5
      };
    
      const rect = (context, x, y, width, height, color) => {
        context.fillStyle = color;
        context.fillRect(x, y, width, height);
      };
    
      const circle = (context, x, y, radius, color, lineWidth) => {
        context.strokeStyle = context.fillStyle = color;
        context.beginPath();
        context.arc(x, y, radius, 0, Math.PI * 2, false);
        context.lineWidth = lineWidth;
        if (lineWidth != null) context.stroke();
        else context.fill();
      };
    
      const progress = (context, time, width, height, margin = 0) => {
        context.fillStyle = 'white';
        context.fillRect(
          margin * 2,
          height - margin * 2,
          (width - margin * 4) * time,
          4
        );
      };
    
      const sketch = ({ width, height }) => {
        const margin = 25;
    
        return props => {
          // 拿到我们需要的属性
          const { context, width, height, playhead } = props;
    
    
          // 设置距离margin的背景
          rect(context, margin, margin, width - margin * 2, height - margin * 2, '#e5b5b5');
    
          // 画出场景
          draw(props);
    
          // 在下面画一个时间轴
          progress(context, playhead, width, height, margin);
        };
    
        function draw ({ context, width, height, playhead, deltaTime }) {
          // Get our 0..1 range value
          const t = playhead;
    
          // 半径20-50
          const radius = lerp(20, 50, t);
    
          // 线宽 20-10
          const lineWidth = lerp(20, 10, t);
    
          // 画圆
          circle(context, width / 2, height / 2, radius, 'white', lineWidth);
        }
      };
    
      canvasSketch(sketch, settings);
    

    参考资料

    逆线性插值

    我们需要20过渡到40的比例是50%,值设置了30

    假设您要对0到100像素之间的滚动位置做出反应。我们称它们为ab。用下面的逆线性插值,你在传递ab以及滚动位置v

    function invlerp(a, b, v) {
      return ( v - a ) / ( b - a )
    }
    

    但是我们会发现返回的值可能会大于1,超过两个极限

    const lerp = (x, y, a) => x * (1 - a) + y * a
    const invlerp = (a, b, v) => clamp(( v - a ) / ( b - a ))
    const clamp = (v, min = 0, max = 1) => Math.min(max, Math.max(min, v))
    

    我自己也是很蒙蔽,直接上案例

    invlerp(20, 40, 20) // 0
    invlerp(20, 40, 30) // 0.5
    

    结果范围20-40结果返回的是0-1

    在小于等于20的时候都是0

    大于等于40的时候都是1

    demo

    决定自己的高度的是你的态度,而不是你的才能

    记得我们是终身初学者和学习者

    总有一天我也能成为大佬

  • 相关阅读:
    Python实现归并排序
    zip解决杨辉三角问题
    Python中协程、多线程、多进程、GIL锁
    Python copy(), deepcopy()
    Python collections的使用
    javascript中的类
    python3中的zip函数
    三数之和(Python and C++解法)
    两数之和(Python and C++解法)
    Python中list、dict、set、tuple的用法细节区别
  • 原文地址:https://www.cnblogs.com/fangdongdemao/p/13986472.html
Copyright © 2020-2023  润新知