JavaScript
语言:
JaveScriptBabelCoffeeScript
确定
'use strict';
// Dom Nodes
var triangle = document.querySelector('#js-triangle');
var centroidTriangle = document.querySelector('#js-centroid-triangle');
var handle1 = document.querySelector('#js-handle-1');
var handle2 = document.querySelector('#js-handle-2');
var handle3 = document.querySelector('#js-handle-3');
var showDebug = false;
if (showDebug) {
var _debugCC = document.querySelector('#js-circum-center');
var _debug = document.querySelector('#js-debug');
}
var animationFrame$ = Rx.Observable.interval(0, Rx.Scheduler.animationFrame);
// Drag Handler
var drag = function drag(domNode, pan$) {
return pan$.filter(function(e) {
return e.type === 'panstart';
}).switchMap(function(pd) {
var start = {
x: +domNode.getAttribute('cx'),
y: +domNode.getAttribute('cy')
};
var w = document.body.clientWidth;
var h = document.body.clientHeight;
domNode.setAttribute('r', 15);
var svgW = w > h ? 400 * w / h : 400;
var svgH = w > h ? 400 : 400 * h / w;
var move$ = pan$.filter(function(e) {
return e.type === 'panmove';
}).map(function(pm) {
return {
x: start.x + linInterp(pm.deltaX, 0, w, 0, svgW),
y: start.y + linInterp(pm.deltaY, 0, h, 0, svgH)
};
}).takeUntil(pan$.filter(function(e) {
return e.type === 'panend';
}));
move$.subscribe(null, null, function() {
return domNode.setAttribute('r', 10);
});
return move$;
});
};
var handleDrag = function handleDrag(domNode) {
var hammerPan = new Hammer(domNode, {
direction: Hammer.DIRECTION_ALL
});
hammerPan.get('pan').set({
direction: Hammer.DIRECTION_ALL
});
var pan$ = Rx.Observable.fromEventPattern(function(h) {
return hammerPan.on('panstart panup pandown panmove panend', h);
});
var drag$ = drag(domNode, pan$);
return animationFrame$.withLatestFrom(drag$, function(_, e) {
return e;
}).scan(RxCSS.lerp(0.1)).map(function(p) {
return [p.x, p.y];
});
};
var points$ = Rx.Observable.combineLatest(handleDrag(handle1).startWith([100, 200]), handleDrag(handle2).startWith([150, 100]), handleDrag(handle3).startWith([300, 200]));
var triangle$ = points$.distinctUntilChanged(function(p, n) {
return Math.abs(addAll(p) - addAll(n)) < 0.1;
}).map(function(points) {
return {
points: points,
circumCenter: circumCenter.apply(undefined, points)
};
});
// State: Main Triangle, Equilateral triangles and Centroid Triangle
var state$ = triangle$.map(function(_ref) {
var _ref$points = _ref.points;
var u = _ref$points[0];
var v = _ref$points[1];
var w = _ref$points[2];
var circumCenter = _ref.circumCenter;
return {
triangle: [u, v, w],
a: eqTriangle(u, v, circumCenter, w),
b: eqTriangle(v, w, circumCenter, u),
c: eqTriangle(w, u, circumCenter, v),
circumCenter: circumCenter
};
}).map(function(_ref2) {
var triangle = _ref2.triangle;
var a = _ref2.a;
var b = _ref2.b;
var c = _ref2.c;
var circumCenter = _ref2.circumCenter;
return {
triangle: triangle,
a: a,
b: b,
c: c,
centroidTriangle: [centroid(a), centroid(b), centroid(c)],
cc: circumCenter
};
});
// Convert state to SVG geometry and render
var svgGeometry$ = state$.map(function(_ref3) {
var triangle = _ref3.triangle;
var a = _ref3.a;
var b = _ref3.b;
var c = _ref3.c;
var centroidTriangle = _ref3.centroidTriangle;
var cc = _ref3.cc;
return {
triangleD: ['M', triangle.join('L'), 'L', a.join('L'), 'L', b.join('L'), 'L', c.join('L')],
cc: cc,
debugD: ['M'].concat(triangle[0], ['L'], cc, ['L'], triangle[1], ['M'], cc, ['L'], triangle[2], ['M'], a[1], ['L'], cc, ['L'], b[1], ['M'], cc, ['L'], c[1]).join(' '),
centroidTriangleD: ['M', centroidTriangle.join('L'), 'Z'],
handles: [triangle[0], triangle[1], triangle[2]]
};
});
svgGeometry$.subscribe(function(_ref4) {
var triangleD = _ref4.triangleD;
var centroidTriangleD = _ref4.centroidTriangleD;
var _ref4$handles = _ref4.handles;
var h1 = _ref4$handles[0];
var h2 = _ref4$handles[1];
var h3 = _ref4$handles[2];
var cc = _ref4.cc;
var debugD = _ref4.debugD;
triangle.setAttribute('d', triangleD.join(''));
centroidTriangle.setAttribute('d', centroidTriangleD.join(''));
handle1.setAttribute('cx', h1[0]);
handle1.setAttribute('cy', h1[1]);
handle2.setAttribute('cx', h2[0]);
handle2.setAttribute('cy', h2[1]);
handle3.setAttribute('cx', h3[0]);
handle3.setAttribute('cy', h3[1]);
if (showDebug) {
debugCC.setAttribute('cx', cc[0]);
debugCC.setAttribute('cy', cc[1]);
debug.setAttribute('d', debugD);
}
});
/**
* Geometry
*/
function eqTriangle(u, v, cc) {
return [u, apex(u, v, cc), v];
}
function apex(_ref5, _ref6, _ref7) {
var ux = _ref5[0];
var uy = _ref5[1];
var vx = _ref6[0];
var vy = _ref6[1];
var ccx = _ref7[0];
var ccy = _ref7[1];
var mpx = (vx + ux) / 2;
var mpy = (vy + uy) / 2;
var dir = sign([ccx, ccy], [ux, uy], [vx, vy]) > 0 ? 1 : -1;
var ccMp = [mpx - ccx, mpy - ccy].map(function(x) {
return x * dir;
});
var h = triangleHeight([ux, uy], [vx, vy]);
var m = magnitude(ccMp);
var _ccMp$map = ccMp.map(function(s) {
return s * (h + dir * m) / m;
});
var nx = _ccMp$map[0];
var ny = _ccMp$map[1];
return [nx + ccx, ny + ccy];
}
function circumCenter(_ref8, _ref9, _ref10) {
var ax = _ref8[0];
var ay = _ref8[1];
var bx = _ref9[0];
var by = _ref9[1];
var cx = _ref10[0];
var cy = _ref10[1];
var d = (ax - cx) * (by - cy) - (bx - cx) * (ay - cy);
var x = (((ax - cx) * (ax + cx) + (ay - cy) * (ay + cy)) / 2 * (by - cy) - ((bx - cx) * (bx + cx) + (by - cy) * (by + cy)) / 2 * (ay - cy)) / d;
var y = (((bx - cx) * (bx + cx) + (by - cy) * (by + cy)) / 2 * (ax - cx) - ((ax - cx) * (ax + cx) + (ay - cy) * (ay + cy)) / 2 * (bx - cx)) / d;
return [Math.round(x * 100) / 100, Math.round(y * 100) / 100];
}
function centroid(_ref11) {
var _ref11$ = _ref11[0];
var ux = _ref11$[0];
var uy = _ref11$[1];
var _ref11$2 = _ref11[1];
var vx = _ref11$2[0];
var vy = _ref11$2[1];
var _ref11$3 = _ref11[2];
var wx = _ref11$3[0];
var wy = _ref11$3[1];
return [avg(ux, vx, wx), avg(uy, vy, wy)];
}
/**
* Utils
*/
function magnitude(_ref12) {
var x = _ref12[0];
var y = _ref12[1];
return Math.pow(Math.pow(x, 2) + Math.pow(y, 2), 0.5);
}
function triangleHeight(_ref13, _ref14) {
var ux = _ref13[0];
var uy = _ref13[1];
var vx = _ref14[0];
var vy = _ref14[1];
return Math.pow(3, 0.5) * dist([ux, uy], [vx, vy]) / 2;
}
function dist(_ref15, _ref16) {
var ux = _ref15[0];
var uy = _ref15[1];
var vx = _ref16[0];
var vy = _ref16[1];
return Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));
}
function avg(t0, t1, t2) {
return (t0 + t1 + t2) / 3;
}
function linInterp(x, x1, x2, y1, y2) {
return (x - x1) * ((y2 - y1) / (x2 - x1)) + y1;
}
function add(a, b) {
return a + b;
}
function addAll(list) {
return list.map(function(x) {
return x.reduce(add, 0);
}).reduce(add, 0);
}
function sign(_ref17, _ref18, _ref19) {
var p1x = _ref17[0];
var p1y = _ref17[1];
var p2x = _ref18[0];
var p2y = _ref18[1];
var p3x = _ref19[0];
var p3y = _ref19[1];
return (p1x - p3x) * (p2y - p3y) - (p2x - p3x) * (p1y - p3y);
}