An Introduction To Programming With Processing
Mapping ValuesNow that we have the slider moving correctly we can use the values of buttonXPos and map them to any values that we choose, for example we could map the range of values that buttonXPos returns to the amount we would like an image to scale on it's X axis, how far or fast an image moves across the screen, or just about anything that can accept a range of values as an input. We're going to map the buttonXPos range to the tint of an image, making the image appear to fade in from black. Mapping one range of values to another is done with the map() function. The map() function accepts parameters in the following format:
map(mValue, oldLow, oldHigh, newLow, newHigh);The parameter mValue is the value that you will be mapping to the new range, in our case this is buttonXPos. The parameters oldLow and oldHigh are the minimum and maximum values of the range you would like to map to the new range, in other words these values are the furtherest left we can drag the slider button (oldLow) or expressed within the context of our program:
The oldHigh value is the maximum value of the original range, and in the context of our program:
width/2 - sliderBk.width/2
You might have noticed, by now that these two values are the exact expressions we used to determine the minimum and maximum values for the constrain() function assigned to buttonXPos, this is no coincidence. These two values determined the maximum range of the sliders movement and this is the exact range we are mapping to a new range. The new range will be represented by the two parameters newLow and newHigh and in our case these are two simple numbers 0 and 255 respectively. As we are mapping the slider button's movement to the tinting of an image via the tint() function we will be using the single value that is returned from the map() function which will be between the newLow and newHigh parameters in order to create the impression of the image fading in from black. In the context of the actual values, 0 to 255 represent the range of values that the tint() function uses to tint the image with various levels of gray. For example the value 0 has the effect of making an image appear as fully gray (or black) and 255 has the effect of making an image appear with no gray and no black tint. With the slider button's values converted to the correct range of values, all that is left to do is link the new values to the image. In order to do this we will start by declaring a new variable in the global scope. Add the following variable to your sketch:
width/2 + sliderBk.width/2 – sliderFd.width
As you can see this variable is datatyped as float, this is because the map() function returns floats. Remember that this does not mean that the parameters themselves have to be floats, nonetheless it is worth noting that in order to perform true division if the parameters you supply Processing with for the map() function are of type int Processing will typecast them to floats for the purpose of the map() function. What this means is that once those values have been evaluated by the map() function, the answer will be returned as a float. Since this is the variable that we will assign the return value of the map() function to, and as just stated this value will be a float it makes sense to datatype this variable as a float. If we try to use another datatype, such as an int, we will get a “type miss-match” error. With our new variable, imgTint, we will use assignment in the if() structure we created earlier within the draw() function, to determine it's value as the slider is dragged. Add the following statement to the if() structure, directly under the assignment statement for buttonXPos:
In the previous statement we use the map() function to determine the value of the imgTint variable. Now that we have a place to store this value we can associate it with the tint() function. Which we will do before the image() function to render img. We do this by adding the following statement:
imgTint = map(buttonXPos, width/2 - sliderBk.width/2, width/2 + sliderBk.width/2 - sliderFd.width, 0, 255);
This statement must precede the statement telling Processing to render the img object. If you were to run the sketch at this point you might notice that everything is working, but not quite as expected. The answer to this problem is order. If you look at the current sketch it runs like so.#
Although this method might be somewhat functional, it's not very intuitive. What this means is that when the user drags the slider the user should be able to see the results of their actions in realtime (another way of saying immediately or something very close to that) and when the user releases the mouse button, the values should stay as the user set them and not jump around to seemingly incorrect values. As a result we need to make sure that the images are being rendered for all possible situations using the correct values, which in our case is only two different branches. So we are going to restructure our code to accommodate for a more intuitively designed interface.
How this new structure is implemented in our program will follow this pattern:
buttonXPos //update variable imgTint //update variable tint() //set the tint value img //render main image now effected by tint noTint() //Turn tint off so slider images are not effected by it sliderBk //render slider background image sliderFd //render slider button image
This is the order within the first control structure of the if else structure the second control structure will follow the same order. For a full listing of the code it's best to look at the sketch itself which is named slider.pde.
Finally to end off the example I've added another image to the sketch which I've associated with the object called star and mapped it's Y movement to the slider. Like I said the mapping of one value with a range to another range can lead to an infinite array of possibilities, and is largely the premise on which more complex applications are built upon. Why not try your own custom mappings you'll soon come to realize that with this simple function, the sky is definitely not the limit.