웹 프론트엔드 H5 튜토리얼 캔버스의 임의의 점을 기반으로 다각형을 그리는 방법

캔버스의 임의의 점을 기반으로 다각형을 그리는 방법

Jun 14, 2018 am 09:19 AM
canvas 다각형 그리다

이 글은 캔버스의 임의의 점을 기반으로 다각형을 그리는 방법에 대한 관련 정보를 주로 소개합니다. 내용이 꽤 좋아서 지금 공유하고 참고하겠습니다.

Cause

오늘 "HTML5+Javascript Animation Basics" 책을 공부하던 중 8장 3절에서 세 개의 스프링을 이용해 세 점을 연결해 스트레칭 동작을 하는 방법에 대해 이야기했습니다.

예시를 마치고 4점, 5점이면 어떨까 생각해봤습니다.

코드를 다시 작성하고 포인트 개수를 가변적으로 만들었습니다. 최종 효과는 균형을 맞추기 위해 각 점의 최종 스트레칭 동작을 달성하는 것이지만 점 사이의 연결이 그다지 좋지 않고 일부가 교차됩니다.

그래서 이 부분을 최적화할 수 있지 않을까 생각해봤습니다.

연결 회전

이전 예의 포인트는 모두 임의의 위치에 있으므로 연결을 제어할 수 없습니다. 그래서 저는 이것부터 먼저 시작하고 싶습니다.

먼저 특정 점을 기준점으로 사용하여 이 점을 기준으로 하는 다른 점의 각도를 구합니다.

그런 다음 작은 각도에서 큰 각도에 따라 이 점들을 연결하면 일반 다각형을 그릴 수 있습니다.

대략적인 구현 코드는 다음과 같습니다.

let balls = [];
let ballNum = 6;
let firstBall = null;
while(ballNum--) {
  let ball = new Ball(20, parseColor(Math.random() * 0xffffff))
  ball.x = Math.random() * width;
  ball.y = Math.random() * height;
  balls.push(ball)

  if (!firstBall) {
    firstBall = ball
    ball.angle = 0
  } else {
    const dx = ball.x - firstBall.x,
          dy = ball.y - firstBall.y;

    ball.angle = Math.atan2(dy, dx);
  }
}

// 尝试让球连线是一个正多边形
balls = balls.sort((ballA, ballB) => {
  return ballA.angle - ballB.angle
})
로그인 후 복사

이렇게 하면 마지막에 연결을 그릴 때 배열을 가로질러 작은 각도에서 큰 각도로 그릴 수 있습니다.

효과는 다음과 같습니다.

이를 통해 선을 넘는 상황을 크게 줄일 수 있지만 여전히 완전히 피할 수는 없습니다.

다음으로 Math.abs를 사용하여 각도를 수정하거나 각 점을 연결하기 위해 가장 작은 각도의 점을 찾는 등 이 솔루션을 최적화하려고 합니다. 하지만 결과는 좋지 않고, 선을 넘는 것도 피할 수 없습니다.

중심점을 기준으로 회전

나중에 또 다른 아이디어가 떠올랐습니다. 다각형의 중심점이 결정되면 중심점을 기준으로 모든 점의 각도를 별도로 계산할 수 있습니다. 포인트는 시계 방향 또는 시계 반대 방향으로 연결될 수 있습니다.

하지만 인터넷에서 오랫동안 검색한 결과 모든 포인트 알고리즘에는 특정 시계 방향 순서로 배열된 일련의 포인트가 필요합니다.

하지만 이 점이 있으면 이미 다각형을 그릴 수 있습니다.

X축 극 분할

을 포기해야 했습니다. 절망에 빠져 Google을 검색하다가 Zhihu에서 좋은 답변을 찾았습니다. 평면 위의 정렬되지 않은 점 집합을 연결하는 방법 단순한 다각형?

구체적인 알고리즘 설명은 답변만 참고하시면 됩니다. 자세한 내용은 다루지 않겠습니다.

단, 상부 체인과 하부 체인을 연결할 때 실제로는 상부 체인이 X축을 기준으로 내림차순으로 연결되고, 하부 체인이 X축을 기준으로 오름차순으로 연결되어 있는지 확인하기만 하면 됩니다( 시계 반대 방향으로 그려집니다.) X축이 동일한 점의 경우 Y축이 더 크거나 작은지는 중요하지 않습니다.

구현 시 답변에 나온 알고리즘에 따라 엄격하게 구현됩니다.

한 점이 상위 체인에 속하는지 하위 체인에 속하는지 판단할 때 가장 먼저 생각해야 할 것은 두 점을 기준으로 직선의 함수 방정식을 결정한 다음 계산할 점의 좌표를 도입하는 것입니다. 그런데 나중에 생각해보니 모든 점은 가장 왼쪽 극을 이용해서 경사각을 계산한 뒤 이를 각도 크기에 따라 나누는 게 시각적으로 이해하기 쉽더라고요.

