Skip to content

Instantly share code, notes, and snippets.

@aerrity
Last active August 23, 2022 20:37
Show Gist options
  • Save aerrity/bd98a26070b9db55a809c8bc1a4eb8e4 to your computer and use it in GitHub Desktop.
Save aerrity/bd98a26070b9db55a809c8bc1a4eb8e4 to your computer and use it in GitHub Desktop.
P5.js, Node, Express & MongoDB: Circle update demo

Demonstration combining client-side P5.js with server-side Node, Express and MongoDB.

Each time the canvas is clicked a circle is moved to, and drawn at, the position of the mouse. The circle's position is stored in a MongoDB collection and updated each time the mouse is clicked. On startup and once every second thereafter, the circle's coordinates are retrieved from the MongoDB collection circles.

Project setup and structure is similar to the previous button click example. The one key change is that this example requires an additional npm dependecy to be installed.

npm install body-parser --save

This is used to parse the x and y coords that are sent from the client to the server in the body of a HTTP PUT request.

Example output (client on left, node/express server on top-right, MongoDB view in Compass on bottom-right):

Example output

let myCircle;
function setup() {
createCanvas(400, 400);
background(0);
// retrieve the x, y coords from the DB
fetch('/circle', {method: 'GET'})
.then(function(response) {
if(response.ok) return response.json();
throw new Error('Request failed.');
})
.then(function(data) {
if(data) {
// create a circle at the x, y coords
myCircle = new Circle(data.x, data.y);
}
else {
myCircle = new Circle(0, 0);
}
})
.catch(function(error) {
console.log(error);
});
}
function draw() {
background(0);
if(myCircle) myCircle.draw();
}
function mousePressed() {
// make sure the circle has been created
if(myCircle) {
// redraw the circle at the position that was clicked
myCircle.x = mouseX;
myCircle.y = mouseY;
// update the DB with the new coords
saveCircleCoords(myCircle.x, myCircle.y);
}
}
function saveCircleCoords(newX, newY) {
fetch('/circle', {
method: 'PUT',
body: JSON.stringify({x: newX, y: newY}),
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
})
.then(function(response) {
if(response.ok) {
console.log('Coords were updated in the DB.');
return;
}
throw new Error('Request failed.');
})
.catch(function(error) {
console.log(error);
});
}
// poll the DB every 1 sec to get the stored x, y coords
// note: this is a demo of how to retrieve data from mongodb, in a real system it might make more sense to send these updates via something like Socket.io to avoid the need for polling
setInterval(function() {
fetch('/circle', {method: 'GET'})
.then(function(response) {
if(response.ok) return response.json();
throw new Error('Request failed.');
})
.then(function(data) {
myCircle.x = data.x;
myCircle.y = data.y;
})
.catch(function(error) {
console.log(error);
});
}, 1000);
// 'blueprint' for our circle objects
class Circle {
constructor(x, y) {
this.x = x;
this.y = y;
this.r = 50;
}
draw() {
stroke(255);
strokeWeight(3);
ellipse(this.x, this.y, this.r);
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>p5.js with Node, Express + MongoDB</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.14/p5.min.js"></script>
<script src="client.js"></script>
<style>
body {
margin:0;
padding:0;
overflow: hidden;
}
canvas {
margin:auto;
}
</style>
</head>
<body>
</body>
</html>
console.log('Server-side code running');
const express = require('express');
const bodyparser = require('body-parser');
const MongoClient = require('mongodb').MongoClient;
const app = express();
// serve files from the public directory
app.use(express.static('public'));
// needed to parse JSON data in the body of POST requests
app.use(bodyparser.json());
// connect to the db and start the express server
let db;
const url = 'mongodb://localhost:27017/p5';
MongoClient.connect(url, (err, database) => {
if(err) {
return console.log(err);
}
db = database;
// start the express web server listening on 8080
app.listen(8080, () => {
console.log('listening on 8080');
});
});
// serve the homepage
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
// after receiving a PUT request, update the database with
// the new x, y coords in the request body
app.put('/circle', (req, res) => {
console.log('Data received: ' + JSON.stringify(req.body));
db.collection('circles').update({}, req.body, {upsert: true}, (err, result) => {
if (err) {
return console.log(err);
}
});
res.sendStatus(200); // respond to the client indicating everything was ok
});
// respond to GET requests with x, y coords from DB
app.get('/circle', (req, res) => {
db.collection('circles').findOne({}, (err, result) => {
if (err) return console.log(err); // log if error occurs
if(!result) return res.send({x: 0, y: 0}); // if no data in the DB return (0,0)
res.send(result); // if neither of the above, send the (x,y) from the DB
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment