javascript - 在正弦波上平移 Canvas 中的像素

标签 javascript html canvas

我正在尝试在我的 Canvas 上创建图像失真效果,但似乎什么也没有发生。这是我的代码:

self.drawScreen = function (abilityAnimator, elapsed) {
    if (!self.initialized) {
        self.initialized = true;
        self.rawData = abilityAnimator.context.getImageData(self.targetX, self.targetY, self.width, self.height);
        self.initialImgData = self.rawData.data;
    }
    abilityAnimator.drawBackground();
    self.rawData = abilityAnimator.context.getImageData(self.targetX, self.targetY, self.width, self.height);
    var imgData = self.rawData.data, rootIndex, translationIndex, newX;
    for (var y = 0; y < self.height; y++) {
        for (var x = 0; x < self.width; x++) {
            rootIndex = (y * self.height + x) * 4;
            newX = Math.ceil(self.amplitude * Math.sin(self.frequency * (y + elapsed)));
            translationIndex = (y * self.width + newX) * 4;
            imgData[translationIndex + 0] = self.initialImgData[rootIndex + 0];
            imgData[translationIndex + 1] = self.initialImgData[rootIndex + 1];
            imgData[translationIndex + 2] = self.initialImgData[rootIndex + 2];
            imgData[translationIndex + 3] = self.initialImgData[rootIndex + 3];
        }
    }
    abilityAnimator.context.putImageData(self.rawData, self.targetX, self.targetY);
};

abilityAnimator 是我的 Canvas 对象的包装器:

abilityAnimator.context = //canvas.context
abilityAnimator.drawBackground = function(){ 
    this.canvas.width = this.canvas.width; 
}

elapsed 是自动画开始以来的毫秒数(elapsed 始终 <= 2000) 我的成员变量具有以下值:

self.width = 125;
self.height = 125;
self.frequency = 0.5;
self.amplitude = self.width / 4;
self.targetX = //arbitrary value within canvas
self.targetY = //arbitrary value within canvas

只要没有正弦函数,我就可以很容易地将图像向右平移,但是,引入这些行:

newX = Math.ceil(self.amplitude * Math.sin(self.frequency * (y + elapsed)));
translationIndex = (y * self.width + newX) * 4;

根本不渲染任何内容。平移索引看起来不是很奇怪,正弦函数的性质应该保证偏移不大于125/4 像素。

最佳答案

您使用 sin 的公式是错误的,频率太高会被视为噪声。
建立正弦曲线的典型公式是:

res = sin ( 2 * PI * frequency * time ) ;

其中频率以 Hz 为单位,时间以 s 为单位。 所以在 js 中将转换为:

res = Math.sin (  2 * Math.PI * f * time_ms * 1e-3 ) ;

你显然可以只计算一次常数因子:

 self.frequency = 0.5 * (  2 * Math.PI * 1e-3 );
 // then use
  res = Math.sin (  self.frequency * time_ms ) ; 

所以你看你快了 1000 倍。

第二期: 现在您的时间频率确定了,让我们修复您的空间频率:当将时间频率乘以 y 时,您相当于添加了苹果和猫。
要构建公式,假设您想在 Canvas 的高度范围内跨越 n 次 2*PI。
所以:

spatialFrequency = ( n ) * 2 * Math.PI / canvasHeight ;

你的公式变成了:

res = Math.sin (  self.frequency * time_ms + spatialFrequency * y ) ; 

您可以使用我制作的这个 jsbin 来尝试各种值,这样您就可以看到效果:

http://jsbin.com/ludizubo/1/edit?js,output

enter image description here

关于javascript - 在正弦波上平移 Canvas 中的像素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23847187/

相关文章:

javascript - 如何使用 JavaScript 禁用所有内联样式?

javascript - 第二次点击时文本卡住

javascript - IOS Safari 中的 HTML5 : Manually "playing" a video inside a canvas,

javascript - 使用 JavaScript 和 Canvas 绘制形状

javascript - Webpack(2) - 延迟加载文件时未定义 'Promise'

css - 语义 ui 边栏实现

javascript - 在 Vue.js 应用程序中使用一个组件中的代码(函数/模板)到另一个没有直接关系的组件中

html - span 不会在 mozilla 的按钮内保持垂直居中

javascript - node.js/backbone.js 应用程序加载配置文件设置

javascript - 是否可以使用 office 加载项复制 excel 公式?