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.