当前位置:网站首页>Draw multiple polygons using canvas
Draw multiple polygons using canvas
2022-06-09 09:18:00 【⑥②】

Go straight to the code
HTML Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
html, body {
}
</style>
<script defer src="test.js"></script>
</head>
<body>
<canvas id="canvas" width="960" height="540"
style="width:960px;height:540px; background:url('https://img0.baidu.com/it/u=2183579431,409639925&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281');background-size: contain"></canvas>
</body>
<script>
</script>
</html>
JS Code
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d');
let clientX = 0, clientY = 0, // Coordinates of the mouse position
points = [], // Store the clicked coordinate node data
polygonFillStyle = 'rgba(255,0,0,.2)',
rectFillStyle = 'yellow',
lineStyle = 'red',
lineWidth = 3
ctx.lineJoin = 'round'
ctx.strokeStyle = lineStyle
ctx.lineWidth = lineWidth
/**
* Empty Canvas Content
*/
function clear() {
ctx.fillStyle = 'transparent'
ctx.clearRect(0, 0, canvas.width, canvas.height)
}
/**
* Initialize listening events
*/
function initEvent(){
// Monitor mouse movement events
canvas.addEventListener('mousemove', (e) => {
let {x,y} = windowToCanvas(e.clientX,e.clientY)
clientX = x
clientY = y
})
// Monitor mouse click events
canvas.addEventListener('click', (e) => {
let len = points.length
let cIndex = 0
// Initialize the storage node array
if (len === 0) {
points[cIndex] = []
} else {
cIndex = len - 1
if (typeof points[len - 1] === 'undefined') {
points[cIndex] = []
}
}
let lastPoints = points[cIndex]
let lastPointsLen = lastPoints.length
if (lastPointsLen === 0) {
// If space is 0 Words , Directly add
points[cIndex].push([clientX, clientY])
} else {
// If it's not zero , Just judge whether it is on the existing point , If so, close the path , If not , Continue to add nodes
let lastStartX = lastPoints[0][0],
lastStartY = lastPoints[0][1]
if (isInPoint(clientX, clientY, lastStartX, lastStartY)) {
points[cIndex].push([lastStartX, lastStartY])
points[len] = []
} else {
points[cIndex].push([clientX, clientY])
}
}
})
}
/**
* Draw a line segment between two points
* @param points
*/
function drawLine(points) {
ctx.beginPath()
for (let i = 0; i < points.length; i++) {
let p = points[i]
let cx = p[0], cy = p[1]
// Initialization starting point
if (i === 0) {
ctx.moveTo(cx, cy)
}
// Draw a line
ctx.lineTo(cx, cy)
// Draw a small rectangle at the point
// ctx.fillRect(cx - 5, cy - 5, 10, 10)
}
ctx.stroke()
}
/**
* Draw the background color between line segments
* @param points
*/
function drawPolygon(points) {
if (points.length < 1) {
return;
}
let len = points.length
let moveX = clientX, moveY = clientY,
startX = points[0][0], startY = points[0][1],
endX = points[len - 1][0], endY = points[len - 1][1]
ctx.fillStyle = polygonFillStyle
for (let i = 0; i < points.length; i++) {
let p = points[i]
let cx = p[0], cy = p[1]
// Initialization starting point
if (i === 0) {
ctx.moveTo(cx, cy)
}
// Draw a line
ctx.lineTo(cx, cy)
}
if (isInPoint(moveX, moveY, startX, startY)) {
ctx.lineTo(startX, startY)
} else {
ctx.lineTo(clientX, clientY)
}
ctx.fill()
}
/**
* Draw the mouse following line segment
*/
function drawFollowLine(points) {
if (points.length < 1) {
ctx.fillRect(clientX - 5, clientY - 5, 10, 10)
return;
}
ctx.save()
let len = points.length
// Determine whether it coincides with the first node
let moveX = clientX, moveY = clientY,
startX = points[0][0], startY = points[0][1],
endX = points[len - 1][0], endY = points[len - 1][1]
ctx.beginPath()
ctx.moveTo(endX, endY)
ctx.fillStyle = rectFillStyle
// If the mouse is near the first point ,, Just force the mouse to the first point
if (isInPoint(moveX, moveY, startX, startY)) {
ctx.lineTo(startX, startY)
// Draw a small rectangle , Follow the mouse
ctx.fillRect(startX - 5, startY - 5, 10, 10)
} else {
ctx.lineTo(moveX, moveY)
// Draw a small rectangle , Follow the mouse
ctx.fillRect(clientX - 5, clientY - 5, 10, 10)
// ctx.arc(clientX , clientY,10, 0 , 2*Math.PI, true)
// ctx.fill()
}
ctx.closePath()
ctx.stroke()
ctx.restore()
}
/**
* Determine whether a point is near another point
*/
function isInPoint(x, y, tx, ty) {
let r = Math.sqrt(Math.pow(x - tx, 2) + Math.pow(y - ty, 2))
if (r <= 20) {
return true
}
return false
}
/**
* Convert window coordinates to Canvas coordinate
* @param x window x coordinate
* @param y window y coordinate
* @returns {
{x: number, y: number}}
*/
function windowToCanvas(x, y) {
let bbox = canvas.getBoundingClientRect();
return {
x: x - bbox.left * (canvas.width / bbox.width),
y: y - bbox.top * (canvas.height / bbox.height)
};
}
/**
* Start function
*/
function start() {
initEvent()
let refresh = function (){
window.requestAnimationFrame(() => {
clear()
let len = points.length
for (let i = 0; i < points.length; i++) {
drawLine(points[i])
drawPolygon(points[i])
if (i == len - 1) {
// Just follow the last polygon with the mouse
drawFollowLine(points[i])
}
}
refresh()
})
}
refresh()
}
start()
边栏推荐
猜你喜欢
![[antenna] [2] explanation of some nouns and simple concepts, still](/img/84/7fb2b01dc717eb9196b33066ea3b4e.png)
[antenna] [2] explanation of some nouns and simple concepts, still

.NET C#基础(6):命名空间 - 组织代码的利器

如何使用阿里云 CDN 对部署在函数计算上的静态网站进行缓存

C指针复习

如今的Android 开发都怎么了?我问的面试题有这么难吗?

面向高校 | “云原生技术应用与实践”示范课程项目开放申报

Residual current relay uses residual current transformer to detect residual current and prevent electrical fire
![Esp32 learning notes [WiFi network] - 01ap & sta](/img/04/de14412d6244ec120c587d98f103aa.png)
Esp32 learning notes [WiFi network] - 01ap & sta

The application of the comprehensive energy efficiency management system of ankery in the data center

MySQL basic multi table query
随机推荐
【Android -- 面试】程序员月入过 W 的十大平台
文件排序 (拓展)
3D编程模式:依赖隔离模式
How to use alicloud CDN to cache static websites deployed on function computing
C指针复习
MySQL basic multi table query
RMAN backup concept_ About automatic backup of RMAN control files and server parameter files
MySQL queries all database table names and their comments
HVV blue team points north
环境变量Path误删除
Change exchange (boundary protection should work before array access) (if there is no such combination, dp[i] should also be integer.max_value - 1) leetcode 80
Do you want to explore MySQL not in indexing?
Precautions for Tencent cloud pagoda website construction
[redis learning 12] sentry mechanism of distributed cache, partitioned cluster
MySQL basic database creation foundation
Wechat applet obtains user information and updates it
Energy management and control system for industrial enterprises helps enterprises strengthen energy management and improve equipment operation efficiency
[antenna] [1] explanation of some nouns and simple concepts
JS realizes three-level linkage
MySQL basic functions