最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • canvas多边形-日记

    正文概述 掘金(肖同志_)   2021-01-03   598

    简介

    canvas是HTML5新增的,用javaScript进行图形的绘制
    beginPath()创建路径,
    closePath()闭合路径,
    arc(x, y, r, startAngle, endAngle, anticlockwise)绘制圆弧,
    stroke()绘制,
    移动画笔
    moveTo(x,y)起始坐标, lineTo(x,y)中途坐标

    首先,创建一个canvas的容器

    html

    <canvas id="ctx" style="border:1px solid #000;" width="600" height="600">
    </canvas>
    

    js

    getDom(domId){
        return document.querySelector(domId)
    }
    let canvas = getDom('#ctx')
    let ctx = canvas.getContext('2d')
    

    介绍完创建画板之后,接下来进入我们画多边形的代码

    js

    构建一个类

    let start = new Draw('#ctx')
    class Draw(){
        constructor(domId){
            //画板容器
            this.domId = domId
            //用于存放每次鼠标点击的位置
            this.dataList=[]
            //端点变化模式
            this.isChange = false
            //第几个图形
            this.changeFatherIndex = 0
            //第几个坐标点
            this.changeIndex = 0
        }
    }
    

    获取dom

    getDom(){
        //this.domId 是构造函数中存好的
        let canvas = document.querySelector(this.domId)
        let ctx = canvas.getContent('2d')
        //完成选区按钮
        let btn = document.querySelector(this.btnId)
        return {
            canvas,
            ctx,
            btn
        }
    }
    

    注册鼠标事件

    event(){
        //鼠标按下的事件,start方法是用来记录点击的坐标点存放入dataList中
        document.addEventListener('mousedown',this.start.bind(this))
        //在端点变化模式开启使用
        document.addEventListener('mouseup', this.closeChange.bind(this))
        document.addEventListener('mousemove', this.changeData.bind(this))
        //完成选取
        btn.addEventListener('click', this.end.bind(this))
    }
    

    画图

    (每次数据发生变化重新绘制图形)因为后面有一个端点拖动的需求

    draw(){
        let {
            canvas,
        } = this.getDom()
        let ctx = canvas.getContext("2d")
        //为了实现多个图形都可以编辑,在数组中嵌套数组对象,第一层的数组代表了有多少个图形,第二层的数组以
        //`{x,y}`的形式存放着每一个端点
        this.dataList.forEach((item, i) => {
            item.forEach((itemi, indexi) => {
                //如果indexi !== 0 时不是起始点就直接往下继续画,相反是起始点的时候开始创建路径画图
                if (indexi !== 0) {
                    ctx.arc(itemi.x, itemi.y, 1, 0, 2 * Math.PI);//画一个小圆点看的明显一点
                    ctx.lineTo(itemi.x, itemi.y)
                    if (indexi == item.length - 1 && this.isChange) {
                        ctx.closePath()
                    }
                    ctx.stroke()
                } else {
                    //当不是第一个的时候闭合上一个图形
                    if (i > 0) {
                         ctx.closePath()
                        ctx.stroke()
                        ctx.beginPath()
                    } else {
                        ctx.beginPath()
                    }
                    ctx.arc(itemi.x, itemi.y, 1, 0, 2 * Math.PI);
                    ctx.stroke()
                    ctx.moveTo(itemi.x, itemi.y)
                }
            })
        })
    }
    

    记录坐标

    start(e) {
            let {
                canvas,
            } = this.getDom()
            //鼠标x y轴位置
            let x = e.pageX - canvas.offsetLeft
            let y = e.pageY - canvas.offsetTop
            //最大宽度位置
            let bodyX = e.pageX + canvas.offsetWidth
            let bodyY = e.pageY + canvas.offsetHeight
            //第一次进入时创建第一个图形
            if (this.dataList.length == 0) {
                this.dataList = [
                    []
                ]
            }
            //判断是否在画板框中
            if (y > e.offsetY && y < bodyY && x > e.offsetX && x < bodyX) {
                //searchData方法是用于点击端点时改变画图模式
                if (this.searchData(x, y)) {
                    //改变端点
                    this.isChange = true
                } else {
                    this.dataList[this.dataList.length - 1].push({
                        x,
                        y
                    })
                    this.fatherIndex = this.dataList.length - 1
                    this.draw()
                }
            }
        }
    

    检测是否为端点

    searchData(x, y) {
            let flag = false
            this.dataList.forEach((item, index) => {
                item.forEach((data, i) => {
                    //点击端点时友好一些,给个点容错
                    if (data.x > x - 3 && data.x < x + 3 && data.y > y - 3 && data.y < y + 3) {
                        this.changeFatherIndex = index
                        this.changeIndex = i
                        flag = true
                    }
                })
            })
            return flag
        }
    

    闭合图形-完成选区

    end() {
            let {
                canvas,
            } = this.getDom()
            let ctx = canvas.getContext("2d")
            ctx.closePath()
            ctx.stroke()
            ctx.beginPath()
            //创建下一个图形
            this.dataList.push([])
        }
    

    变化端点

    changeData(e) {
        //是否开启了端点变化模式
        if (this.isChange) {
            this.close()
            let {
                canvas,
            } = this.getDom()
            let x = e.pageX - canvas.offsetLeft
            let y = e.pageY - canvas.offsetTop
                //最大宽度位置
            let bodyX = e.pageX + canvas.offsetWidth
            let bodyY = e.pageY + canvas.offsetHeight
            if (y > e.offsetY && y < bodyY && x > e.offsetX && x < bodyX) {
                //改变端点坐标
                this.dataList[this.changeFatherIndex][this.changeIndex] = {
                    x,
                    y
                }
                //重新绘制
                this.draw()
            }
        }
    }
    

    点击完成选取闭合图形

    closeChange() {
        this.isChange = false
    }
    

    html

    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>canvas多边形</title>
    </head>
    
    <body>
        <div>
            <button id="btn">完成选区</button>
        </div>
        <canvas id="ctx" style="border:1px solid #000;" width="600" height="600">
        </canvas>
    </body>
    </html>
    

    结语

    分享一下我对画多边形的思路 首先得创建好一个画板,鼠标点击第一次的时候需要创建一个起始点,之后的点击让线一点一点的连起来,最后画好图形点击完成选取的按钮闭合图形。

    拖动端点改变端点位置,在上面我们先把每一个画好图形的(x,y)坐标去存到一个数组里面,鼠标从点击端点时保存好端点的位置,鼠标抬起时把当前拖动的端点(x,y)坐标改变,去清空画板重新beginTo()一个新的图形

    在写项目的过程中,经常会写到很多重复的代码,复用性不是很高 这次尝试使用面向对象的编程模式,使用过程中感觉到了不少的益处,最重要的是代码可读性会更高一些,在找bug的时候能轻易的分辨。


    起源地下载网 » canvas多边形-日记

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元