#javascript #svg #анимация #canvas
Всем привет! Подскажите, пожалуйста: какая технология используется для реализации кнопки меню как на сайте https://www.panoply.co.uk/? Заказчик просит скопировать.. Вижу что canvas, но не могу понять в ручную ли написан код или может фреймворк какой.. Заранее благодарен за любую информацию.
Ответы
Ответ 1
Вот собрал вам нечто похожее из подручных средств, в этом примере нет WebGL, все посчитано и нарисовано через 2d контекст. let ctx = canvas.getContext('2d'); let k = 300, a1 = 0, a2 = 0, dir = 0, far = 300, w = canvas.width, h = canvas.height, planes = []; ctx.translate(w/2, h/2); for (var i=-20; i<21; i+=20) { addRect(10,10,20,i,-20) addRect(10,10,-20,i,-20) addDiag(15,10,20,i,-20) addDiag(-15,10,20,i,-20) } addTopDiag(25,15,-25,20) addTopDiag(-25,-15,-25,20) function addTopDiag(x1,x2,dy,dz) { whitePlane([ pt(-x1, dy, -dz), pt(-x2, dy, -dz), pt(x1, dy, dz), pt(x2, dy, dz) ]); } function addDiag(w, h, dx=0, dy=0, dz=0){ whitePlane([ pt(0, h/2+dy, -5), pt(0, -h/2+dy, -5), pt(w, -h/2+dy, dz), pt(w, h/2+dy, dz) ]); } function addRect(w, h, dx=0, dy=0, dz=0){ whitePlane([ pt(-w/2+dx, -h/2+dy, dz), pt(-w/2+dx, h/2+dy, dz), pt(w/2+dx, h/2+dy, dz), pt(w/2+dx, -h/2+dy,dz) ]); } requestAnimationFrame(render) function whitePlane(points){ planes.push({color: 'white', points}); } function pt(x,y,z) { return {x, y, z}; } function project(p) { let sinA1 = Math.sin(a1), cosA1 = Math.cos(a1); let sinA2 = Math.sin(a2), cosA2 = Math.cos(a2); let x = p.x*cosA1 + p.z*sinA1; let z = p.z*cosA1 - p.x*sinA1; let y = p.y*cosA2 + z*sinA2; let kd = k/(z*cosA2 - p.y*sinA2 + far); p.X = kd*x; p.Y = kd*y; } function render() { a2 += dir * 0.1; if (a2 < -Math.PI/2 || a2 > 0) { dir = 0; a2 = a2 > 0 ? 0 : -Math.PI/2; } if (a2 < 0 && a2 > -Math.PI/2) requestAnimationFrame(render); planes.forEach(plane => plane.points.forEach(project)); ctx.clearRect(-w/2, -h/2, w, h); planes.forEach(drawPlane); } function drawPlane(plane) { ctx.fillStyle = plane.color; ctx.beginPath(); ctx.moveTo(plane.points[0].X, plane.points[0].Y); for (var i = 1; i < plane.points.length; i++) ctx.lineTo(plane.points[i].X, plane.points[i].Y); ctx.fill(); ctx.closePath(); } function toggle() { if (a2 < 0 && a2 > -Math.PI/2) return; dir = a2 === 0 ? -1 : 1 requestAnimationFrame(render); } body { background: url(https://picsum.photos/id/22/700/200); } canvas { cursor: pointer; }Ответ 2
В отличие от соседнего ответа, посчитал почти все точки по формуле и нарисовал при помощи SVG... let cos = Math.cos, sin = Math.sin, k = 1000, a1 = 0, a2 = 0, far = 1000, dir = 0, planes = []; let pts = Array(8).fill(0).map((e, i) => { let a = Math.PI*(.25+.5*Math.floor(i/2)) + (i%2?.2:-.2); return [cos(a)*30, sin(a)*30]; }); let t = -25; whitePlane([pt(0,t),pt(1,t),pt(4,t),pt(5,t)]) whitePlane([pt(2,t),pt(3,t),pt(6,t),pt(7,t)]) for (var i=0; i<3;i++){ let t2 = t+20*i; let t3 = -15+20*i; whitePlane([ pt(4,t2),pt(5,t2),{x:0,y:t2,z:-7},pt(6,t2),pt(7,t2), pt(7,t3),pt(6,t3),{x:0,y:t3,z:-7},pt(5,t3),pt(4,t3), ]) } requestAnimationFrame(render) function whitePlane(points) { let id = "plane_" + planes.length; svg.innerHTML += ``; planes.push({points, id}); } function pt(i, y=0) { return {x:pts[i][0], y, z:pts[i][1]}; } function project(p) { let x = p.x*cos(a1) + p.z*sin(a1); let z = p.z*cos(a1) - p.x*sin(a1); let y = p.y*cos(a2) + z*sin(a2); let d = z*cos(a2) - p.y*sin(a2) + far; return [ (k/d)*x ,(k/d)*y ]; } function render() { a2 += dir * 0.1 if (a2 < -Math.PI/2 || a2 > 0){ dir = 0; a2 = a2 > 0 ? 0 : -Math.PI/2; } dir !== 0 && requestAnimationFrame(render) planes.forEach(plane => window[plane.id] .setAttribute("points", plane.points.map(project))); } function toggle() { if (dir !== 0) return; requestAnimationFrame(render); dir = a2 === 0 ? -1 : 1 } body { background-color: black; overflow: hidden; } svg { width: 200px; height: 200px; cursor: pointer; } polygon { fill: white; }
Комментариев нет:
Отправить комментарий