Skip to content
Permalink
Browse files

Add pusher whiteboard example (#468)

* add pusher whiteboard example

* add readme

* rename pusher-whiteboard -> vanilla-pusher-functions

* update readme to reflect pusher name changes

* append .js to Node -> Node.js

* Update vanilla-pusher-functions/README.md

* Update vanilla-pusher-functions/README.md

* Update vanilla-pusher-functions/README.md
  • Loading branch information...
coetry authored and msweeneydev committed Aug 23, 2019
1 parent d760b25 commit ee4ac709a69e41687e5df1f0e435077b386ed112
@@ -0,0 +1,4 @@
.env
node_modules
#*
.#*
@@ -0,0 +1,2 @@
.env
node_modules
@@ -0,0 +1,19 @@
# Realtime Pusher Whiteboard

This directory is a realtime serverless whiteboard powered by Pusher. The frontend is static vanilla HTML, CSS, and JavaScript and the backend is a single Node.js function.

## Creating This Example

To get started with a realtime whiteboard on Now, you can use [Now CLI](https://zeit.co/download) to initialize the project:

```shell
$ now init vanilla-pusher-functions
```

## Deploying This Example

Once initialized, you can deploy the example with just a single command:

```shell
$ now
```
@@ -0,0 +1,5 @@
{
"dependencies": {
"pusher": "^2.2.2"
}
}
@@ -0,0 +1,21 @@
const Pusher = require("pusher");

const {
APP_ID: appId,
KEY: key,
SECRET: secret,
CLUSTER: cluster
} = process.env;

const pusher = new Pusher({
appId,
key,
secret,
cluster
});

module.exports = (req, res) => {
const { x0, x1, y0, y1, color } = req.body;
pusher.trigger("drawing-events", "drawing", { x0, x1, y0, y1, color });
res.status(200).end("sent event succesfully");
};
@@ -0,0 +1,24 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Realtime Whiteboard</title>
<link rel="stylesheet" href="style.css">
</head>
<body>

<canvas class="whiteboard" ></canvas>

<div class="colors">
<div class="color black"></div>
<div class="color red"></div>
<div class="color green"></div>
<div class="color blue"></div>
<div class="color yellow"></div>
</div>

<script src="https://js.pusher.com/4.4/pusher.min.js"></script>
<script src="main.js"></script>
</body>
</html>
@@ -0,0 +1,140 @@
"use strict";

(function() {
let canvas = document.querySelector(".whiteboard");
let colors = document.querySelectorAll(".color");
let context = canvas.getContext("2d");

let pusher = new Pusher("2a81e2e82be1a9d76433", {
cluster: "us2"
});
let channel = pusher.subscribe("drawing-events");

channel.bind("drawing", onDrawingEvent);

let current = {
color: "black"
};

let drawing = false;

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

canvas.addEventListener("mousedown", onMouseDown, false);
canvas.addEventListener("mouseup", onMouseUp, false);
canvas.addEventListener("mouseout", onMouseUp, false);
canvas.addEventListener("mousemove", throttle(onMouseMove, 10), false);

canvas.addEventListener("touchstart", onMouseDown, false);
canvas.addEventListener("touchend", onMouseUp, false);
canvas.addEventListener("touchcancel", onMouseUp, false);
canvas.addEventListener("touchmove", throttle(onMouseMove, 10), false);

for (var i = 0; i < colors.length; i++) {
colors[i].addEventListener("click", updateColor, false);
}

function drawLine(x0, x1, y0, y1, color, emit) {
context.beginPath();
context.moveTo(x0, y0);
context.lineTo(x1, y1);
context.strokeStyle = color;
context.lineWidth = 2;
context.stroke();
context.closePath();

if (!emit) {
return;
}

let w = canvas.width;
let h = canvas.height;

pushDrawData({
x0: x0 / w,
x1: x1 / w,
y0: y0 / h,
y1: y1 / h,
color
});
}

function onMouseDown(e) {
drawing = true;
current.x = e.clientX || e.touches[0].clientX;
current.y = e.clientY || e.toches[0].clientY;
}

function onMouseUp(e) {
if (!drawing) {
return;
}
drawing = false;
drawLine(
current.x,
e.clientX || e.touches[0].clientX,
current.y,
e.clientY || e.touches[0].clientY,
current.color,
true
);
}

function onMouseMove(e) {
if (!drawing) {
return;
}
drawLine(
current.x,
e.clientX || e.touches[0].clientX,
current.y,
e.clientY || e.touches[0].clientY,
current.color,
true
);
current.x = e.clientX || e.touches[0].clientX;
current.y = e.clientY || e.touches[0].clientY;
}

function throttle(callback, delay) {
let previousCall = Date.now();
return function() {
let time = Date.now();

if (time - previousCall >= delay) {
previousCall = time;
callback.apply(null, arguments);
}
};
}

function updateColor(e) {
pushDrawData();
current.color = e.target.className.split(" ")[1];
}

function onDrawingEvent({ x0, x1, y0, y1, color }) {
let w = canvas.width;
let h = canvas.height;
drawLine(x0 * w, x1 * w, y0 * h, y1 * h, color);
}

function onResize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}

async function pushDrawData(data) {
const res = await fetch("/api/push-draw-data", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
if (!res.ok) {
console.error("event not sent");
}
}
})();
@@ -0,0 +1,9 @@
{
"version": 2,
"env": {
"APP_ID": "@pusher-whiteboard-app-id",
"KEY": "@pusher-whiteboard-key",
"SECRET": "@pusher-whiteboard-secret",
"CLUSTER": "us2"
}
}
@@ -0,0 +1,39 @@
* {
box-sizing: border-box;
}

html, body {
height: 100%;
margin: 0;
padding: 0;
}

/**
* Canvas
*/

.whiteboard {
height: 100%;
width: 100%;
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
}

.colors {
position: fixed;
}

.color {
display: inline-block;
height: 48px;
width: 48px;
}

.color.black { background-color: black; }
.color.red { background-color: red; }
.color.green { background-color: green; }
.color.blue { background-color: blue; }
.color.yellow { background-color: yellow; }

1 comment on commit ee4ac70

@now

This comment has been minimized.

Please sign in to comment.
You can’t perform that action at this time.