资讯专栏INFORMATION COLUMN

利用vue制作在线涂鸦板

nemo / 2883人阅读

摘要:撤销清空等操作撤销前进清空清空前后数据恢复到默认数据地址查看代码

效果展示

Canvas API简介 调用方法

getImageData() 返回ImageData对象,该对象为画布上指定的矩形复制像素数据

putImageData() 把图像数据(从指定的 ImageData 对象)放回画布上

clearRect() 在给定的矩形内清除指定的像素

toDataURL() 返回canvas图像的URL

lineTo() 添加一个新点,创建从该点到最后指定点的线条

stroke() 绘制已定义的路径

beginPath() 起始一条路径,或重置当前路径

moveTo() 把路径移动到画布中的指定点,不创建线条

调用属性

strokeStyle 设置或返回用于笔触的颜色、渐变或模式

shadowBlur 设置或返回用于阴影的模糊级别

shadowColor 设置或返回用于阴影的颜色

lineWidth 设置或返回当前的线条宽度

更多API请参考 canvas基本使用

功能需求说明

基础线条绘制功能

笔触颜色修改

笔刷粗细调整

撤回、前进、情况功能

生成图片

初始化数据

colors: 笔触颜色列表

brushs: 笔刷对应的粗细

context: canvas context

imgUrl: 用于存放保存图片的地址

canvasMoveUse: 是否允许执行move时候绘制线条

preDrawAry: 存储当前表面状态数组-上一步

nextDrawAry: 存储当前表面状态数组-下一步

middleAry: 中间数组

lineWidth: 线条宽度

lineColor: 线条颜色

shadowBlur: 阴影

data() {
  return {
    colors: ["#fef4ac","#0018ba","#ffc200","#f32f15","#cccccc","#5ab639"],
    brushs: [{
            className: "small fa fa-paint-brush",
            lineWidth: 3
          },{
            className: "middle fa fa-paint-brush",
            lineWidth: 6
          },{
            className: "big fa fa-paint-brush",
            lineWidth: 12
          }],
    context: {},
    imgUrl: [],
    canvasMoveUse: true,
    preDrawAry: [],
    nextDrawAry: [],
    middleAry: [],
    config: {
      lineWidth: 1,
      lineColor: "#f2849e",
      shadowBlur: 2
    }
  }
}
设置绘画配置
  setCanvasStyle() {
    this.context.lineWidth = this.config.lineWidth
    this.context.shadowBlur = this.config.shadowBlur
    this.context.shadowColor = this.config.lineColor
    this.context.strokeStyle = this.config.lineColor
  }

笔触颜色及粗细相关设置(点击修改config数据):


  • 
     
    画笔的移动操作
    // 当在屏幕中移动时即开始绘制准备
    beginPath(e){
      const canvas = document.querySelector("#canvas")
      if (e.target !== canvas) {
        this.context.beginPath()
      }
    }
    // 在canvas中鼠标按下
     canvasDown(e) {
      // 让move方法可用
      this.canvasMoveUse = true
      // client是基于整个页面的坐标
      // offset是cavas距离顶部以及左边的距离
      const canvasX = e.clientX - e.target.parentNode.offsetLeft
      const canvasY = e.clientY - e.target.parentNode.offsetTop
      // 设置canvas的配置
      this.setCanvasStyle()
      //清除子路径
      this.context.beginPath()
      // 移动的起点
      this.context.moveTo(canvasX, canvasY)
      //当前绘图表面状态
      const preData = this.context.getImageData(0, 0, 600, 400)
      //当前绘图表面进栈
      // 按下相当于新的操作的开始,所以把当前记录数据放到prev中
      this.preDrawAry.push(preData)
    },
    // canvas中鼠标移动
    canvasMove(e) {
      if(this.canvasMoveUse) {
        // 只有允许移动时调用
        const t = e.target
        let canvasX
        let canvasY
        // 由于手机端和pc端获取页面坐标方式不同,所以需要做出判断
        if(this.isPc()){
          canvasX = e.clientX - t.parentNode.offsetLeft
          canvasY = e.clientY - t.parentNode.offsetTop
        }else {
          canvasX = e.changedTouches[0].clientX - t.parentNode.offsetLeft
          canvasY = e.changedTouches[0].clientY - t.parentNode.offsetTop
        }
        // 连接到移动的位置并上色
        this.context.lineTo(canvasX, canvasY)
        this.context.stroke()
      }
    },
    // canvas中鼠标放开
    canvasUp(e){
      const preData = this.context.getImageData(0, 0, 600, 400)
      if (!this.nextDrawAry.length) {
        // 在没有撤销过的情况下,将当前数据放入prev
        //当前绘图表面进栈
        this.middleAry.push(preData)
      } else {
        // 在撤销的情况下,将在后面步骤的数据情况记录
        this.middleAry = []
        this.middleAry = this.middleAry.concat(this.preDrawAry)
        this.middleAry.push(preData)
        this.nextDrawAry = []
      }
      // 设置move时不可绘制
      this.canvasMoveUse = false
    }

    为了保证移动端的可用性,加入touchstart等。

    撤销清空等操作
    // 撤销
    if (this.preDrawAry.length) {
      const popData = this.preDrawAry.pop()
      const midData = this.middleAry[this.preDrawAry.length + 1]
      this.nextDrawAry.push(midData)
      this.context.putImageData(popData, 0, 0)
    }
    // 前进
    if (this.nextDrawAry.length) {
      const popData = this.nextDrawAry.pop()
      const midData = this.middleAry[this.middleAry.length - this.nextDrawAry.length - 2]
      this.preDrawAry.push(midData)
      this.context.putImageData(popData, 0, 0)
    }
    // 清空
    this.context.clearRect(0, 0, this.context.canvas.width, this.context.canvas.height)
    // 清空前后数据
    this.preDrawAry = []
    this.nextDrawAry = []
    // middleAry恢复到默认数据
    this.middleAry = [this.middleAry[0]]

    demo地址

    查看代码

    文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

    转载请注明本文地址:https://www.ucloud.cn/yun/81082.html

    相关文章

    • 前端文档收集

      摘要:系列种优化页面加载速度的方法随笔分类中个最重要的技术点常用整理网页性能管理详解离线缓存简介系列编写高性能有趣的原生数组函数数据访问性能优化方案实现的大排序算法一怪对象常用方法函数收集数组的操作面向对象和原型继承中关键词的优雅解释浅谈系列 H5系列 10种优化页面加载速度的方法 随笔分类 - HTML5 HTML5中40个最重要的技术点 常用meta整理 网页性能管理详解 HTML5 ...

      jsbintask 评论0 收藏0
    • 前端文档收集

      摘要:系列种优化页面加载速度的方法随笔分类中个最重要的技术点常用整理网页性能管理详解离线缓存简介系列编写高性能有趣的原生数组函数数据访问性能优化方案实现的大排序算法一怪对象常用方法函数收集数组的操作面向对象和原型继承中关键词的优雅解释浅谈系列 H5系列 10种优化页面加载速度的方法 随笔分类 - HTML5 HTML5中40个最重要的技术点 常用meta整理 网页性能管理详解 HTML5 ...

      muddyway 评论0 收藏0
    • STM32CubeMX学习教程之硬件I2C读取光照度

      摘要:使用库读写环境光照度传感器本文将教大家如何快速使用库读取光照度数据。五实验样机测试展示通过之前配置好的面板,通过涂鸦智能进行配网实时采集光照度传感器的数据。 使用STM32 HAL库读写环境光照度传感器(BH1750) 本文将教大家如何快速使用STM32HAL库读取光照度数据。 实现功能:通...

      tinylcy 评论0 收藏0
    • Android:涂鸦tuytaSDK实现逻辑

      摘要:开启扫描时需要设备处于配网状态一分类配网子设备可以通过使用手机蓝牙直接扫描获取设备到设备基础信息,再使用配网接口实现设备的本地配网。   (一)分类   (二)设备配置   (三)设备管理     设备管理,大体分为两类,mesh 和 其他     获取设备列表,给涂鸦sdk发送当前房间id...

      MorePainMoreGain 评论0 收藏0

    发表评论

    0条评论

    nemo

    |高级讲师

    TA的文章

    阅读更多
    最新活动
    阅读需要支付1元查看
    <