A concept for how to connect vectors radially and proximally using vector grouping. These groups would be determined at the vector level by doing calculations on the vector's radial position.
A Pen by HARUN PEHLİVAN on CodePen.
<div> | |
<canvas id="cvs1" height="800" width="800"></canvas> | |
<canvas id="cvs2" height="800" width="800"></canvas> | |
</div> |
console.clear(); | |
const PI = Math.PI; | |
const PI2 = PI * 2; | |
class Point { | |
constructor() { | |
this.x = Math.random(); | |
this.y = Math.random(); | |
} | |
} | |
class Canvas { | |
constructor() { | |
this.element1 = document.querySelector("#cvs1"); | |
this.context1 = this.element1.getContext("2d"); | |
this.element2 = document.querySelector("#cvs2"); | |
this.context2 = this.element2.getContext("2d"); | |
this.diameter = this.element1.width; | |
this.hypot = Math.hypot(-0.5, -0.5); | |
this.gutter = this.hypot * this.diameter - this.diameter / 2; | |
this.switchContext(0); | |
} | |
clear(which) { | |
if (which !== undefined) { | |
[ | |
this.context1, | |
this.context2 | |
][which].clearRect(0, 0, this.diameter, this.diameter); | |
} else { | |
this.context1.clearRect(0, 0, this.diameter, this.diameter); | |
this.context2.clearRect(0, 0, this.diameter, this.diameter); | |
} | |
} | |
switchContext(idx) { | |
this.context = [this.context1, this.context2][idx]; | |
} | |
grid() { | |
this.switchContext(0); | |
this.rect(0, 0, 1, 1, "#444"); | |
this.circ(0.5, 0.5, this.hypot, "#444"); | |
} | |
dToR(deg) { | |
return deg * PI / 180; | |
} | |
text(x, y, text, offset = 1) { | |
this.context.textAlign = "center"; | |
this.context.textBaseline = "middle"; | |
let fontSize = 14; | |
let offsetY = y > 0.5 | |
? fontSize * (offset * 1.5) | |
: fontSize * (offset * -1.5); | |
this.context.fillStyle = "white"; | |
this.context.font = `${fontSize}px Helvetica`; | |
this.context.fillText(text, this.rel(x), this.rel(y) + offsetY); | |
} | |
point(x, y, fill = "red") { | |
this.context.fillStyle = fill; | |
this.context.beginPath(); | |
this.context.arc(this.rel(x), this.rel(y), 2, 0, PI2); | |
this.context.fill(); | |
} | |
path(x1, y1, x2, y2, stroke = "red") { | |
this.context.strokeStyle = stroke; | |
this.context.lineWidth = 2; | |
this.context.beginPath(); | |
this.context.moveTo(this.rel(x1), this.rel(y1)); | |
this.context.lineTo(this.rel(x2), this.rel(y2)); | |
this.context.stroke(); | |
} | |
arc(x, y, rad, sDeg, eDeg, ccwise, stroke, fill) { | |
x = x === null ? 0.5 : x; | |
y = y === null ? 0.5 : y; | |
rad = rad === null ? this.hypot : rad; | |
this.context.fillStyle = fill; | |
this.context.strokeStyle = stroke; | |
this.context.lineWidth = 1; | |
this.context.beginPath(); | |
this.context.moveTo(this.rel(x), this.rel(y)); | |
this.context.arc( | |
this.rel(x), | |
this.rel(y), | |
this.relS(rad), | |
this.dToR(sDeg), | |
this.dToR(eDeg), | |
ccwise | |
); | |
this.context.lineTo(this.rel(x), this.rel(y)); | |
this.context.closePath(); | |
this.context.fill(); | |
this.context.stroke(); | |
} | |
cone(deg, rad, ratio, stroke, fill) { | |
let x = this.rel(0.5); | |
let y = this.rel(0.5); | |
let off = ratio * 45; | |
let relrad = this.relS(rad); | |
this.context.fillStyle = fill; | |
this.context.lineJoin = "round"; | |
this.context.strokeStyle = stroke; | |
this.context.lineWidth = 1; | |
let srad = this.dToR(90 + deg); | |
let erad = this.dToR(-90 + deg); | |
let mrad = this.dToR(deg); | |
let mrad1 = this.dToR(deg - off); | |
let mrad2 = this.dToR(deg + off); | |
let mrad3 = this.dToR(90 + deg - off); | |
let mrad4 = this.dToR(-90 + deg + off); | |
let ax = rad * Math.cos(erad) + 0.5; | |
let ay = rad * Math.sin(erad) + 0.5; | |
let bx = rad * Math.cos(srad) + 0.5; | |
let by = rad * Math.sin(srad) + 0.5; | |
let cx = this.hypot * Math.cos(mrad1) + 0.5; | |
let cy = this.hypot * Math.sin(mrad1) + 0.5; | |
let dx = this.hypot * Math.cos(mrad2) + 0.5; | |
let dy = this.hypot * Math.sin(mrad2) + 0.5; | |
let ex = rad * Math.cos(mrad3) + 0.5; | |
let ey = rad * Math.sin(mrad3) + 0.5; | |
let fx = rad * Math.cos(mrad4) + 0.5; | |
let fy = rad * Math.sin(mrad4) + 0.5; | |
let mx = this.hypot * Math.cos(mrad) + 0.5; | |
let my = this.hypot * Math.sin(mrad) + 0.5; | |
this.context.beginPath(); | |
this.context.arc(x, y, relrad, srad, erad, false); | |
this.context.lineTo(this.rel(ax), this.rel(ay)); | |
this.context.lineTo(this.rel(cx), this.rel(cy)); | |
this.context.arc( | |
this.rel(0.5), this.rel(0.5), | |
this.relS(this.hypot), mrad1, mrad2, false | |
); | |
// this.context.lineTo(this.rel(dx), this.rel(dy)); | |
this.context.lineTo(this.rel(bx), this.rel(by)); | |
this.context.closePath(); | |
this.context.fill(); | |
this.context.stroke(); | |
this.context.beginPath(); | |
this.context.moveTo(this.rel(ex), this.rel(ey)); | |
this.context.lineTo(this.rel(mx), this.rel(my)); | |
this.context.lineTo(this.rel(fx), this.rel(fy)); | |
this.context.stroke(); | |
this.context.beginPath(); | |
this.context.arc(x, y, relrad, this.dToR(0), this.dToR(360), false); | |
this.context.stroke(); | |
} | |
circ(x, y, rad, stroke = "red") { | |
this.context.strokeStyle = stroke; | |
this.context.beginPath(); | |
this.context.arc(this.rel(x), this.rel(y), this.relS(rad), 0, PI2); | |
this.context.stroke(); | |
} | |
rect(x, y, w, h, stroke = "red") { | |
this.context.strokeStyle = stroke; | |
this.context.lineWidth = 2; | |
this.context.strokeRect( | |
this.rel(x), | |
this.rel(y), | |
this.relS(w), | |
this.relS(h) | |
); | |
} | |
get relativeS() { | |
return this.diameter - this.gutter * 2; | |
} | |
relS(size) { | |
return size * this.relativeS; | |
} | |
rel(plot) { | |
return this.relS(plot) + this.gutter; | |
} | |
} | |
class Radar { | |
constructor(points) { | |
this.canvas = new Canvas(); | |
this.canvas.switchContext(0); | |
this.canvas.grid(); | |
this.draw(points); | |
this.canvas.switchContext(1); | |
this.ticker = 0; | |
this.step = 1; | |
this.tick() | |
} | |
draw(points) { | |
points.forEach(({ x, y }) => { | |
this.canvas.point(x, y, 'white'); | |
}); | |
} | |
tick() { | |
let offset = 270; | |
let deg = (this.ticker % 360) + offset; | |
let rotations = 4; | |
let outof = rotations * 360; | |
let rat = Math.pow((this.ticker % outof) / outof, PI); | |
let rad = rat * 0.5; | |
// console.log(deg, rad) | |
this.canvas.clear(1); | |
let c1 = 'hsla(70,100%,40%,1)'; | |
let c2 = 'hsla(70,100%,60%,0.5)'; | |
this.canvas.cone(deg, rad, rat, c1, c2); | |
this.ticker += this.step; | |
window.requestAnimationFrame(() => this.tick()); | |
} | |
} | |
let points = []; | |
for (let i = 0; i < 10; i++) { | |
points.push(new Point()); | |
} | |
let radar = new Radar(points); |
body { | |
background: #121212; | |
} | |
header { | |
text-align: center; | |
margin: 1rem 0; | |
} | |
div { | |
position: relative; | |
margin: 1rem auto; | |
width: 95%; | |
max-width: 600px; | |
canvas { | |
&:first-child { | |
background: black; | |
} | |
position: absolute; | |
top: 0; left: 50%; | |
transform: translateX(-50%); | |
width: 100%; | |
height: auto; | |
} | |
} |
A concept for how to connect vectors radially and proximally using vector grouping. These groups would be determined at the vector level by doing calculations on the vector's radial position.
A Pen by HARUN PEHLİVAN on CodePen.