2014-05-24 2 views
1

J'essaie de créer un effet de distorsion d'image sur ma toile, mais rien ne semble se produire. Voici mon code:Traduction de pixels dans un canevas sur une onde sinusoïdale

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 est un emballage pour mon objet toile:

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

elapsed est tout simplement le nombre de millisecondes depuis l'animation a commencé (écoulé est toujours < = 2000) Mon membre les variables ont les valeurs suivantes:

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 

Je peux traduire l'image vers la droite très facilement ong comme il n'y a pas de fonction sinusoïdale, cependant, l'introduction de ces lignes:

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

Causes rien à rendre du tout. Les index de traduction ne semblent pas très étranges, et la nature de la fonction sinusoïdale devrait garantir que le décalage ne dépasse pas 125/4 pixels.

Répondre

2

Votre formule utilisant le péché est fausse, la fréquence sera si élevée qu'elle sera considérée comme du bruit.
La formule typique pour construire une sinusoïde est:

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

où la fréquence en Hz et est de temps en s. Ainsi, dans js qui se traduirait par:

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

vous pouvez évidemment calculer une fois le facteur constant:

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

Vous vous étiez en 1000 fois trop vite.

Deuxième question: Maintenant que vous avez votre fréquence de temps ok, nous allons fixer votre fréquence spatiale: en multipliant la fréquence de temps par y, vous avez tout à fait d'ajouter des pommes et des chats.
Pour construire la formule, pensez que vous voulez traverser n fois 2 * PI pendant la hauteur de la toile.
donc:

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

et votre formule devient:

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

Vous pouvez jouer avec différentes valeurs avec ce jsbin je l'ai fait afin que vous puissiez visualiser l'effet:

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

enter image description here

+0

Cet outil a été très utile, merci pour la référence! – jokulmorder

+0

@jokulmorder: Je suis content que ce jsbin que j'ai fait puisse vous aider à décider des bonnes valeurs pour votre effet. N'hésitez pas à poster ici si vous avez une version en ligne de votre effet de retouche d'image !! – GameAlchemist

Questions connexes