대략적인 코드는 다음과 같습니다.

let balls = [];
let tempBalls = [];
let ballNum = 6;
let isDragingBall = false;

while(ballNum--) {
  let ball = new Ball(10, parseColor(Math.random() * 0xffffff))
  ball.x = Math.random() * width;
  ball.y = Math.random() * height;
  tempBalls.push(ball)
}

// 让点按X轴升序排序
tempBalls = tempBalls.sort((ballA, ballB) => {
  return ballA.x - ballB.x
})

// 找X轴左右极点
let firstBall = tempBalls[0],
    lastBall = tempBalls[tempBalls.length -1];
let smallXBalls = tempBalls.filter(ball => ball.x === firstBall.x),
    bigXBalls = tempBalls.filter(ball => ball.x === lastBall.x)

// 处理左右极点有多个的情况
if (smallXBalls.length > 1) {
  smallXBalls.sort((ballA, ballB) => {
    return ballB.y - ballA.y
  })
}
if (bigXBalls.length > 1) {
  bigXBalls.sort((ballA, ballB) => {
    return ballB.y - ballA.y
  })
}

firstBall = smallXBalls[0]
lastBall = bigXBalls[0]

// 获得极点连线的角度
let splitLineAngle = Math.atan2(lastBall.y - firstBall.y, lastBall.x - firstBall.x);
let upperBalls = [],
    lowerBalls = [];

// 所有其他点跟firstBall计算角度
// 大于splitLineAngle的都是下链
// 其他是上链
tempBalls.forEach(ball => {
  if (ball === firstBall || ball === lastBall) {
    return false
  }
  let angle = Math.atan2(ball.y - firstBall.y, ball.x - firstBall.x);
  if (angle > splitLineAngle) {
    lowerBalls.push(ball)
  } else {
    upperBalls.push(ball)
  }
})

// 处理X轴相同情况的排序
lowerBalls = lowerBalls.sort((ballA, ballB) => {
  if (ballA.x !== ballB.x) {
    return ballA.x - ballB.x
  }
  return ballB.y - ballA.y
})

upperBalls = upperBalls.sort((ballA, ballB) => {
  if (ballA.x !== ballB.x) {
    return ballB.x - ballA.x
  }
  return ballB.y - ballB.x
})

// 逆时针连接所有的点
balls = [firstBall].concat(lowerBalls, [lastBall], upperBalls)

balls = balls.map((ball, i) => {
  ball.text = i + 1;
  return ball
})
로그인 후 복사

드디어 반환된 공은 시계 반대 방향으로 정렬된 다각형의 점입니다.

효과는 다음과 같습니다.

각 공의 내부 상태는 다음과 같습니다.

위 내용은 모두의 학습에 도움이 되기를 바랍니다. 관련 내용은 PHP 중국어 웹사이트를 주목해주세요!

관련 권장사항:

html5 사용 Canvas는 echart가 구현할 수 없는 원형 차트를 캡슐화합니다

HTML5 Canvas는 곡선을 그리는 방법을 구현합니다

위 내용은 캔버스의 임의의 점을 기반으로 다각형을 그리는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

건축 ppt로 평면도를 직접 그릴 수 있나요? 건축 ppt로 평면도를 직접 그릴 수 있나요? Mar 20, 2024 am 08:43 AM

ppt는 특히 교육, 건축 등 다양한 분야와 업무에서 널리 사용됩니다. 건축 ppt를 할 때 먼저 건축 도면의 프레젠테이션을 생각해야 합니다. 전문적인 도면 소프트웨어를 사용하지 않는 경우 간단한 건축 계획을 직접 그릴 수 있습니까? 사실 여기서 작업을 완료할 수 있는데, 아래에서는 이 아이디어를 바탕으로 비교적 간단한 평면도를 그려보도록 하겠습니다. 1. 먼저 두 번 클릭하여 데스크탑에서 ppt 소프트웨어를 열고 클릭하여 새 프레젠테이션 빈 문서를 만듭니다. 2. 메뉴 표시 줄에서 삽입 → 모양 → 직사각형을 찾습니다. 3. 직사각형을 그린 후 그래픽을 두 번 클릭하고 채우기 색상 유형을 수정합니다.

칠각형 수 칠각형 수 Sep 24, 2023 am 10:33 AM

칠각형 숫자는 칠각형으로 표현될 수 있는 숫자입니다. 칠각형 숫자는 칠각형으로 표현될 수 있습니다. 칠각형 숫자는 칠각형(7면 다각형)의 연속적인 레이어의 조합으로 표현될 수 있습니다. 칠각형 숫자는 아래 그림으로 더 잘 설명될 수 있습니다. 그러므로,

Python으로 3D 지리 차트를 그리는 방법 Python으로 3D 지리 차트를 그리는 방법 Sep 28, 2023 am 10:19 AM

