Две недофункции для canvas
Хотя символ года ими вполне можно нарисовать (нужен включённый яваскрипт и браузер с поддержкой тега <canvas>
, чтобы ниже появилась картинка):
Проблемы в том, что drawEllipse
проста, но не поворачивает эллипсы, а
drawRoundedPoly
рисует многоугольники с закруглёнными углами, но не стоит от неё ждать одновременной корректной работы с
fill
(заливкой) и stroke
(линиями) даже в простых случаях :( Обе функции основаны на решениях из инета, лишь слегка подправил, но не выправил до конца...
Листинг с комментариями - под катом, в качестве памятки.
<div align="center"> <canvas id="pigCanvas" width="350" height="350" style="background-color:#ffffff; border: 1px solid #333333; margin:10px;"> </canvas> </div> <script> function drawEllipse (ctx, x, y, a, b) { /* ctx – контекст отрисовки x, y – центр эллипса a – большая полуось (горизонтальный радиус) b – малая полуось (вертикальный радиус) Функция не обязана корректно выполнять вместе fill и stroke :) */ ctx.save(); ctx.beginPath(); ctx.translate(x, y); ctx.scale(a / b, 1); ctx.arc(0, 0, b, 0, Math.PI * 2, true); ctx.fill(); ctx.stroke(); ctx.closePath(); ctx.restore(); } function drawRoundedPoly (ctx, points, radiusAll) { /* ctx – контекст отрисовки points - массив точек вида [{x :?, y: ?},... radiusAll - максимальный радиус закругления угла */ var i, x, y, len, p1, p2, p3, v1, v2, sinA, sinA90, radDirection, drawDirection, angle, halfAngle, cRadius, lenOut,radius; var asVec = function(p, pp, v) { //конвертирует пару точек в векторную форму, полярную форму и нормализует v.x = pp.x - p.x; v.y = pp.y - p.y; v.len = Math.sqrt(v.x * v.x + v.y * v.y); v.nx = v.x / v.len; v.ny = v.y / v.len; v.ang = Math.atan2(v.ny, v.nx); } ctx.save(); ctx.beginPath(); radius = radiusAll; v1 = {}; v2 = {}; len = points.length; p1 = points[len - 1]; for (i = 0; i < len; i++) { p2 = points[(i) % len]; p3 = points[(i + 1) % len]; // Part 1 asVec(p2, p1, v1); asVec(p2, p3, v2); sinA = v1.nx * v2.ny - v1.ny * v2.nx; sinA90 = v1.nx * v2.nx - v1.ny * -v2.ny; angle = Math.asin(sinA); radDirection = 1; drawDirection = false; if (sinA90 < 0) { if (angle < 0) { angle = Math.PI + angle; } else { angle = Math.PI - angle; radDirection = -1; drawDirection = true; } } else { if (angle > 0) { radDirection = -1; drawDirection = true; } } if (p2.radius !== undefined) { radius = p2.radius; } else { radius = radiusAll; } // Part 2 halfAngle = angle / 2; // Part 3 lenOut = Math.abs(Math.cos(halfAngle) * radius / Math.sin(halfAngle)); // Special part A if (lenOut > Math.min(v1.len / 2, v2.len / 2)) { lenOut = Math.min(v1.len / 2, v2.len / 2); cRadius = Math.abs(lenOut * Math.sin(halfAngle) / Math.cos(halfAngle)); } else { cRadius = radius; } // Part 4 x = p2.x + v2.nx * lenOut; y = p2.y + v2.ny * lenOut; // Part 5 x += -v2.ny * cRadius * radDirection; y += v2.nx * cRadius * radDirection; // Part 6 ctx.arc (x, y, cRadius, v1.ang + Math.PI / 2 * radDirection, v2.ang - Math.PI / 2 * radDirection, drawDirection); p1 = p2; p2 = p3; } ctx.fill(); ctx.stroke(); ctx.closePath(); ctx.restore(); } var canvas = document.getElementById("pigCanvas"); var ctx = canvas.getContext("2d"); ctx.lineWidth = 3.0; //голова: ctx.fillStyle = "#fbd2ce"; ctx.strokeStyle = "#000000"; drawEllipse (ctx, 170, 188, 113, 96); //глаза: ctx.fillStyle = "#000000"; drawEllipse (ctx, 143, 172, 12, 19); drawEllipse (ctx, 198, 172, 12, 19); //пятак: ctx.fillStyle = "#000000"; drawEllipse (ctx, 170, 233, 41, 28); ctx.fillStyle = "#fbd2ce"; drawEllipse (ctx, 170, 233, 38, 25); ctx.fillStyle = "#000000"; drawEllipse (ctx, 157, 233, 8, 11); drawEllipse (ctx, 183, 233, 8, 11); //уши: ctx.fillStyle = "#fbd2ce"; var e1 = [{x:141,y:98},{x:58,y:68},{x:82,y:135}]; drawRoundedPoly (ctx,e1,8); var e2 = [{x:209,y:98},{x:292,y:68},{x:268,y:135}]; drawRoundedPoly (ctx,e2,8); </script> <noscript>You need Javascript to run it</noscript>
04.01.2019, 17:30 [1686 просмотров]