Created
September 6, 2015 15:38
-
-
Save riston/aaaa08467aa19517175d to your computer and use it in GitHub Desktop.
Reactive RXJS drawing example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var canvas = document.getElementById("container"); | |
var ctx = canvas.getContext("2d"); | |
// The line settings | |
ctx.lineWidth = 4; | |
ctx.lineJoin = ctx.lineCap = "round"; | |
var intervalSource = Rx.Observable.interval(2 * 1000, Rx.Scheduler.requestAnimationFrame); | |
var pauser = new Rx.Subject(); | |
var mouseMove = Rx.Observable.fromEvent(canvas, "mousemove"); | |
var mouseDown = Rx.Observable.fromEvent(canvas, "mousedown"); | |
var mouseUp = Rx.Observable.fromEvent(canvas, "mouseup"); | |
var windowResize = Rx.Observable.fromEvent(window, "resize") | |
.throttleFirst(250 /* ms */); | |
var mousePath = mouseDown | |
.first() | |
.concat(mouseMove.takeUntil(mouseUp)) | |
.repeat(); | |
var snapToGrid = mousePath | |
.map(function (e) { | |
var gridWidth = 15; | |
var x = Math.round(e.x / gridWidth) * gridWidth; | |
var y = Math.round(e.y / gridWidth) * gridWidth; | |
return { | |
x: x, | |
y: y, | |
}; | |
}) | |
.distinctUntilChanged(); | |
snapToGrid | |
.bufferWithCount(2, 1) | |
.subscribe(function (e) { | |
// console.log("N", e.x, e.y); | |
// newTick(e.y); | |
// var drawLine = function (p) { | |
// ctx.lineTo(p.x, p.y); | |
// ctx.stroke(); | |
// }; | |
// drawLine(e); | |
// drawCircle(e.x, e.y, 2, "#aaa"); | |
}); | |
mouseDown.subscribe(function (first) { | |
console.log("First Event", first); | |
ctx.beginPath(); | |
ctx.moveTo(first.x, first.y); | |
// mouseMove.resume(); | |
}); | |
mouseUp.subscribe(function (last) { | |
console.log("Last event"); | |
ctx.closePath(); | |
// mouseMove.pause(); | |
}); | |
mousePath | |
.map(roundEventValues) | |
.distinctUntilChanged() | |
// .debounce(5) | |
// .bufferWithCount(2) | |
.subscribe(function (point) { | |
var drawEvent = function (e) { | |
var x = e.x; | |
var y = e.y; | |
drawCircle(x, y, 4); | |
}; | |
var drawLine = function (p) { | |
ctx.lineTo(p.x, p.y); | |
ctx.stroke(); | |
}; | |
var drawQuadLine = function (a, b) | |
{ | |
var midPoint = midPointBtw(a, b); | |
ctx.quadraticCurveTo(a.x, a.y, midPoint.x, midPoint.y); | |
ctx.stroke(); | |
}; | |
console.log("D", point); | |
// drawQuadLine(points[0], points[1]); | |
drawLine(point); | |
// drawLine(points[1]); | |
}); | |
intervalSource.subscribe(function (e) { | |
console.log("Interval"); | |
}); | |
windowResize.subscribeOnNext(function (e) { | |
var size = getWindowSize(); | |
console.log("Resize window", size); | |
canvas.setAttribute("height", size.height); | |
canvas.setAttribute("width", size.width); | |
}); | |
function roundEventValues (e) | |
{ | |
return { | |
x: ~~e.x, | |
y: ~~e.y, | |
}; | |
} | |
function drawCircle(x, y, radius, defaultColor) | |
{ | |
var hr = Math.floor(radius / 2); | |
var color = defaultColor || "#fff"; | |
ctx.fillStyle = color; | |
ctx.beginPath(); | |
ctx.arc(x - hr, y - hr, radius, radius, Math.PI * 2, true); | |
ctx.closePath(); | |
ctx.fill(); | |
} | |
function midPointBtw (p1, p2) | |
{ | |
return { | |
x: p1.x + (p2.x - p1.x) / 2, | |
y: p1.y + (p2.y - p1.y) / 2 | |
}; | |
} | |
function getWindowSize () | |
{ | |
return { | |
width: window.innerWidth, | |
height: window.innerHeight, | |
}; | |
} | |
function onLoad () | |
{ | |
var size = getWindowSize(); | |
console.log("Window loaded", getWindowSize()); | |
canvas.setAttribute("height", size.height); | |
canvas.setAttribute("width", size.width); | |
} | |
function main () | |
{ | |
console.log("Called main"); | |
window.addEventListener("load", onLoad); | |
} | |
main(); | |
// Drawing chart for the mouse movements | |
// var n = 40, | |
// random = d3.random.normal(0, 200), | |
// data = d3.range(n).map(random); | |
// var margin = {top: 20, right: 20, bottom: 20, left: 40}, | |
// width = 400 - margin.left - margin.right, | |
// height = 200 - margin.top - margin.bottom; | |
// var x = d3.scale.linear() | |
// .domain([0, n - 1]) | |
// .range([0, width]); | |
// var y = d3.scale.linear() | |
// .domain([0, 1000]) | |
// .range([height, 0]); | |
// var line = d3.svg.line() | |
// .x(function(d, i) { return x(i); }) | |
// .y(function(d, i) { return y(d); }); | |
// var svg = d3.select(".x-axis").append("svg") | |
// .attr("width", width + margin.left + margin.right) | |
// .attr("height", height + margin.top + margin.bottom) | |
// .append("g") | |
// .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
// svg.append("defs").append("clipPath") | |
// .attr("id", "clip") | |
// .append("rect") | |
// .attr("width", width) | |
// .attr("height", height); | |
// svg.append("g") | |
// .attr("class", "x axis") | |
// .attr("transform", "translate(0," + y(0) + ")") | |
// .call(d3.svg.axis().scale(x).orient("bottom")); | |
// svg.append("g") | |
// .attr("class", "y axis") | |
// .call(d3.svg.axis().scale(y).orient("left")); | |
// var path = svg.append("g") | |
// .attr("clip-path", "url(#clip)") | |
// .append("path") | |
// .datum(data) | |
// .attr("class", "line") | |
// .attr("d", line); | |
// // tick(); | |
// function newTick (y) { | |
// // push a new data point onto the back | |
// data.push(y); | |
// // redraw the line, and slide it to the left | |
// path | |
// .attr("d", line) | |
// .attr("transform", "") | |
// .transition() | |
// .duration(500) | |
// .ease("linear") | |
// .attr("transform", "translate(" + x(-1) + ",0)"); | |
// // .each("end", tick); | |
// // pop the old data point off the front | |
// data.shift(); | |
// } | |
// function tick() { | |
// // push a new data point onto the back | |
// data.push(random()); | |
// // redraw the line, and slide it to the left | |
// path | |
// .attr("d", line) | |
// .attr("transform", "") | |
// .transition() | |
// .duration(500) | |
// .ease("linear") | |
// .attr("transform", "translate(" + x(-1) + ",0)") | |
// .each("end", tick); | |
// // pop the old data point off the front | |
// data.shift(); | |
// } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Drawing</title> | |
<link rel="stylesheet" type="text/css" href="./style.css"> | |
</head> | |
<body> | |
<div> | |
<canvas id="container" width="600" height="600"></canvas> | |
</div> | |
<div class="x-axis"></div> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/3.1.1/rx.all.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script> | |
<script src="./app.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
margin: 0; | |
padding: 0; | |
overflow: hidden; | |
} | |
#container { | |
/* position: absolute; | |
top: 0; | |
right: 0; | |
left: 0; | |
bottom: 0; | |
*/ | |
background-color: #adf; | |
/*width: 900px;*/ | |
/*height: 900px;*/ | |
} | |
canvas { | |
pointer: crosshair; | |
background: rgba(147,206,222,1); | |
background: linear-gradient(to right, rgba(147,206,222,1) 0%, rgba(117,189,209,1) 41%, rgba(73,165,191,1) 100%); | |
} | |
svg { | |
font: 10px sans-serif; | |
} | |
.line { | |
fill: none; | |
stroke: #000; | |
stroke-width: 1.5px; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment