您好,欢迎访问一九零五行业门户网

HTML5 canvas实现画图程序(附代码)

这篇文章给大家介绍的内容是关于html5 canvas实现画图程序(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
项目简介整个项目分为两大部分
场景
场景负责canvas控制,事件监听,动画处理
精灵
精灵则指的是每一种可以绘制的canvas元素
demo演示地址
项目特点可扩展性强
sprite精灵实现父类class element {  constructor(options = {    fillstyle: 'rgba(0,0,0,0)',    linewidth: 1,    strokestyle: 'rgba(0,0,0,255)'  }) {    this.options = options  }  setstyle(options){    this.options =  object.assign(this.options. options)  }}
属性:
options中存储了所有的绘图属性
fillstyle:设置或返回用于填充绘画的颜色、渐变或模式
strokestyle:设置或返回用于笔触的颜色、渐变或模式
linewidth:设置或返回当前的线条宽度
使用的都是getcontext(2d)对象的原生属性,此处只列出了这三种属性,需要的话还可以继续扩充。
有需要可以继续扩充
方法:
setstyle方法用于重新设置当前精灵的属性
有需要可以继续扩充
所有的精灵都继承element类。
子类子类就是每一种精灵元素的具体实现,这里我们介绍一遍circle元素的实现
class circle extends element {  // 定位点的坐标(这块就是圆心),半径,配置对象  constructor(x, y, r = 0, options) {    // 调用父类的构造函数    super(options)    this.x = x    this.y = y    this.r = r  }  // 改变元素大小  resize(x, y) {    this.r = math.sqrt((this.x - x) ** 2 + (this.y - y) ** 2)  }  // 移动元素到新位置,接收两个参数,新的元素位置  moveto(x, y) {    this.x = x    this.y = y  }  // 判断点是否在元素中,接收两个参数,点的坐标  choose(x, y) {    return ((x - this.x) ** 2 + (y - this.y) ** 2) < (this.r ** 2) } // 偏移,计算点和元素定位点的相对偏移量(ofsetx, offsety) getoffset(x, y) { return { x: x - this.x, y: y - this.y } } // 绘制元素实现,接收一个ctx对象,将当前元素绘制到指定画布上 draw(ctx) { // 取到绘制所需属性 let { fillstyle, strokestyle, linewidth } = this.options // 开始绘制beginpath() 方法开始一条路径,或重置当前的路径 ctx.beginpath() // 设置属性 ctx.fillstyle = fillstyle ctx.strokestyle = strokestyle ctx.linewidth = linewidth // 画圆 ctx.arc(this.x, this.y, this.r, 0, 2 * math.pi) // 填充颜色 ctx.stroke() ctx.fill() // 绘制完成 } // 验证函数,判断当前元素是否满足指定条件,此处用来检验是否将元素添加到场景中。 validate() { return this.r >= 3  }}
arc() 方法创建弧/曲线(用于创建圆或部分圆)
x    圆的中心的 x 坐标。
y    圆的中心的 y 坐标。
r    圆的半径。
sangle    起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。
eangle    结束角,以弧度计。
counterclockwise    可选。规定应该逆时针还是顺时针绘图。false = 顺时针,true = 逆时针。
注意事项:
构造函数的形参只有两个是必须的,就是定位点的坐标。
其它的形参都必须有默认值。
所有方法的调用时机
我们在画布上绘制元素的时候回调用resize方法。
移动元素的时候调用moveto方法。
choose会在鼠标按下时调用,判断当前元素是否被选中。
getoffset选中元素时调用,判断选中位置。
draw绘制函数,绘制元素到场景上时调用。
scene场景的实现属性介绍
class sence {  constructor(id, options = {    width: 600,    height: 400  }) {    // 画布属性    this.canvas = document.queryselector('#' + id)    this.canvas.width = options.width    this.canvas.height = options.height    this.width = options.width    this.height = options.height    // 绘图的对象    this.ctx = this.canvas.getcontext('2d')    // 离屏canvas    this.outcanvas = document.createelement('canvas')    this.outcanvas.width = this.width    this.outcanvas.height = this.height    this.outctx = this.outcanvas.getcontext('2d')    // 画布状态    this.statelist = {      drawing: 'drawing',      moving: 'moving'    }    this.state = this.statelist.drawing    // 鼠标状态    this.mousestate = {    // 记录鼠标按下时的偏移量      offsetx: 0,      offsety: 0,      down: false, //记录鼠标当前状态是否按下      target: null //当前操作的目标元素    }    // 当前选中的精灵构造器    this.currentspriteconstructor = null    // 存储精灵    let sprites = []    this.sprites = sprites    /* .... */  }}
事件逻辑
class sence {  constructor(id, options = {    width: 600,    height: 400  }) {  /* ... */  // 监听事件    this.canvas.addeventlistener('contextmenu', (e) => {      console.log(e)    })    // 鼠标按下时的处理逻辑    this.canvas.addeventlistener('mousedown', (e) => {    // 只有左键按下时才会处理鼠标事件      if (e.button === 0) {      // 鼠标的位置        let x = e.offsetx        let y = e.offsety        // 记录鼠标是否按下        this.mousestate.down = true        // 创建一个临时target        // 记录目标元素        let target = null        if (this.state === this.statelist.drawing) {        // 判断当前有没有精灵构造器,有的话就构造一个对应的精灵元素          if (this.currentspriteconstructor) {            target = new this.currentspriteconstructor(x, y)          }        } else if (this.state === this.statelist.moving) {          let sprites = this.sprites          // 遍历所有的精灵,调用他们的choose方法,判断有没有被选中          for (let i = sprites.length - 1; i >= 0; i--) {            if (sprites[i].choose(x, y)) {              target = sprites[i]              break;            }          }                    // 如果选中的话就调用target的getoffset方法,获取偏移量          if (target) {            let offset = target.getoffset(x, y)            this.mousestate.offsetx = offset.x            this.mousestate.offsety = offset.y          }        }        // 存储当前目标元素        this.mousestate.target = target        // 在离屏canvas保存除目标元素外的所有元素        let ctx = this.outctx        // 清空离屏canvas        ctx.clearrect(0, 0, this.width, this.height)        // 将目标元素外的所有的元素绘制到离屏canvas中        this.sprites.foreach(item => {          if (item !== target) {            item.draw(ctx)          }        })        if(target){            // 开始动画            this.anmite()        }      }    })    this.canvas.addeventlistener('mousemove', (e) => {    //  如果鼠标按下且有目标元素,才执行下面的代码      if (this.mousestate.down && this.mousestate.target) {        let x = e.offsetx        let y = e.offsety        if (this.state === this.statelist.drawing) {        // 调用当前target的resize方法,改变大小          this.mousestate.target.resize(x, y)        } else if (this.state === this.statelist.moving) {        // 取到存储的偏移量          let {            offsetx, offsety          } = this.mousestate          // 调用moveto方法将target移动到新的位置          this.mousestate.target.moveto(x - offsetx, y - offsety)        }      }    })    document.body.addeventlistener('mouseup', (e) => {      if (this.mousestate.down) {      // 将鼠标按下状态记录为false        this.mousestate.down = false        if (this.state === this.statelist.drawing) {        // 调用target的validate方法。判断他要不要被加到场景去呢          if (this.mousestate.target.validate()) {            this.sprites.push(this.mousestate.target)          }        } else if (this.state === this.statelist.moving) {          // 什么都不做        }      }    })  }}
方法介绍
class sence {// 动画  anmite() {    requestanimationframe(() => {      // 清除画布      this.clear()      // 将离屏canvas绘制到当前canvas上      this.paint(this.outcanvas)      // 绘制target      this.mousestate.target.draw(this.ctx)      // 鼠标是按下状态就继续执行下一帧动画      if (this.mousestate.down) {        this.anmite()      }    })  }  // 可以将手动的创建的精灵添加到画布中  append(sprite) {    this.sprites.push(sprite)    sprite.draw(this.ctx)  }  // 根据id值,从场景中删除对应元素  remove(id) {    this.sprites.splice(id, 1)  }  // clearrect清除指定区域的画布内容  clear() {    this.ctx.clearrect(0, 0, this.width, this.height)  }  // 重绘整个画布的内容  reset() {    this.clear()    this.sprites.foreach(element => {      element.draw(this.ctx)    })  }  // 将离屏canvas绘制到页面的canvas画布上  paint(canvas, x = 0, y = 0) {    this.ctx.drawimage(canvas, x, y, this.width, this.height)  }  // 设置当前选中的精灵构造器  setcurrentsprite(element) {    this.currentspriteconstructor = element  }
相关文章推荐:
canvas如何实现二维码和图片合成的代码
html5 canvas实现交互式地铁线路图
以上就是html5 canvas实现画图程序(附代码)的详细内容。
其它类似信息

推荐信息