1 2// Button active class 3 4 5let canvas, ctx; 6let render, init; 7let blob; 8 9class Blob { 10 constructor() { 11 this.points = []; 12 } 13 14 init() { 15 for(let i = 0; i < this.numPoints; i++) { 16 let point = new Point(this.divisional * ( i + 1 ), this); 17 // point.acceleration = -1 + Math.random() * 2; 18 this.push(point); 19 } 20 } 21 22 render() { 23 let canvas = this.canvas; 24 let ctx = this.ctx; 25 let position = this.position; 26 let pointsArray = this.points; 27 let radius = this.radius; 28 let points = this.numPoints; 29 let divisional = this.divisional; 30 let center = this.center; 31 32 ctx.clearRect(0,0,canvas.width,canvas.height); 33 34 pointsArray[0].solveWith(pointsArray[points-1], pointsArray[1]); 35 36 let p0 = pointsArray[points-1].position; 37 let p1 = pointsArray[0].position; 38 let _p2 = p1; 39 40 ctx.beginPath(); 41 ctx.moveTo(center.x, center.y); 42 ctx.moveTo( (p0.x + p1.x) / 2, (p0.y + p1.y) / 2 ); 43 44 for(let i = 1; i < points; i++) { 45 46 pointsArray[i].solveWith(pointsArray[i-1], pointsArray[i+1] || pointsArray[0]); 47 48 let p2 = pointsArray[i].position; 49 var xc = (p1.x + p2.x) / 2; 50 var yc = (p1.y + p2.y) / 2; 51 ctx.quadraticCurveTo(p1.x, p1.y, xc, yc); 52 // ctx.lineTo(p2.x, p2.y); 53 54 ctx.fillStyle = '#000000'; 55 // ctx.fillRect(p1.x-2.5, p1.y-2.5, 5, 5); 56 57 p1 = p2; 58 } 59 60 var xc = (p1.x + _p2.x) / 2; 61 var yc = (p1.y + _p2.y) / 2; 62 ctx.quadraticCurveTo(p1.x, p1.y, xc, yc); 63 // ctx.lineTo(_p2.x, _p2.y); 64 65 // ctx.closePath(); 66 ctx.fillStyle = this.color; 67 ctx.fill(); 68 ctx.strokeStyle = '#000000'; 69 // ctx.stroke(); 70 71/* 72 ctx.fillStyle = '#000000'; 73 if(this.mousePos) { 74 let angle = Math.atan2(this.mousePos.y, this.mousePos.x) + Math.PI; 75 ctx.fillRect(center.x + Math.cos(angle) * this.radius, center.y + Math.sin(angle) * this.radius, 5, 5); 76 } 77*/ 78 requestAnimationFrame(this.render.bind(this)); 79 } 80 81 push(item) { 82 if(item instanceof Point) { 83 this.points.push(item); 84 } 85 } 86 87 set color(value) { 88 this._color = value; 89 } 90 get color() { 91 return this._color || '#000000'; 92 } 93 94 set canvas(value) { 95 if(value instanceof HTMLElement && value.tagName.toLowerCase() === 'canvas') { 96 this._canvas = canvas; 97 this.ctx = this._canvas.getContext('2d'); 98 } 99 } 100 get canvas() { 101 return this._canvas; 102 } 103 104 set numPoints(value) { 105 if(value > 2) { 106 this._points = value; 107 } 108 } 109 get numPoints() { 110 return this._points || 32; 111 } 112 113 set radius(value) { 114 if(value > 0) { 115 this._radius = value; 116 } 117 } 118 get radius() { 119 return this._radius || 150; 120 } 121 122 set position(value) { 123 if(typeof value == 'object' && value.x && value.y) { 124 this._position = value; 125 } 126 } 127 get position() { 128 return this._position || { x: 0.5, y: 0.5 }; 129 } 130 131 get divisional() { 132 return Math.PI * 2 / this.numPoints; 133 } 134 135 get center() { 136 return { x: this.canvas.width * this.position.x, y: this.canvas.height * this.position.y }; 137 } 138 139 set running(value) { 140 this._running = value === true; 141 } 142 get running() { 143 return this.running !== false; 144 } 145} 146 147class Point { 148 constructor(azimuth, parent) { 149 this.parent = parent; 150 this.azimuth = Math.PI - azimuth; 151 this._components = { 152 x: Math.cos(this.azimuth), 153 y: Math.sin(this.azimuth) 154 }; 155 156 this.acceleration = -0.3 + Math.random() * 0.6; 157 } 158 159 solveWith(leftPoint, rightPoint) { 160 this.acceleration = (-0.3 * this.radialEffect + ( leftPoint.radialEffect - this.radialEffect ) + ( rightPoint.radialEffect - this.radialEffect )) * this.elasticity - this.speed * this.friction; 161 } 162 163 set acceleration(value) { 164 if(typeof value == 'number') { 165 this._acceleration = value; 166 this.speed += this._acceleration * 2; 167 } 168 } 169 get acceleration() { 170 return this._acceleration || 0; 171 } 172 173 set speed(value) { 174 if(typeof value == 'number') { 175 this._speed = value; 176 this.radialEffect += this._speed * 5; 177 } 178 } 179 get speed() { 180 return this._speed || 0; 181 } 182 183 set radialEffect(value) { 184 if(typeof value == 'number') { 185 this._radialEffect = value; 186 } 187 } 188 get radialEffect() { 189 return this._radialEffect || 0; 190 } 191 192 get position() { 193 return { 194 x: this.parent.center.x + this.components.x * (this.parent.radius + this.radialEffect), 195 y: this.parent.center.y + this.components.y * (this.parent.radius + this.radialEffect) 196 } 197 } 198 199 get components() { 200 return this._components; 201 } 202 203 set elasticity(value) { 204 if(typeof value === 'number') { 205 this._elasticity = value; 206 } 207 } 208 get elasticity() { 209 return this._elasticity || 0.001; 210 } 211 set friction(value) { 212 if(typeof value === 'number') { 213 this._friction = value; 214 } 215 } 216 get friction() { 217 return this._friction || 0.03; 218 //return this._friction || 0.0085; 219 } 220} 221 222blob = new Blob; 223 224init = function() { 225 canvas = document.createElement('canvas'); 226 canvas.setAttribute('touch-action', 'none'); 227 var container = document.querySelector('.watch_btn') 228 container.appendChild(canvas); 229 230 let resize = function() { 231 canvas.width = window.innerWidth; 232 canvas.height = window.innerHeight; 233 } 234 window.addEventListener('resize', resize); 235 resize(); 236 237 let oldMousePoint = { x: 0, y: 0}; 238 let hover = false;
239 let mouseMove = function(e) { 240 241 let pos = blob.center; 242 let diff = { x: e.clientX - pos.x, y: e.clientY - pos.y }; 243 let dist = Math.sqrt((diff.x * diff.x) + (diff.y * diff.y)); 244 let angle = null; 245 246 blob.mousePos = { x: pos.x - e.clientX, y: pos.y - e.clientY }; 247 248 if(dist < blob.radius && hover === false) { 249 let vector = { x: e.clientX - pos.x, y: e.clientY - pos.y }; 250 angle = Math.atan2(vector.y, vector.x); 251 hover = true; 252 // blob.color = '#77FF00'; 253 } else if(dist > blob.radius && hover === true){ 254 let vector = { x: e.clientX - pos.x, y: e.clientY - pos.y }; 255 angle = Math.atan2(vector.y, vector.x); 256 hover = false; 257 blob.color = null; 258 } 259 260 if(typeof angle == 'number') { 261 262 let nearestPoint = null; 263 let distanceFromPoint = 100; 264 265 blob.points.forEach((point)=> { 266 if(Math.abs(angle - point.azimuth) < distanceFromPoint) { 267 // console.log(point.azimuth, angle, distanceFromPoint); 268 nearestPoint = point; 269 distanceFromPoint = Math.abs(angle - point.azimuth); 270 } 271 272 }); 273 274 if(nearestPoint) { 275 let strength = { x: oldMousePoint.x - e.clientX, y: oldMousePoint.y - e.clientY }; 276 strength = Math.sqrt((strength.x * strength.x) + (strength.y * strength.y)) * 10; 277 if(strength > 100) strength = 100; 278 nearestPoint.acceleration = strength / 100 * (hover ? -1 : 1); 279 } 280 } 281 282 oldMousePoint.x = e.clientX; 283 oldMousePoint.y = e.clientY; 284 } 285 // window.addEventListener('mousemove', mouseMove); 286 window.addEventListener('pointermove', mouseMove); 287 288 blob.canvas = canvas; 289 blob.init(); 290 blob.render(); 291} 292 293init();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.