使用Canvas画出多个多边形Polygon

直接上代码吧

HTML代码

<!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代码

const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d');

let clientX = 0, clientY = 0,  // 鼠标所在的位置坐标
    points = [],   // 存储点击的坐标节点数据
    polygonFillStyle = 'rgba(255,0,0,.2)',
    rectFillStyle = 'yellow',
    lineStyle = 'red',
    lineWidth = 3

ctx.lineJoin = 'round'
ctx.strokeStyle = lineStyle
ctx.lineWidth = lineWidth
/**
 * 清空Canvas内容
 */
function clear() {
    ctx.fillStyle = 'transparent'
    ctx.clearRect(0, 0, canvas.width, canvas.height)
}

/**
 * 初始化监听事件
 */
function initEvent(){
    // 监听鼠标移动事件
    canvas.addEventListener('mousemove', (e) => {
        let {x,y} = windowToCanvas(e.clientX,e.clientY)
        clientX = x
        clientY = y
    })

    // 监听鼠标点击事件
    canvas.addEventListener('click', (e) => {
        let len = points.length
        let cIndex = 0
        // 初始化存储节点数组
        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) {
            // 如果空间是0的话,就直接新增
            points[cIndex].push([clientX, clientY])
        } else {
            // 如果不是零,就判断是否在已存在的点上,如果是就闭合路径,如果不是,就继续添加节点
            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])
            }
        }
    })

}

/**
 * 绘制两点之间的线段
 * @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]

        // 初始化起始点
        if (i === 0) {
            ctx.moveTo(cx, cy)
        }

        // 画一条线
        ctx.lineTo(cx, cy)
        // 在点处画一个小矩形
        // ctx.fillRect(cx - 5, cy - 5, 10, 10)
    }
    ctx.stroke()
}

/**
 * 绘制线段之间的背景颜色
 * @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]
        // 初始化起始点
        if (i === 0) {
            ctx.moveTo(cx, cy)
        }
        // 画一条线
        ctx.lineTo(cx, cy)
    }
    if (isInPoint(moveX, moveY, startX, startY)) {
        ctx.lineTo(startX, startY)
    } else {
        ctx.lineTo(clientX, clientY)
    }

    ctx.fill()
}

/**
 * 绘制鼠标跟随线段
 */
function drawFollowLine(points) {
    if (points.length < 1) {
        ctx.fillRect(clientX - 5, clientY - 5, 10, 10)
        return;
    }
    ctx.save()
    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.beginPath()
    ctx.moveTo(endX, endY)
    ctx.fillStyle = rectFillStyle
    // 如果鼠标在第一个点的附近,,就将鼠标强制到这第一个点
    if (isInPoint(moveX, moveY, startX, startY)) {
        ctx.lineTo(startX, startY)
        // 画一个小矩形,跟随鼠标
        ctx.fillRect(startX - 5, startY - 5, 10, 10)
    } else {
        ctx.lineTo(moveX, moveY)
        // 画一个小矩形,跟随鼠标
        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()
}


/**
 * 判断一个点是否在另一点的附近
 */
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
}


/**
 * 将窗口坐标转换成Canvas坐标
 * @param x 窗口x坐标
 * @param y 窗口y坐标
 * @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)
    };
}


/**
 * 开始函数
 */
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) {
                    // 只对最后一个多边形做鼠标跟随
                    drawFollowLine(points[i])
                }
            }

            refresh()
        })
    }
    refresh()
}
start()

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值