БлогNot. Две недофункции для canvas

Две недофункции для 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 просмотров]


теги: графика ошибка javascript памятка программирование

К этой статье пока нет комментариев, Ваш будет первым