Cristina Cochior 5 years ago
parent
commit
a508458f4d
  1. 34
      voicegardens/static/styles.css
  2. 182
      voicegardens/static/voicegardens.js
  3. 4
      voicegardens/templates/about.html

34
voicegardens/static/styles.css

@ -1,57 +1,56 @@
/* Custom CSS styles */ /* Custom CSS styles */
@font-face { @font-face {
font-family: 'Signika Bold'; font-family: "Signika Bold";
src: url('fonts/Signika-Bold.ttf') format('ttf'); src: url("fonts/Signika-Bold.ttf") format("ttf");
font-weight: bold; font-weight: bold;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Signika'; font-family: "Signika";
src: url('fonts/Signika-Regular.ttf') format('ttf'); src: url("fonts/Signika-Regular.ttf") format("ttf");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Rubik'; font-family: "Rubik";
src: url('fonts/Rubik-Bold.ttf') format('ttf'), src: url("fonts/Rubik-Bold.ttf") format("ttf"),
url('fonts/rubik-bold-webfont.woff') format('woff'), url("fonts/rubik-bold-webfont.woff") format("woff"),
url('fonts/rubik-bold-webfont.woff2') format('woff2'); url("fonts/rubik-bold-webfont.woff2") format("woff2");
font-weight: bold; font-weight: bold;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Rubik'; font-family: "Rubik";
src: url('fonts/Rubik-Regular.ttf') format('ttf'); src: url("fonts/Rubik-Regular.ttf") format("ttf");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Rubik'; font-family: "Rubik";
src: url('fonts/Rubik-Italic.ttf') format('ttf'); src: url("fonts/Rubik-Italic.ttf") format("ttf");
font-weight: normal; font-weight: normal;
font-style: italic; font-style: italic;
} }
@font-face { @font-face {
font-family: 'PalanquinDark'; font-family: "PalanquinDark";
src: url('fonts/PalanquinDark-Bold.ttf') format('ttf'); src: url("fonts/PalanquinDark-Bold.ttf") format("ttf");
font-weight: bold; font-weight: bold;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'PalanquinDark'; font-family: "PalanquinDark";
src: url('fonts/PalanquinDark-Regular.ttf') format('ttf'); src: url("fonts/PalanquinDark-Regular.ttf") format("ttf");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
body { body {
height: 100vh; height: 100vh;
margin: 0px; margin: 0px;
@ -177,7 +176,6 @@ div.footer {
right: 25vw; right: 25vw;
bottom: 2vh; bottom: 2vh;
left: unset; left: unset;
} }
.leaf { .leaf {

182
voicegardens/static/voicegardens.js

@ -55,11 +55,9 @@ var shapes = [];
var amplitude; var amplitude;
var duration; var duration;
// random shape positioning // The background colour choices for the environment
var positionTick = false; var bgChoices;
var secondTick = false; var bgColour;
var secondTimer = 0;
var positionTimer = 0;
function record() { function record() {
/** /**
@ -201,7 +199,7 @@ class GeneratedShape {
else this.soundAmplitude = soundAmplitude; else this.soundAmplitude = soundAmplitude;
// mouse hover awareness for sound playing // mouse hover awareness for sound playing
this.hover = false; this.hovering = false;
// The opacity of the shape. This controls whether we can see the shape or // The opacity of the shape. This controls whether we can see the shape or
// not (transparency). It starts at zero as we want to fade the shapes in // not (transparency). It starts at zero as we want to fade the shapes in
@ -216,14 +214,8 @@ class GeneratedShape {
this.accelX = 0.0; this.accelX = 0.0;
this.accelY = 0.0; this.accelY = 0.0;
// The x, y destination values which the shape moves towards. This can be
// calculated against the `mouseX` and `mouseY` values, for example. Then
// the shape will follow the mouse.
this.deltaX = 0.0;
this.deltaY = 0.0;
// The speed at which the shape 'springs' towards its final destination. // The speed at which the shape 'springs' towards its final destination.
this.springing = 0.0009; this.springing = random(0.0006, 0.0009);
// The speed at which the shape rocks back and forth when it is in the // The speed at which the shape rocks back and forth when it is in the
// process of coming to a halt. // process of coming to a halt.
@ -232,7 +224,7 @@ class GeneratedShape {
// Value that controls the tightness or looseness of the curves between the // Value that controls the tightness or looseness of the curves between the
// x,y values of the shape. AFAIK, this value can go between -5 and +5. // x,y values of the shape. AFAIK, this value can go between -5 and +5.
// With +5 we have very sharp curves and edges. // With +5 we have very sharp curves and edges.
this.organicConstant = random(-5, 5); this.organicConstant = 1.0;
// The x,y values which determine where the shape is currently. These are // The x,y values which determine where the shape is currently. These are
// required in order to calculate where the shape is currently so that we // required in order to calculate where the shape is currently so that we
@ -275,15 +267,24 @@ class GeneratedShape {
this.angle = radians(360 / this.edges); this.angle = radians(360 / this.edges);
// ??? // ???
this.centerX = random(windowWidth); this.centerX = random(windowWidth) - toScreenX;
this.centerY = random(windowHeight); this.centerY = random(windowHeight) - toScreenY;
// new destination for the shapes // new destination for the shapes
this.destX = random(windowWidth); this.destX = random(windowWidth);
this.destY = random(windowHeight); this.destY = random(windowHeight);
// the shape that was last collided with // The x, y destination values which the shape moves towards. This can be
this.lastCollidedShape; // calculated against the `mouseX` and `mouseY` values, for example. Then
// the shape will follow the mouse.
this.deltaX = this.destX - this.centerX - toScreenX;
this.deltaY = this.destY - this.centerY - toScreenY;
// time management for timing when to make new random position
// movements
this.drawTimer = 0;
this.nextTick = random(1000, 9000);
this.tickTimer = 0;
this.initialise(); this.initialise();
} }
@ -302,8 +303,8 @@ class GeneratedShape {
// this directly influences the shape of the size alongside the // this directly influences the shape of the size alongside the
// this.radius shape value // this.radius shape value
this.randXs[i] = ceil(this.soundDuration * random(-30, 30)); this.randXs[i] = this.soundDuration * random(-10, 40);
this.randYs[i] = ceil(this.soundDuration * random(-30, 30)); this.randYs[i] = this.soundDuration * random(-10, 40);
} }
for (let i = 0; i < this.edges; i++) { for (let i = 0; i < this.edges; i++) {
@ -324,7 +325,7 @@ class GeneratedShape {
for (let i = 0; i < shapes.length; i++) { for (let i = 0; i < shapes.length; i++) {
let shape = shapes[i]; let shape = shapes[i];
if (this === shape || this.lastCollidedShape === shape) { if (this === shape) {
continue; continue;
} }
@ -338,7 +339,6 @@ class GeneratedShape {
); );
if (collision === true) { if (collision === true) {
this.lastCollidedShape = shape;
return [true, shape]; return [true, shape];
} }
} }
@ -376,14 +376,37 @@ class GeneratedShape {
/** /**
* Choose a colour for the shape. * Choose a colour for the shape.
**/ **/
// TODO: choose nicer colours
// TODO: Can we have gradient colours
// TODO: Can we have multiple colours
let colourChoices = [ let colourChoices = [
color("red"), color("#4F6EE8"),
color("blue"), color("#626788"),
color("green"), color("#334171"),
color("black") color("#1529C2"),
color("#A17AA3"),
color("#606CEB"),
color("#8A77D5"),
color("#EB4913"),
color("#FC6012"),
color("#D94C14"),
color("#F08A60"),
color("#F8988F"),
color("#6E4F47"),
color("#93E35B"),
color("#DE3F16"),
color("#D1611F"),
color("#C22F0A"),
color("#C97814"),
color("#EDA714"),
color("#D5894A"),
color("#448F54"),
color("#61C26F"),
color("#ACE9B2"),
color("#CC25B6"),
color("#D695F0"),
color("#C5C2F0"),
color("#CC3D25"),
color("#A3614E"),
color("#F0DBA9"),
color("#7C4531")
]; ];
let index = floor(random(0, colourChoices.length)); let index = floor(random(0, colourChoices.length));
@ -404,9 +427,27 @@ class GeneratedShape {
for (let i = 0; i < this.edges; i++) { for (let i = 0; i < this.edges; i++) {
curveVertex(this.xs[i], this.ys[i]); curveVertex(this.xs[i], this.ys[i]);
} }
for (let i = 0; i < this.edges - 1; i++) {
curveVertex(this.xs[i], this.ys[i]);
}
endShape(CLOSE); endShape(CLOSE);
} }
tick() {
/**
* Manage internal time for each shape.
**/
this.drawTimer = millis();
if (this.drawTimer >= this.nextTick + this.tickTimer) {
this.tickTimer = millis();
this.nextTick = random(1000, 9000);
return true;
}
return false;
}
draw() { draw() {
/** /**
* Draw the shape vectors. * Draw the shape vectors.
@ -424,6 +465,26 @@ class GeneratedShape {
this.curve(); this.curve();
} }
hover() {
/**
* React to mouse hovering.
**/
let isHovering = collidePointPoly(
mouseX - screenX,
mouseY - screenY,
this.vectors
);
if (isHovering === true) {
if (this.hovering === false) {
this.sound();
this.hovering = true;
}
} else {
this.hovering = false;
}
}
move() { move() {
/** /**
* Move the shape vectors. * Move the shape vectors.
@ -463,33 +524,31 @@ function setup() {
createCanvas(windowWidth, windowHeight); createCanvas(windowWidth, windowHeight);
frameRate(frameRate); frameRate(frameRate);
setupRecording(); setupRecording();
bgChoices = [
color("#F6B2FF"),
color("#F58F6C"),
color("#C3EFDB"),
color("#ADCA95"),
color("#F58F6C"),
color("#A5F1F7"),
color("#FFC266"),
color("#FF66BB"),
color("#F6B2FF"),
color("#CFE4D9")
];
bgColour = bgChoices[floor(random(0, bgChoices.length - 1))];
} }
function draw() { function draw() {
/** /**
* The draw loop which is called x times a second where x is the frameRate. * The draw loop which is called x times a second where x is the frameRate.
**/ **/
background("white"); background(bgColour);
blendMode(BLEND); blendMode(BLEND);
smooth(); smooth();
noStroke(); noStroke();
// count random waiting times in seconds until choosing a new destX, destY
// for a moving shape
let nextPositionTick = random(3000, 8000);
let positionTickingTime = millis();
if (positionTickingTime >= nextPositionTick + positionTimer) {
positionTick = true;
positionTimer = millis();
}
let nextSecondTick = 1000;
let secondTickingTime = millis();
if (secondTickingTime >= nextSecondTick + secondTimer) {
secondTick = true;
secondTimer = millis();
}
// offset the window view based on new values of x,y related to the screen. // offset the window view based on new values of x,y related to the screen.
// These values are generated once the user drags the screen with the mouse. // These values are generated once the user drags the screen with the mouse.
screenX = lerp(screenX, toScreenX, 0.2); screenX = lerp(screenX, toScreenX, 0.2);
@ -509,47 +568,24 @@ function draw() {
for (let i = 0; i < shapes.length; i++) { for (let i = 0; i < shapes.length; i++) {
let shape = shapes[i]; let shape = shapes[i];
// if hovering over the shape, play the recorded sound shape.hover();
let hovering = collidePointPoly( shape.draw();
mouseX - screenX, shape.move();
mouseY - screenY,
shape.vectors
);
if (hovering === true) {
if (shape.hover === false) {
shape.sound();
shape.hover = true;
}
} else {
shape.hover = false;
}
// randomly move the shapes if (shape.tick() === true) {
if (positionTick) {
shape.destX = random(windowWidth); shape.destX = random(windowWidth);
shape.destY = random(windowHeight); shape.destY = random(windowHeight);
// also reset last collided shape
shape.lastCollidedShape = undefined;
} }
shape.draw();
shape.move();
// play recordings when shapes collide // play recordings when shapes collide
let [collision, collidedShape] = shape.collide(shapes); let [collision, collidedShape] = shape.collide(shapes);
if (collision === true) { if (collision === true) {
if (secondTick) {
shape.sound(); shape.sound();
collidedShape.sound(); collidedShape.sound();
} }
} }
} }
// reset random shape position time ticker
positionTick = false;
}
function mouseDragged() { function mouseDragged() {
/** /**
* Mouse drag movement handling. * Mouse drag movement handling.

4
voicegardens/templates/about.html

@ -49,7 +49,7 @@
<p>Kari also plays in the improvisational/experimental band Difficult with Eothan Stearn and Tracy Hanna.</p> <p>Kari also plays in the improvisational/experimental band Difficult with Eothan Stearn and Tracy Hanna.</p>
<h3>4. How the page works</h3> <h3>4. How the page works</h3>
<p>This website is made using mainly <a href="https://flask.palletsprojects.com/en/1.1.x/">flask</a> and <a href="https://p5js.org/">p5js</a>.</p> <p>This website is made using mainly <a href="https://flask.palletsprojects.com/en/1.1.x/">Flask</a> and <a href="https://p5js.org/">P5js</a>.</p>
<p>Users are invited to record their voices speaking or making non-verbal sounds into the site which the software will then translate into visual forms. Audio attributes such as amplitude and duration of sound recordings are translated into the <p>Users are invited to record their voices speaking or making non-verbal sounds into the site which the software will then translate into visual forms. Audio attributes such as amplitude and duration of sound recordings are translated into the
visual properties of size, number of edges, and colour. Users can play with using the different qualities of their voice to create varied and dynamic visualisations. The recordings are then ‘planted’ in the voicegarden (or added to the visual properties of size, number of edges, and colour. Users can play with using the different qualities of their voice to create varied and dynamic visualisations. The recordings are then ‘planted’ in the voicegarden (or added to the
archive). </p> archive). </p>
@ -83,7 +83,7 @@
</p> </p>
<h3>7. Licensing for the code</h3> <h3>7. Licensing for the code</h3>
The code for this website is licensed under <a href="https://www.gnu.org/licenses/agpl-3.0.en.html">AGPL</a> and can be found <a href="https://git.vvvvvvaria.org/varia/voicegardens">here</a>. The code for this website is licensed under the <a href="https://www.gnu.org/licenses/agpl-3.0.en.html">AGPL</a> and can be found <a href="https://git.vvvvvvaria.org/varia/voicegardens">here</a>.
<h3>8. Browser Compatibility</h3> <h3>8. Browser Compatibility</h3>

Loading…
Cancel
Save