Cristina Cochior 4 years ago
parent
commit
a508458f4d
  1. 164
      voicegardens/static/styles.css
  2. 186
      voicegardens/static/voicegardens.js
  3. 6
      voicegardens/templates/about.html

164
voicegardens/static/styles.css

@ -1,57 +1,56 @@
/* Custom CSS styles */
@font-face {
font-family: 'Signika Bold';
src: url('fonts/Signika-Bold.ttf') format('ttf');
font-weight: bold;
font-style: normal;
font-family: "Signika Bold";
src: url("fonts/Signika-Bold.ttf") format("ttf");
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'Signika';
src: url('fonts/Signika-Regular.ttf') format('ttf');
font-weight: normal;
font-style: normal;
font-family: "Signika";
src: url("fonts/Signika-Regular.ttf") format("ttf");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'Rubik';
src: url('fonts/Rubik-Bold.ttf') format('ttf'),
url('fonts/rubik-bold-webfont.woff') format('woff'),
url('fonts/rubik-bold-webfont.woff2') format('woff2');
font-weight: bold;
font-style: normal;
font-family: "Rubik";
src: url("fonts/Rubik-Bold.ttf") format("ttf"),
url("fonts/rubik-bold-webfont.woff") format("woff"),
url("fonts/rubik-bold-webfont.woff2") format("woff2");
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'Rubik';
src: url('fonts/Rubik-Regular.ttf') format('ttf');
font-weight: normal;
font-style: normal;
font-family: "Rubik";
src: url("fonts/Rubik-Regular.ttf") format("ttf");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'Rubik';
src: url('fonts/Rubik-Italic.ttf') format('ttf');
font-weight: normal;
font-style: italic;
font-family: "Rubik";
src: url("fonts/Rubik-Italic.ttf") format("ttf");
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: 'PalanquinDark';
src: url('fonts/PalanquinDark-Bold.ttf') format('ttf');
font-weight: bold;
font-style: normal;
font-family: "PalanquinDark";
src: url("fonts/PalanquinDark-Bold.ttf") format("ttf");
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: 'PalanquinDark';
src: url('fonts/PalanquinDark-Regular.ttf') format('ttf');
font-weight: normal;
font-style: normal;
font-family: "PalanquinDark";
src: url("fonts/PalanquinDark-Regular.ttf") format("ttf");
font-weight: normal;
font-style: normal;
}
body {
height: 100vh;
margin: 0px;
@ -70,48 +69,48 @@ img.button {
}
.record {
position:fixed;
top:20px;
left:20px;
position: fixed;
top: 20px;
left: 20px;
}
.record:hover {
top:22px;
left:22px;
top: 22px;
left: 22px;
}
.stop {
position:fixed;
top:100px;
left:20px;
position: fixed;
top: 100px;
left: 20px;
}
.stop:hover {
top:102px;
left:22px;
top: 102px;
left: 22px;
}
.leaf {
position:fixed;
top:180px;
left:20px;
position: fixed;
top: 180px;
left: 20px;
}
.leaf:hover {
top:182px;
left:22px;
top: 182px;
left: 22px;
}
.about {
width: 3% !important;
position:fixed;
top:260px;
left:20px;
position: fixed;
top: 260px;
left: 20px;
}
.about:hover {
top:262px;
left:22px;
top: 262px;
left: 22px;
}
.about-text {
@ -129,11 +128,11 @@ h1 {
}
.backtoindex img {
width: 10%;
margin: 0 auto !important;
margin-left: 20vw;
padding: 3em 2em 0 10em;
float: left;
width: 10%;
margin: 0 auto !important;
margin-left: 20vw;
padding: 3em 2em 0 10em;
float: left;
}
.button.button-about {
@ -161,15 +160,15 @@ div.footer {
@media screen and (max-width: 770px) {
img.button {
width: 10%;
}
}
.about {
width: 7% !important;
top: unset;
right: 25vw;
bottom: 2vh;
left: unset;
}
width: 7% !important;
top: unset;
right: 25vw;
bottom: 2vh;
left: unset;
}
.about:hover {
width: 7% !important;
@ -177,43 +176,42 @@ div.footer {
right: 25vw;
bottom: 2vh;
left: unset;
}
}
.leaf {
top: unset;
bottom: 3vh;
left: 55vw;
top: unset;
bottom: 3vh;
left: 55vw;
}
.leaf:hover {
top: unset;
bottom: 3vh;
left: 55vw;
top: unset;
bottom: 3vh;
left: 55vw;
}
.stop {
top: unset;
bottom: 3vh;
left: 40vw;
top: unset;
bottom: 3vh;
left: 40vw;
}
.stop:hover {
top: unset;
bottom: 3vh;
left: 40vw;
top: unset;
bottom: 3vh;
left: 40vw;
}
.record {
top: unset;
bottom: 3vh;
left: 25vw;
top: unset;
bottom: 3vh;
left: 25vw;
}
.record:hover {
top: unset;
bottom: 3vh;
left: 25vw;
top: unset;
bottom: 3vh;
left: 25vw;
}
.about-text {

186
voicegardens/static/voicegardens.js

@ -55,11 +55,9 @@ var shapes = [];
var amplitude;
var duration;
// random shape positioning
var positionTick = false;
var secondTick = false;
var secondTimer = 0;
var positionTimer = 0;
// The background colour choices for the environment
var bgChoices;
var bgColour;
function record() {
/**
@ -201,7 +199,7 @@ class GeneratedShape {
else this.soundAmplitude = soundAmplitude;
// 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
// 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.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.
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
// process of coming to a halt.
@ -232,7 +224,7 @@ class GeneratedShape {
// 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.
// 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
// 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.centerX = random(windowWidth);
this.centerY = random(windowHeight);
this.centerX = random(windowWidth) - toScreenX;
this.centerY = random(windowHeight) - toScreenY;
// new destination for the shapes
this.destX = random(windowWidth);
this.destY = random(windowHeight);
// the shape that was last collided with
this.lastCollidedShape;
// 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 = 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();
}
@ -302,8 +303,8 @@ class GeneratedShape {
// this directly influences the shape of the size alongside the
// this.radius shape value
this.randXs[i] = ceil(this.soundDuration * random(-30, 30));
this.randYs[i] = ceil(this.soundDuration * random(-30, 30));
this.randXs[i] = this.soundDuration * random(-10, 40);
this.randYs[i] = this.soundDuration * random(-10, 40);
}
for (let i = 0; i < this.edges; i++) {
@ -324,7 +325,7 @@ class GeneratedShape {
for (let i = 0; i < shapes.length; i++) {
let shape = shapes[i];
if (this === shape || this.lastCollidedShape === shape) {
if (this === shape) {
continue;
}
@ -338,7 +339,6 @@ class GeneratedShape {
);
if (collision === true) {
this.lastCollidedShape = shape;
return [true, shape];
}
}
@ -376,14 +376,37 @@ class GeneratedShape {
/**
* Choose a colour for the shape.
**/
// TODO: choose nicer colours
// TODO: Can we have gradient colours
// TODO: Can we have multiple colours
let colourChoices = [
color("red"),
color("blue"),
color("green"),
color("black")
color("#4F6EE8"),
color("#626788"),
color("#334171"),
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));
@ -404,9 +427,27 @@ class GeneratedShape {
for (let i = 0; i < this.edges; 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);
}
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 the shape vectors.
@ -424,6 +465,26 @@ class GeneratedShape {
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 the shape vectors.
@ -463,33 +524,31 @@ function setup() {
createCanvas(windowWidth, windowHeight);
frameRate(frameRate);
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() {
/**
* The draw loop which is called x times a second where x is the frameRate.
**/
background("white");
background(bgColour);
blendMode(BLEND);
smooth();
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.
// These values are generated once the user drags the screen with the mouse.
screenX = lerp(screenX, toScreenX, 0.2);
@ -509,45 +568,22 @@ function draw() {
for (let i = 0; i < shapes.length; i++) {
let shape = shapes[i];
// if hovering over the shape, play the recorded sound
let hovering = collidePointPoly(
mouseX - screenX,
mouseY - screenY,
shape.vectors
);
if (hovering === true) {
if (shape.hover === false) {
shape.sound();
shape.hover = true;
}
} else {
shape.hover = false;
}
shape.hover();
shape.draw();
shape.move();
// randomly move the shapes
if (positionTick) {
if (shape.tick() === true) {
shape.destX = random(windowWidth);
shape.destY = random(windowHeight);
// also reset last collided shape
shape.lastCollidedShape = undefined;
}
shape.draw();
shape.move();
// play recordings when shapes collide
let [collision, collidedShape] = shape.collide(shapes);
if (collision === true) {
if (secondTick) {
shape.sound();
collidedShape.sound();
}
shape.sound();
collidedShape.sound();
}
}
// reset random shape position time ticker
positionTick = false;
}
function mouseDragged() {

6
voicegardens/templates/about.html

@ -13,7 +13,7 @@
<div class="about-text">
<h1>Kari Robertson<br>
<i>Wet Signal Voice Gardens</i></h1>
<i>Wet Signal Voice Gardens</i></h1>
<h3>1. Key</h3>
@ -49,7 +49,7 @@
<p>Kari also plays in the improvisational/experimental band Difficult with Eothan Stearn and Tracy Hanna.</p>
<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
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>
@ -83,7 +83,7 @@
</p>
<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>

Loading…
Cancel
Save