7 songs
7 Songs, new and improved! Thank you Niek Reus!
The work called “music” or “7 songs” has become unreadable because of the disappearance of Flash. Niek Reus recreated it for me. He had never seen the work before. He could extract the different sounds, the sounds of the 7 songs, but for the visuals…. We proceeded with words only, description, objective or metaphoric, using email. I didn’t want to re-do the work exactly the way it was, because it was much too small for contemporary screens, it used 12 pixels, based on tiny pink rectangles 3×4 or 4×3 pixels slightly modifying during the time of the song.
Here is one of the last mails. Instead of tiny rectangles I proposed to use the shape of some emojis.
Here is the code with the comments by Niek Reus
<html>
<head>
<title>My music</title>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1″>
<script type=”text/javascript”>
var _gaq = _gaq || [];
_gaq.push([‘_setAccount’, ‘UA-25454047-1’]);
_gaq.push([‘_trackPageview’]);
(function() {
var ga = document.createElement(‘script’); ga.type = ‘text/javascript’; ga.async = true;
ga.src = (‘https:’ == document.location.protocol ? ‘https://ssl’ : ‘http://www’) + ‘.google-analytics.com/ga.js’;
var s = document.getElementsByTagName(‘script’)[0]; s.parentNode.insertBefore(ga, s);
})();
//put the sounds in the right order in an array
var sounds = new Array(“ao”, “hm”, “h”, “oi”, “hu”, “hhh”, “aa”);
//make an array of colors, so that each sound gets an image in the corresponding color
var colors = new Array(“AA7D9F”, “C44883”, “BE2168”, “990000”, “B72B91”, “D3370A”, “E0921D”);
//the appendixes are there to produce the right title for each sound
var appendixes = new Array(“st”, “nd”, “rd”, “th”);
//all images have the same width, but their heights are different, so we put all the heights in an array in the right order
var heights = new Array(“27”, “45”, “23”, “41”, “21”, “42”, “25”);
//process has to be false for the clicking to have any effect, during the music playing process will be true;
var process = false;
//index indicates which item in the array of sounds or array of colors, so in the beginning index = 0
var index = 0;
//duration will indicate the duration of the sound at hand in seconds; duration1 – duration3 indicate the duration of each phase the animation goes through (appearing, resting, disappearing) of the sound at hand
var duration1, duration2, duration3, duration = 0;
//progress is the progress the animation is making after each interval; there are 25 intervals in a second, which means for each phase of the animation the progress = 1/(duration of the phase * 25)
var progress = 0;
//the animation for each sound goes through 3 phases, numbered 0 – 2
var phase = 0;
//at the beginning of each phase phase_progress = 0 and will be augmented by 1 with each interval; that means that by the time phase_progress/progress is 1, the phase comes to an end
var phase_progress = 0;
//intevalID is the object that gets the value of the function setInterval, and is used to end the interval
var intervalID;
//the idea of dividing the duration of a sound into 3 parts to synchronize the animation with the sound is not really working, because in reality the animation of the first phase takes longer than expected; that’s why the real time lapse should be captured to know how long an image is allowed to stay in a resting position; for this we need the variables starttime and thistime
var starttime;
var thistime;
//the variable counter is needed to make the 3rd sound and animation play 3 times
var counter = 0;
//the images are changing color from white into the color they are supposed to get in the rest situation in phase 1; for this we need to transform the hexadecimal color code into a decimal one and back; for this are the functions hexdec and dechex respectively
function hexdec (hexString) {
return parseInt(hexString, 16);
}
function dechex(d, padding) {
var hex = Number(d).toString(16).toUpperCase();
padding = typeof (padding) === “undefined” || padding === null ? padding = 2 : padding;
while (hex.length < padding) {
hex = “0” + hex;
}
return hex;
}
//playSound is called each time somebody clicks the text ‘listen’ or the pink dot
function playSound() {
//only when progress is false something will happen
if (!process) {
process = true;
//the following provides the audio object ‘music’ with the right sound and lets it play
var music = document.getElementById(“music”);
var sound = sounds[index]+”.wav”;
music.setAttribute(“src”, sound);
music.play();
//the following sets the title of the web page right
var number = index+1;
if (number==7) number = “last”;
if (number<4) appendix = appendixes[index];
else if (number<7) appendix = appendixes[3];
else appendix = “”;
document.title = “My “+number+appendix+” interactive song”;
//the function getDuration is called to get the duration of the sound at hand
music.oncanplay = function() {
getDuration(this);
}
}
}
//getDuration() is meant to get the duration of each sound and to start the interval for shaping
function getDuration(music) {
duration = music.duration;
startShaping();
}
//startShaping sets the values of duration1 – duration3, the value of progress during duration1, makes a notation of the time at the start of the interval and starts the interval for shaping
function startShaping() {
duration3 = duration/3;
if (duration3>0.4) duration3 = 0.4;
duration1 = (duration-duration3)*0.67;
duration2 = duration-duration1-duration3;
progress = 1/(duration1*25);
starttime = new Date();
intervalID = setInterval(“shaping()”, 40);
}
function shaping() {
//to get the height of the image at hand
var height = heights[index];
//at each interval get the actual time to figure out how much time has passed since the beginning of the shaping process
if (phase<2) {
thistime = new Date();
var difference = thistime-starttime;
}
if (phase==0) {
//during phase=0 the image is appearing
//the following makes the color of the image change during phase=0 from white to the color that it is meant to have
var startcolor = hexdec(“FF”);
var endcolor = colors[index];
var endcolorR = hexdec(endcolor.substr(0, 2));
var endcolorG = hexdec(endcolor.substr(2, 2));
var endcolorB = hexdec(endcolor.substr(4, 2));
var colorprogressR = Math.round(startcolor-(phase_progress*progress*(startcolor-endcolorR)));
var colorprogressG = Math.round(startcolor-(phase_progress*progress*(startcolor-endcolorG)));
var colorprogressB = Math.round(startcolor-(phase_progress*progress*(startcolor-endcolorB)));
var colorprogress = “#”+dechex(colorprogressR)+dechex(colorprogressG)+dechex(colorprogressB);
console.log(colorprogress);
//blurprogress is the amount of blur of the image during phase=0 going from 22 to 2
var blurprogress = 22-20*phase_progress*progress;
//opacity is the amount of opacity of the image during phase=0 going from 0 – 1
var opacity = phase_progress*progress;
//opacity2, going from 1 – 0, indicates the opacity of the text ‘listen’ or of the pink dot
var opacity2 = 1-opacity;
//with each interval phase_progress is augmented by 1
phase_progress++;
//the element ‘nextshape’ gets the image at hand as background and all the properties to make the image look the right way
//the element ‘nav’ contains the text ‘listen’ or the pink dot and becomes more and more transparent
document.getElementById(“nextshape”).style.filter = “blur(“+blurprogress+”px)”;
document.getElementById(“nextshape”).style.background = “url(shape”+index+”.png) no-repeat “+colorprogress;
document.getElementById(“nextshape”).style.height = height+”px”;
document.getElementById(“nav”).style.opacity = opacity2;
//the function transform is called to give each image its own transformation during phase=0
transform(index);
//the introduction text should disappear during playing of the first sound
if (index==0) document.getElementById(“text”).style.opacity = opacity2;
//if phase_progress*progress is 1 then we should move on to the next phase
if (phase_progress*progress>=1) {
//we set phase_progress to 0, progress to 1/(duration2*25) and phase gets the value 1
phase_progress = 0;
progress = 1/(duration2*25);
phase++;
//the element ‘nav’ gets the image at hand and all the properties that go with it
document.getElementById(“nav”).style.width = “30px”;
document.getElementById(“nav”).style.height = height+”px”;
document.getElementById(“nav”).style.opacity = 1;
document.getElementById(“nav”).style.background = “url(shape”+index+”.png) no-repeat #”+colors[index];
document.getElementById(“nav”).style.filter = “blur(2px)”;
document.getElementById(“nav”).innerHTML = “”;
//the element ‘nextshape’ gets the image ‘dot’ and all the properties that go with it
document.getElementById(“nextshape”).style.filter = “blur(0)”;
document.getElementById(“nextshape”).style.backgroundColor = “transparent”;
document.getElementById(“nextshape”).style.opacity = 0;
document.getElementById(“nextshape”).innerHTML = “<img src=’dot.png’ />”;
document.getElementById(“nextshape”).style.width = “10px”;
document.getElementById(“nextshape”).style.height = “10px”;
}
}
if (phase==1) {
//during phase=1 the image is resting
//so with each interval phase_progress is augmented by 1
phase_progress++;
//if difference is equal to or bigger than duration1+duration2 in seconds or phase_progress*progress is 1 or more, we move on to the next phase
if (difference>=(duration1+duration2)*1000 || phase_progress*progress>=1) {
phase_progress = 0;
progress = 1/(duration3*25);
phase++;
}
}
if (phase==2) {
//the following makes the image sharper and sharper and at the same time smaller and smaller
var blurprogress = 2-2*phase_progress*progress; //the blur of the shape
var navbreedte = 30-40*phase_progress*progress;
var navhoogte = (navbreedte*height)/30;
console.log(“navhoogte “+index+”: “+navhoogte);
//the opacity of the dot goes to 1
var opacity = phase_progress*progress;
//the opacity of the image goes to 0
var opacity2 = 1-opacity;
//at the start the image has its own color, but during the process moves to the pink color of the dot (color endcolor: “#FF6EC7”)
var startcolor = colors[index];
var endcolor = “FF6EC7”;
//the following takes care of the transition from own color to dot color
var startcolorR = hexdec(startcolor.substr(0, 2));
var endcolorR = hexdec(endcolor.substr(0, 2));
var startcolorG = hexdec(startcolor.substr(2, 2));
var endcolorG = hexdec(endcolor.substr(2, 2));
var startcolorB = hexdec(startcolor.substr(4, 2));
var endcolorB = hexdec(endcolor.substr(4, 2));
var colorprogressR = Math.round(startcolorR-(phase_progress*progress*(startcolorR-endcolorR)));
var colorprogressG = Math.round(startcolorG-(phase_progress*progress*(startcolorG-endcolorG)));
var colorprogressB = Math.round(startcolorB-(phase_progress*progress*(startcolorB-endcolorB)));
console.log (“CB: “+colorprogressB);
var colorprogress = “#”+dechex(colorprogressR)+dechex(colorprogressG)+dechex(colorprogressB);
phase_progress++;
//in the following the elements “nextshape and “nav” get all the properties that have been established in the previous code
document.getElementById(“nextshape”).style.opacity = opacity;
document.getElementById(“nav”).style.background = “url(shape”+index+”.png) “+colorprogress;
document.getElementById(“nav”).style.filter = “blur(“+blurprogress+”px)”;
document.getElementById(“nav”).style.opacity = opacity2;
document.getElementById(“nav”).style.width = navbreedte+”px”;
document.getElementById(“nav”).style.height = navhoogte+”px”;
//when phase_progress*progress reach 1 the image of “nav” will be the pink dot and “nextshape” will be transparant
if (phase_progress*progress>=1) {
document.getElementById(“nav”).innerHTML = “<img src=’dot.png’ />”;
document.getElementById(“nav”).style.backgroundColor = “transparent”;
document.getElementById(“nav”).style.opacity = 1;
document.getElementById(“nav”).style.width = “10px”;
document.getElementById(“nav”).style.height = “10px”;
document.getElementById(“nextshape”).style.background = “url(shape”+index+”.png) no-repeat #FFFFFF”;
document.getElementById(“nextshape”).style.width = “30px”;
document.getElementById(“nextshape”).style.height = “30px”;
document.getElementById(“nextshape”).innerHTML = “”;
//phase will be 0, so that the process will again start there when the dot is clicked on
phase = 0;
//phase_progress will again be 0
phase_progress = 0;
//process now is false so that something will happen when the pink dot is clicked on
process = false;
//the interval is cleared
clearInterval(intervalID);
//to make the 3d image play 3 times when index is 2, the variable counter is augmented by 1 as long counter < 2
//otherwise index is augmented by i as long the end of the array of sounds is not reached
if (index==2 && counter<2) {
counter++;
}
else {
if (index<sounds.length-1) index++;
}
}
}
document.getElementById(“nav”).style.backgroundSize = “contain”;
document.getElementById(“nextshape”).style.backgroundSize = “contain”;
document.getElementById(“nav”).style.backgroundPosition = “center center”;
document.getElementById(“nextshape”).style.backgroundPosition = “center center”;
document.getElementById(“nav”).style.backgroundRepeat = “no-repeat”;
document.getElementById(“nextshape”).style.backgroundRepeat = “no-repeat”;
}
//the function transform gives each image its own way of appearing
function transform(thisindex) {
var translate = “translate(-50%, -50%) “;
switch (thisindex) {
case 0 :
var deg = 2160*Math.abs(Math.sin(Math.PI*phase_progress*progress/2));
document.getElementById(“nextshape”).style.transform = translate+”rotate(“+deg+”deg)”;
break;
case 1 :
document.getElementById(“nextshape”).style.transform = translate+”rotateX(“+Math.round(720*phase_progress*progress)+”deg)”;
break;
case 3 :
var deg = 720*Math.abs(Math.sin(Math.PI*phase_progress*progress/2));
document.getElementById(“nextshape”).style.transform = translate+”rotateY(“+deg+”deg)”;
break;
case 4 :
document.getElementById(“nextshape”).style.transform = translate+”skew(“+Math.round(720*phase_progress*progress)+”deg, “+Math.round(720*phase_progress*progress)+”deg)”;
break;
case 5 :
document.getElementById(“nextshape”).style.transform = translate+”skewX(“+Math.round(720*phase_progress*progress)+”deg)”;
break;
case 6 :
var scale = Math.cos(Math.PI*4*phase_progress*progress);
document.getElementById(“nextshape”).style.transform = translate+”scale(“+scale+”)”;
}
}
</script>
<style>
body {
background-color:#FFFFFF;
color:#FF66CC;
font-family:Arial, Helvetica, sans-serif;
font-size:13px;
overflow:hidden;
}
a {
text-decoration:none;
}
#text {
width:250px;
/*margin:40px auto;*/
position:absolute;
top:50%;
left:50%;
transform:translate(-50%,-140%);
font-size:11px;
color:#FF6CFF/*#FF6EC7;*/
}
#nav {
text-align:center;
font-weight:bold;
width:30px;
height:30px;
color:#6666FF;
z-index:2;
filter:blur(0);
}
#nav, #nextshape {
position:absolute;
left:50%;
top:50%;
transform:translate(-50%, -50%);
cursor:pointer;
background-position: center center;
background-repeat:no-repeat;
background-size:cover;
}
#nextshape {
z-index:1;
width:30px;
height:30px;
}
#nav img {
opacity:1;
}
#imgshape {
/*filter:blur(20px);
opacity:1;*/
margin:0 auto;
}
.soundshape {
width:30px;
height:30px;
display:none;
}
.shape {
width:100%;
height:100%;
background-color:#FF6EC7;
}
#dot {
width:10px;
height:10px;
border-radius:5px;
background-color:#FF6EC7;
}
img {
max-width:100%;
height:100%;
}
@media screen and (max-height:470px) {
#text {
width:450px;
}
}
</style>
</head>
<body>
<audio id=”music”>
</audio>
<div id=”text”>
You have always known me as a web superstar, but now you will discover me as a pop singer. I made music and I composed these 7 songs for you.
<br />They have no words, no title, but I am sure you will understand their meaning. As tiny as they are, each of them is a complete song, a whole piece of interactive music which you can also see and touch. Their interaction is not so much in the mouse clicks than in your own reactions.
<br />The last of these 7 songs will be my very last song. You may recall it, play it again, but it will link you nowhere. Its lack of interaction will leave you alone with your own reactions.
</div>
<div id=”nav” onClick=”playSound()”>listen</div>
<div id=”nextshape”></div>
</body>
</html>