Last active
February 24, 2020 20:59
-
-
Save nmattia/b3baf8aea526d133137a8fe204d26c51 to your computer and use it in GitHub Desktop.
rotating divs
This file contains 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
let clientX_0 = 0; | |
let clientX_d = 0; | |
const MIN_WIDTH = 10; | |
const MIN_HEIGHT = 10; | |
let w0 = getpc("inner-width"); | |
let h0 = getpc("inner-height"); | |
let w = w0; | |
let h = h0; | |
let p0_x = getpc("inner-left"); | |
let p0_y = getpc("inner-top"); | |
let r0_x = getpc("inner-left"); | |
let r0_y = getpc("inner-top"); | |
let p_x = p0_x; | |
let p_y = p0_y; | |
let pp_x = p0_x; | |
let pp_y = p0_y; | |
let qp0_x = p0_x + w; | |
let qp0_y = p0_y + h; | |
let q_x = qp0_x; | |
let q_y = qp0_y; | |
let qp_x = qp0_x; | |
let qp_y = qp0_y; | |
let cp_x = (q_x + p_x) / 2; | |
let cp_y = (q_y + p_y) / 2; | |
render_debug = false; | |
function update(name, delta) { | |
const reg = /(-?\d+)(.+)/; | |
let res = reg.exec(get(name)); | |
let was = parseInt(res[1]); | |
let ext = res[2]; | |
let new_ = was + delta; | |
new_ = `${new_}${ext}`; | |
set(name, new_); | |
} | |
function set(name, val) { | |
document.body.style.setProperty(`--${name}`, val); | |
} | |
function get(name) { | |
return window.getComputedStyle(document.body).getPropertyValue(`--${name}`); | |
} | |
function getpx(name) { | |
const reg = /(-?\d+)px/; | |
let res = reg.exec(get(name)); | |
return parseInt(res[1]); | |
} | |
function getpc(name) { | |
const reg = /(-?\d+)%/; | |
let res = reg.exec(get(name)); | |
return parseInt(res[1]); | |
} | |
function setpc(name, val) { | |
set(name, `${val}%`); | |
} | |
function getdeg(name) { | |
const reg = /(-?\d+)deg/; | |
let res = reg.exec(get(name)); | |
return parseInt(res[1]); | |
} | |
function render() { | |
if (render_debug) { | |
// document.getElementById("logs").innerHTML = ` | |
// clientX_0: ${clientX_0} <br/> | |
// clientX_d: ${clientX_d} <br/><br/> | |
// theta: ${get("theta")} <br/> | |
// inner-left: ${get("inner-left")}<br/> | |
// inner-top: ${get("inner-top")}<br/> | |
// p_0 = (${p0_x}, ${p0_y})<br/> | |
// p = (${p_x}, ${p_y})<br/> | |
// p' = (${pp_x}, ${pp_y})<br/><br/> | |
// q = (${q_x}, ${q_y})<br/> | |
// q'_0 = (${qp0_x}, ${qp0_y})<br/> | |
// q' = (${qp_x}, ${qp_y})<br/><br/> | |
// w = ${w0} -> ${w}<br/> | |
// h = ${h0} -> ${h}<br/> | |
// w' = ${getpc("inner-width")}<br/> | |
// h' = ${getpc("inner-height")}<br/> | |
// c' = (${cp_x}, ${cp_y}) | |
// `; | |
} else { | |
document.getElementById("logs").innerHTML = ""; | |
} | |
} | |
render(); | |
function onKey(e) { | |
switch(e.keyCode) { | |
case 37: | |
update("inner-left", -10); | |
break; | |
case 38: | |
update("inner-top", -10); | |
break; | |
case 39: | |
update("inner-left", 10); | |
break; | |
case 40: | |
update("inner-top", 10); | |
break; | |
} | |
render(); | |
} | |
function onDragStart(a,b) { | |
const c = a === 1 ? 0 : 1; | |
const d = b === 1 ? 0 : 1; | |
return function (e){ | |
clientX_0 = e.clientX; | |
clientY_0 = e.clientY; | |
const w0 = getpc("inner-width"); | |
const h0 = getpc("inner-height"); | |
let theta = getdeg("theta"); | |
theta = Math.PI * 2 * theta / 360; | |
const cos_t = Math.cos(theta); | |
const sin_t = Math.sin(theta); | |
const r0_x = getpc("inner-left"); | |
const r0_y = getpc("inner-top"); | |
const c0_x = r0_x + w0 / 2.0; | |
const c0_y = r0_y + h0 / 2.0; | |
q0_x = r0_x + a * w0; | |
q0_y = r0_y + b * h0; | |
qp0_x = q0_x * cos_t - q0_y * sin_t - c0_x * cos_t + c0_y * sin_t + c0_x; | |
qp0_y = q0_x * sin_t + q0_y * cos_t - c0_x * sin_t - c0_y * cos_t + c0_y; | |
p0_x = r0_x + c * w0; | |
p0_y = r0_y + d * h0; | |
// pp == pp0 | |
pp_x = p0_x * cos_t - p0_y * sin_t - c0_x * cos_t + c0_y * sin_t + c0_x; | |
pp_y = p0_x * sin_t + p0_y * cos_t - c0_x * sin_t - c0_y * cos_t + c0_y; | |
render(); | |
} | |
} | |
function onDrag(a, b) { | |
const c = a === 1 ? 0 : 1; | |
const d = b === 1 ? 0 : 1; | |
return function(e) { | |
// silly jitter | |
if (e.clientX === 0 || e.clientY === 0) { return; } | |
clientX_d = 100 * (e.clientX - clientX_0) / getpx("outer-width"); | |
clientY_d = 100 * (e.clientY - clientY_0) / getpx("outer-height"); | |
const mtheta = -1 * Math.PI * 2 * getdeg("theta") / 360; | |
const cos_mt = Math.cos(mtheta); | |
const sin_mt = Math.sin(mtheta); | |
qp_x = qp0_x + clientX_d; | |
qp_y = qp0_y + clientY_d; | |
cp_x = (qp_x + pp_x) / 2.0; | |
cp_y = (qp_y + pp_y) / 2.0; | |
q_x = qp_x * cos_mt - qp_y * sin_mt - cos_mt * cp_x + sin_mt * cp_y + cp_x; | |
q_y = qp_x * sin_mt + qp_y * cos_mt - sin_mt * cp_x - cos_mt * cp_y + cp_y; | |
p_x = pp_x * cos_mt - pp_y * sin_mt - cos_mt * cp_x + sin_mt * cp_y + cp_x; | |
p_y = pp_x * sin_mt + pp_y * cos_mt - sin_mt * cp_x - cos_mt * cp_y + cp_y; | |
const wtmp = a * (q_x - p_x) + c * (p_x - q_x); | |
const htmp = b * (q_y - p_y) + d * (p_y - q_y); | |
if (wtmp < MIN_WIDTH || htmp < MIN_HEIGHT) { | |
w = Math.max(MIN_WIDTH, wtmp); | |
h = Math.max(MIN_HEIGHT, htmp); | |
const theta = -1 * mtheta; | |
cos_t = Math.cos(theta); | |
sin_t = Math.sin(theta); | |
let dh_x = - sin_t * h; | |
let dh_y = cos_t * h; | |
let dw_x = cos_t * w; | |
let dw_y = sin_t * w; | |
qp_x = pp_x + (a - c) * dw_x + (b - d) * dh_x | |
qp_y = pp_y + (a - c) * dw_y + (b - d) * dh_y | |
cp_x = (qp_x + pp_x) / 2.0; | |
cp_y = (qp_y + pp_y) / 2.0; | |
q_x = qp_x * cos_mt - qp_y * sin_mt - cos_mt * cp_x + sin_mt * cp_y + cp_x; | |
q_y = qp_x * sin_mt + qp_y * cos_mt - sin_mt * cp_x - cos_mt * cp_y + cp_y; | |
p_x = pp_x * cos_mt - pp_y * sin_mt - cos_mt * cp_x + sin_mt * cp_y + cp_x; | |
p_y = pp_x * sin_mt + pp_y * cos_mt - sin_mt * cp_x - cos_mt * cp_y + cp_y; | |
} else { | |
w = wtmp; | |
h = htmp; | |
} | |
const r_x = c * q_x + a * p_x; | |
const r_y = d * q_y + b * p_y; | |
setpc("inner-left", r_x); | |
setpc("inner-top", r_y); | |
setpc("inner-width", w); | |
setpc("inner-height", h); | |
render(); | |
} | |
} | |
function onDragEnd(xf,yf) { | |
return function(e) { | |
clientX_d = clientX_0 = 0; | |
clientY_d = clientY_0 = 0; | |
setpc("inner-left", r0_x); | |
setpc("inner-top", r0_y); | |
setpc("inner-width", w0); | |
setpc("inner-height", h0); | |
render(); | |
} | |
} | |
window.onkeydown = onKey; | |
document.getElementById("bottomright").ondrag = onDrag(1,1); | |
document.getElementById("bottomright").ondragstart = onDragStart(1,1); | |
document.getElementById("bottomright").ondragend = onDragEnd(1,1); | |
document.getElementById("bottomleft").ondrag = onDrag(0,1); | |
document.getElementById("bottomleft").ondragstart = onDragStart(0,1); | |
document.getElementById("bottomleft").ondragend = onDragEnd(0,1); | |
document.getElementById("topleft").ondrag = onDrag(0,0); | |
document.getElementById("topleft").ondragstart = onDragStart(0,0); | |
document.getElementById("topleft").ondragend = onDragEnd(0,0); | |
document.getElementById("topright").ondrag = onDrag(1,0); | |
document.getElementById("topright").ondragstart = onDragStart(1,0); | |
document.getElementById("topright").ondragend = onDragEnd(1,0); |
This file contains 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
<head> | |
<style> | |
body { | |
background-color: linen; | |
} | |
h1 { | |
color: maroon; | |
margin-left: 40px; | |
} | |
:root { | |
--outer-top: 250px; | |
--outer-left: 250px; | |
--outer-width: 500px; | |
--outer-height: 500px; | |
--inner-width: 50%; | |
--inner-height: 50%; | |
--inner-left: -25%; | |
--inner-top: -25%; | |
--corner-radius: 20px; | |
--theta: 25deg; | |
} | |
#outer { | |
position: relative; | |
width: var(--outer-width); | |
height: var(--outer-height); | |
top: var(--outer-top); | |
left: var(--outer-left); | |
border: solid lightgray 2px; | |
} | |
#inner { | |
position: absolute; | |
width: var(--inner-width); | |
height: var(--inner-height); | |
top: var(--inner-top); | |
left: var(--inner-left); | |
border: solid black 2px; | |
transform: rotate(var(--theta)); | |
} | |
.corner { | |
position: absolute; | |
width: 20px; | |
height: 20px; | |
border: solid black 2px; | |
border-radius: 20px; | |
} | |
#bottomright{ | |
top: calc( 100% - var(--corner-radius) / 2); | |
left: calc( 100% - var(--corner-radius) / 2); | |
} | |
#bottomleft{ | |
top: calc( 100% - var(--corner-radius) / 2); | |
left: calc( 0% - var(--corner-radius) / 2); | |
} | |
#topright{ | |
top: calc( 0px - var(--corner-radius) / 2); | |
left: calc( 100% - var(--corner-radius) / 2); | |
} | |
#topleft{ | |
top: calc( 0% - var(--corner-radius) / 2); | |
left: calc( 0% - var(--corner-radius) / 2); | |
} | |
</style> | |
</head> | |
<div id="outer"> | |
<div id="inner" draggable="true"> | |
<div id="bottomright" class="corner" draggable="true"></div> | |
<div id="bottomleft" class="corner" draggable="true"></div> | |
<div id="topright" class="corner" draggable="true"></div> | |
<div id="topleft" class="corner" draggable="true"></div> | |
</div> | |
</div> | |
<div id="logs"> | |
</div> | |
<script src="./foo.js"></script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment