auto-accept/index.html

253 lines
8.7 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Auto accept</title>
<style type='text/css'>
body{
margin:0;
overflow: hidden;
cursor: url('./cursor.svg') 15 15, crosshair;
}
svg{
width:100vw;
height:100vh;
}
svg .rect{
stroke: red;
stroke-width: .2cm;
fill: none;
transition: stroke .5s;
}
svg .rect.locked{
stroke:blue;
opacity: 1;
transition: opacity .5s;
}
svg .rect.hide{
opacity:0;
}
#crosshair line{
stroke: gray;
stroke-dasharray: 5px 5px;
}
#video_background{
position: absolute;
top:0;
left:0;
bottom:0;
right:0;
z-index: -1;
opacity:0;
transition:opacity 10s;
}
</style>
</head>
<body>
<svg id='canvas' viewBox="0 0 220 100" xmlns="http://www.w3.org/2000/svg">
<g id='crosshair'>
<line id='crosshair_x' x1="0" y1="0" x2="0" y2="100%" />
<line id='crosshair_y' x1="0" y1="0" x2="100%" y2="0" />
</g>
</svg>
<video id="video_background" autoplay loop>
<source src="Blue_Sky_and_Clouds_Timelapse_0892__Videvo.mov">
</video>
<script>
/*
The interface is like a flywheel.
*/
class Flywheel{
constructor() {
this.value = 0.; // start at 0 - gradual meter
this.stage = 0.; // start at 0 - the various stages
this.f_falloff = (value) => value/20; // value at which it reduces per second
this.f_stage = (value) => 5*Math.log10(value); // value to stage calculation
this.value_min = 0;
this.value_max = 100; // gives stage 0-9
// this.interval = window.setInterval(this.step, 50)
this.time = null;
window.requestAnimationFrame(this.step.bind(this));
// TODO: once/twice per second should be enough! + on release (add())
}
step(time){
if(this.time === null){
// first run
this.time = time;
window.requestAnimationFrame(this.step.bind(this));
return;
}
if(time-this.time < 500){
window.requestAnimationFrame(this.step.bind(this));
return;
}
const dt = time - this.time;
this.time = time;
this.value -= this.f_falloff(this.value) * dt/1000; // linear falloff
if(this.value < 0){
this.value = 0;
}
// console.log(this.value,this.falloff, dt,this.time);
// TODO: check if this should be different
const stage = Math.max(0,Math.floor(this.f_stage(this.value)));
if (stage != this.stage){
this.changeStage(stage);
}
window.requestAnimationFrame(this.step.bind(this));
}
add(increment){
this.value += typeof increment == 'undefined' ? 1 : increment;
// cap:
if(this.value > this.value_max) this.value = this.value_max;
}
changeStage(stage){
this.stage = stage;
console.log('stage now at', this.stage);
// TODO: handle stage change
}
}
var flywheel = new Flywheel();
let svgEl = document.getElementById('canvas');
let crosshairXEl = document.getElementById('crosshair_x');
let crosshairYEl = document.getElementById('crosshair_y');
const segmentCount = window.location.search.substr(1).length ? window.location.search.substr(1) : 4;
function getPathShapeBetweenPoints(p1, p2, corners) {
let d = `M ${p1.x},${p1.y} L `;
if(corners == 4){
// draw inbetween p1 & p2.
let minx = Math.min(p1.x, p2.x);
let miny = Math.min(p1.y, p2.y);
let maxx = Math.max(p1.x, p2.x);
let maxy = Math.max(p1.y, p2.y);
d += ` ${p1.x},${p2.y} ${p2.x},${p2.y} ${p2.x},${p1.y} ${p1.x},${p1.y} `;
}
else{
// find center of circle that describes the polygon of which p1 and p2 are part
// it's _not_ the center between the two points, as p1 and p2 are corners on the shape
// distance between p1 and p2
const length = Math.sqrt(Math.pow(p1.x-p2.x,2)+ Math.pow(p1.y - p2.y, 2));
const segmentAngle = Math.PI * 2 / corners;
// we don't want
// const segmentsAngle = Math.floor(180/segmentAngle) * segmentAngle;
const radius = (length*.5)/Math.sin(segmentAngle);
const rotation = Math.atan2((p2.y -p1.y),(p2.x - p1.x)) + (Math.PI/2-segmentAngle);
const dx = Math.cos(rotation) * radius;// * Math.sign(p2.x - p1.x);
const dy = Math.sin(rotation) * radius;// * Math.sign(p2.y - p1.y);
// we now have the center:
const cx = p2.x - dx;
const cy = p2.y - dy;
// startpoint in relation to circle
const sx = cx - p1.x;
const sy = cy - p1.y;
let startRot = Math.asin(sx / radius);
if(sy>0){startRot = -1 * startRot + Math.PI;}
// console.log(sx, radius, startRot);
// animI+= .1;
// console.log(sx, sy, startRot);
for (let a = 0; a < Math.PI*2; a += segmentAngle) {
let x = radius * Math.sin(a-startRot) + cx;
let y = radius * Math.cos(a-startRot) + cy;
d += ` ${x},${y}`;
}
}
return d + ' Z';
}
// canvas position relative to mouse/screen
// TODO: update on resize:
svgEl.setAttribute('viewBox', '0 0 '+window.innerWidth+' '+window.innerHeight);
let rect = svgEl.getBoundingClientRect();
let cx = rect.left + rect.width/2;
let cy = rect.top + rect.height/2;
let center = {'x': cx, 'y': cy};
// move crosshairs
window.addEventListener('mousemove', function(mousemoveEv){
let x = mousemoveEv.clientX - rect.left;
let y = mousemoveEv.clientY - rect.top;
crosshairXEl.setAttribute('x1', x)
crosshairXEl.setAttribute('x2', x)
crosshairYEl.setAttribute('y1', y)
crosshairYEl.setAttribute('y2', y)
});
svgEl.addEventListener('mousedown', function(mousedownEv){
let shapeEl = document.createElementNS('http://www.w3.org/2000/svg','path');
shapeEl.classList.add('rect');
let p1 = {'x': mousedownEv.clientX - rect.left, 'y': mousedownEv.clientY - rect.top}
// shapeEl.setAttribute('x', p1.x);
// shapeEl.setAttribute('y', p1.y);
// shapeEl.setAttribute('width', 0);
// shapeEl.setAttribute('height', 0);
let d = getPathShapeBetweenPoints(p1, p1, segmentCount);
svgEl.appendChild(shapeEl);
shapeEl.setAttribute('d', d);
let mouseMoveEv = function(mousemoveEv) {
let p2 = {'x': mousemoveEv.clientX - rect.left, 'y': mousemoveEv.clientY - rect.top}
let d = getPathShapeBetweenPoints(p1, p2, segmentCount);
shapeEl.setAttribute('d', d);
};
let mouseUpEv = function() {
console.log('up');
window.removeEventListener('mousemove', mouseMoveEv); // remove itself.
window.removeEventListener('mouseup', mouseUpEv); // remove itself.
shapeEl.classList.add('locked');
//TODO: calculate points
flywheel.add();
setTimeout(function(){
shapeEl.classList.add('hide');
setTimeout(function(){
shapeEl.parentNode.removeChild(shapeEl);
},1000);
}, 1000);
};
window.addEventListener('mousemove', mouseMoveEv);
window.addEventListener('mouseup', mouseUpEv);
})
</script>
</body>
</html>