Как нарисовать шесть линий, симметрично расположенных по радиусу в Canvas? - PullRequest
2 голосов
/ 07 января 2020

Я пытаюсь создать приложение для рисования снежинок в Canvas, очень похожее на это: http://www.pumpkinpirate.info/ks/.

Обычно, если вы рисуете точку, ее нужно повторить еще 5 раз в виде симметричного круга на холсте. Вот иллюстрация:

snowflake concept

Я знаю, как сказать холсту рисовать что-то несколько раз, но мои математические навыки ограничены, и мне интересно, как рассчитать положение 5 скопированных точек по отношению к исходной.

Я думаю, что мне нужно найти середину холста и вычислить расстояние от него до положений x и y исходной точки. После этого я предполагаю, что, возможно, мне нужно найти радиус, если бы я должен был нарисовать круг из этой точки, а затем ... это когда моя голова начинает курить.

Мне интересно, могу ли я сделать что-то подобное к тому, что они здесь делают: Инвертировать координаты X и Y на HTML5 canvas

Только для фона я изначально начал с 6 обрезанных холстов, где 5 было повернуто, и скопировал бы первое один, но я понял, что этот подход на самом деле не работал, отчасти потому, что полотна слегка перекрывали друг друга (но были и другие проблемы).

Вот код, который у меня есть:

drawing = false;
startX = 0;
startY = 0;
imageData = null;

const canvas = document.getElementById("canvas");

canvas.addEventListener("mousedown", startPosition());
canvas.addEventListener("mouseup", endPosition());
canvas.addEventListener("mousemove", draw());

function startPosition(e) {
  const canvas = this;
  const ctx = canvas.getContext("2d");

  startX = e.clientX;
  startY = e.clientY;
  imageData = ctx.getImageData(0,0,canvas.width,canvas.height);
  drawing = true;
}

function endPosition(e) {
  const canvas = document.getElementById("canvas");
  const ctx = canvas.getContext("2d");

  ctx.lineWidth = 4;
  ctx.lineCap = "round";
  ctx.moveTo(startX, startY);
  ctx.lineTo(e.clientX, e.clientY);
  ctx.strokeStyle = '#ffffff';
  ctx.stroke();
  ctx.beginPath();

  drawing = false;
}
function draw(e) {
  const canvas = document.getElementById("canvas");
  const ctx = canvas.getContext("2d");

  if(!drawing) {
    return;
  }

  ctx.putImageData(imageData, 0, 0);
  ctx.lineWidth = 4;
  ctx.lineCap = "round";
  ctx.moveTo(startX, startY);
  ctx.lineTo(e.clientX, e.clientY);    
  ctx.strokeStyle = '#ffffff';
  ctx.stroke();
  ctx.beginPath();
  ctx.moveTo(e.clientX, e.clientY);

  //draw line 2
  ctx.moveTo(startX - 50, startY - 50);
  ctx.lineTo(e.clientX - 50, e.clientY - 50);
  ctx.stroke();
  ctx.beginPath();
  ctx.moveTo(e.clientX - 50, e.clientY - 50);

  //draw line 3
  ctx.moveTo(startX - 100, startY - 100);
  ctx.lineTo(e.clientX - 100, e.clientY - 100);
  ctx.stroke();
  ctx.beginPath();
  ctx.moveTo(e.clientX - 100, e.clientY - 100);
}

1 Ответ

2 голосов
/ 07 января 2020

Чтобы повернуть точку вокруг другой точки

const center = {x: 100, y: 100};   // Point to rotate around
const point = {x: ?, y: ?};        // Point to rotate
const rotate = (Math.PI * 2) / 5;  // Rotate 1/5th of 360


// Get the vector from center to point
const vx = point.x - center.x;
const vy = point.y - center.y;

// Get the transformation (2D uniform rotate)
const xAx = Math.cos(rotate);
const xAy = Math.sin(rotate); 

// Transform the vector (rotates) and translate back to center
const tx = vx * xAx - vy * xAy + center.x;
const ty = vx * xAy + vy * xAx + center.y;

Как функция

function rotate(point, center, rotate, result = {}) {
    const vx = point.x - center.x;
    const vy = point.y - center.y;
    const xAx = Math.cos(rotate);
    const xAy = Math.sin(rotate); 
    result.x = vx * xAx - vy * xAy + center.x;
    result.y = vx * xAy + vy * xAx + center.y;
    return result;
}

Чтобы создать 5 точек из 1, используя вышеуказанную функцию

const slices = 5; // number of rotations
const center = {x: 100, y: 100}; // center point

// Rotates point steps times around center
// Returns array of points
function rotateAll(point, steps, result = []) {
    const ang = Math.PI * 2 / steps;
    result.push(point);                      // Add first point
    for (let rot = 1; rot < steps; rot++) {  // Add remaining points
        result.push(rotate(point, center, rot * ang));
    }
    return result;
}

// Usage
const points = rotateAll({x: 10, y: 20}, slices);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...