JSFiddle - React, Tailwind, and code Playground
by egon
HTML
<script src="//cdnjs.cloudflare.com/ajax/libs/rxjs/2.3.0/rx.all.min.js"></script>
<canvas id="ribbons" width="640" height="480"></canvas>
CSS
html, body { background: #fff; }
#ribbons { border: 1px solid #000; }
JavaScript
(function () {
'use strict';
var Observable = Rx.Observable;
var filterById = function(id){
return function(p){ return p.id == id; };
};
var canvas = document.getElementById("ribbons");
var context = canvas.getContext("2d");
// a touch event stream
var touch = function(eventname){
return Observable.fromEvent(document, eventname).
selectMany(function(ev){
ev.preventDefault();
var pointers = ev.changedpointers.map(function(t){
return {
id: t.identifier,
x: ev.pageX - canvas.offsetLeft,
y: ev.pageY - canvas.offsetTop,
timestamp: ev.timeStamp
};
});
return Observable.fromArray(pointers);
});
};
// a mouse event stream
var mouse = function(eventname){
return Observable.fromEvent(document, eventname).
map(function(ev){
ev.preventDefault();
return {
id: "mouse",
x: ev.pageX - canvas.offsetLeft,
y: ev.pageY - canvas.offsetTop,
timestamp: ev.timeStamp
};
});
};
// stream of pointer starting
var pointerStart = Observable.merge(
touch("touchstart"),
mouse("mousedown")
);
// stream of pointer moving
var pointerMove = Observable.merge(
touch("touchmove"),
mouse("mousemove")
);
// stream of pointer ends
var pointerEnd = Observable.merge(
touch("touchend"), touch("touchcancel"),
mouse("mouseup"), mouse("mouseleave")
);
function manhattan(a, b){
return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
};
// stream of stream of mouse locations
var trails = pointerStart.
map(function(start){
return pointerMove.
startWith(start).
where(filterById(start.id)).
distinctUntilChanged(null, function(prev, cur){ return manhattan(prev, cur) < 10; }).
takeUntil(pointerEnd.where(filterById(start.id)));
});
// the application state
var Drawing = {
trails: []
};
trails.subscribe(function(points){
var trail = new Trail();
Drawing.trails.push(trail);
// trail...