線性插值編寫視覺化程式碼
阿新 • • 發佈:2020-11-16
線性插值
處於創意編碼,遊戲開發,資料視覺化和生成創意的功能
[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畫素之間的滾動位置做出反應。我們稱它們為a
和b
。用下面的逆線性插值,你在傳遞a
,b
以及滾動位置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