Python으로 3D 지리 차트를 그리는 방법 개요: 3D 지리 차트를 그리는 것은 지리 데이터와 공간 분포를 보다 직관적으로 이해하는 데 도움이 될 수 있습니다. 강력하고 사용하기 쉬운 프로그래밍 언어인 Python은 다양한 유형의 지리 차트를 그리는 데 사용할 수 있는 많은 라이브러리와 도구를 제공합니다. 이 기사에서는 Python 프로그래밍 언어와 Matplotlib 및 Basemap과 같은 일부 인기 있는 라이브러리를 사용하여 3D 지리 차트를 그리는 방법을 알아봅니다. 환경 준비: 시작하기 전에 다음 사항을 확인해야 합니다.

5분 안에 Python으로 덴드로그램과 방사형 차트를 그리는 방법을 알아보세요. 5분 안에 Python으로 덴드로그램과 방사형 차트를 그리는 방법을 알아보세요. Sep 27, 2023 pm 12:48 PM

데이터 시각화에서 덴드로그램과 방사형 차트는 일반적으로 사용되는 두 가지 차트 형식입니다. 트리맵은 계층 구조를 표시하는 데 사용되는 반면 방사형 차트는 여러 차원의 데이터를 비교하는 데 사용됩니다. 이 기사에서는 Python을 사용하여 이 두 차트를 그리는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 1. 덴드로그램 그리기 Python에는 matplotlib 및 graphviz와 같이 덴드로그램을 그리는 데 사용할 수 있는 여러 라이브러리가 있습니다. 다음은 matplotlib 라이브러리를 예시로 사용하여 보여줍니다.

캔버스 프레임워크를 배우고 일반적으로 사용되는 캔버스 프레임워크에 대해 자세히 설명합니다. 캔버스 프레임워크를 배우고 일반적으로 사용되는 캔버스 프레임워크에 대해 자세히 설명합니다. Jan 17, 2024 am 11:03 AM

Canvas 프레임워크 탐색: 일반적으로 사용되는 Canvas 프레임워크가 무엇인지 이해하려면 특정 코드 예제가 필요합니다. 소개: Canvas는 풍부한 그래픽 및 애니메이션 효과를 얻을 수 있는 HTML5에서 제공되는 그리기 API입니다. 그리기의 효율성과 편의성을 향상시키기 위해 많은 개발자들이 다양한 Canvas 프레임워크를 개발했습니다. 이 기사에서는 일반적으로 사용되는 몇 가지 캔버스 프레임워크를 소개하고 독자가 이러한 프레임워크를 사용하는 방법을 더 깊이 이해하는 데 도움이 되는 특정 코드 예제를 제공합니다. 1. EaselJS 프레임워크 Ea

html2canvas에는 어떤 버전이 있나요? html2canvas에는 어떤 버전이 있나요? Aug 22, 2023 pm 05:58 PM

html2canvas 버전에는 html2canvas v0.x, html2canvas v1.x 등이 포함됩니다. 자세한 소개: 1. html2canvas v0.x는 html2canvas의 초기 버전입니다. 최신 안정 버전은 v0.5.0-alpha1입니다. 2. html2canvas v1.x는 html2canvas의 새 버전입니다.

uniapp은 캔버스를 사용하여 차트와 애니메이션 효과를 그리는 방법을 구현합니다. uniapp은 캔버스를 사용하여 차트와 애니메이션 효과를 그리는 방법을 구현합니다. Oct 18, 2023 am 10:42 AM

uniapp에서 캔버스를 사용하여 차트와 애니메이션 효과를 그리는 방법에는 특정 코드 예제가 필요합니다. 1. 소개 모바일 장치의 인기로 인해 점점 더 많은 응용 프로그램이 모바일 단말기에 다양한 차트와 애니메이션 효과를 표시해야 합니다. Vue.js를 기반으로 하는 크로스 플랫폼 개발 프레임워크인 uniapp은 캔버스를 사용하여 차트와 애니메이션 효과를 그리는 기능을 제공합니다. 이 기사에서는 uniapp이 캔버스를 사용하여 차트 및 애니메이션 효과를 구현하는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 2. 캔버스

Python으로 애니메이션 차트를 그리는 방법 Python으로 애니메이션 차트를 그리는 방법 Sep 27, 2023 am 09:53 AM

Python으로 애니메이션 차트 그리는 방법 강력한 프로그래밍 언어인 Python은 다양한 데이터 시각화 및 차트 그리기에 사용할 수 있습니다. 그 중 애니메이션 차트를 그리는 것은 데이터를 더욱 생생하고 흥미롭게 만들 수 있습니다. 이 기사에서는 Python을 사용하여 애니메이션 차트를 그리는 방법을 소개하고 구체적인 코드 예제를 제공합니다. 먼저 Python에서 가장 일반적으로 사용되는 차트 라이브러리 중 하나인 matplotlib 라이브러리를 설치해야 합니다. matplotlib를 설치하려면 터미널에서 다음 명령을 실행하십시오: pipinsta

See all articles