效果展示

Canvas API简介

调用方法

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

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

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

toDataURL() 返回canvas图像的URL

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

stroke() 绘制已定义的路径

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

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

调用属性

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

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

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

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

功能需求说明

基础线条绘制功能

笔触颜色修改

笔刷粗细调整

撤回、前进、情况功能

生成图片

初始化数据

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数据):

v-for="item in colors"

:class="{'active':config.lineColor === item}"

:style="{ background: item }"

@click="setColor(item)"

>

v-for="pen in brushs"

:class="[pen.className,{'active': config.lineWidth === pen.lineWidth}]"

@click="setBrush(pen.lineWidth)"

>

画笔的移动操作

// 当在屏幕中移动时即开始绘制准备

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等。

id="canvas"

class="fl"

width="600"

height="400"

@mousedown="canvasDown($event)"

@mouseup="canvasUp($event)"

@mousemove="canvasMove($event)"

@touchstart="canvasDown($event)"

@touchend="canvasUp($event)"

@touchmove="canvasMove($event)"

>

撤销清空等操作

// 撤销

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]]

vue页面绘图_利用vue制作在线涂鸦板相关推荐

  1. vue canvas插件_基于vue.js 制作在线桌椅定制选择交互特效源码

    码农那点事儿 关注我们,一起学习进步 基于vue.js写的在线桌子椅子垫子选择拼成的自己理想的书桌椅图像,这是一款交互式的课桌椅在线定制选择功能.非常不错,感兴趣的朋友前来下载使用. 下载源码(提取码 ...

  2. vue 井号_使用Vue 2制作井字游戏:第1部分

    vue 井号 This tutorial assumes that you have a little prior knowledge of JavaScript and the Vue framew ...

  3. vue 公用页面引用_关于vue全局引用公共的js和公共的组件的折腾

    前沿 最近在项目开发中遇到一些需要全局引用的公共js,或者公共组件,早就烦死了那种每个页面都写一遍,都引用一个js的写法,正好vue解决了这个额问题,于是乎就开始折腾,折腾的过程中也发现了一些自己之前 ...

  4. vue 同级页面调用方法_【Vue】一个vue页面调用另一个vue页面中的方法

    想仿着 vue-material 的 Demo & Document 页面的效果写一个小例子. 遇到问题的地方是: 如上图红色圈出的地方,点击 button 按钮时,无法执行 toggle() ...

  5. vue页面绘图_Vue+Canvas绘图使用

    1. 前言 图片储存在后台中,根据图片的地址,在vue页面中,查看图片,并根据坐标标注指定区域. 由于浏览器的机制,使用window.location.href下载图片时,并不会保存到本地,会在浏览器 ...

  6. axios vue 回调函数_前端Vue 面试题大全

    点蓝色字关注"程序员报刊" 「  学习 新闻 招聘 」 vue的底层原理? vue组件之间的通信? JS中判断数据类型的方法有几种? 最常见的判断方法:typeof 判断已知对象类 ...

  7. vue族谱架构_基于 Vue 实现动态家谱图/组织结构图

    Vue-Tree-Chart 最近一个项目里有个前端绘制家谱图的需求,大概是下面这个样子: 点击节点会弹出操作菜单,实现增删改查等操作,查阅网上资料发现,现有案例基本都是基于orgchart这个jQu ...

  8. baidumap vue 判断范围_一个Vue引发的性能问题

    笔者最近在一个Vue项目里面引入了一个动画库,但是发现性能有点异常,项目里面使用的CPU是在一个demo页面的3.5倍左右,我已经把项目里所有其它干扰的东西都给删掉了,但是CPU就是降不下去,如下图所 ...

  9. vue部门结构图_基于 Vue 实现动态组织结构图

    基于 Vue 实现动态组织结构图 最近一个项目里有个前端绘制家谱图的需求, 大概是下面这个样子: 点击节点会弹出操作菜单, 实现增删改查等操作, 查阅网上资料发现, 现有案例基本都是基于 orgcha ...

最新文章

  1. html特殊字符的html,js,css写法汇总
  2. linux系统硬盘数据恢复软件下载,Linux硬盘数据恢复软件
  3. USACO 1.3-Combination Lock
  4. javaweb入门笔记(4)-request和response
  5. 基于Flask实现后台权限管理系统 - 表设计
  6. java保存登录信息_java – 保存登录详细信息(首选项)android
  7. html5 字母单词拖拽,HTML5拖拽
  8. 小白必须要会的Github操作 确定不进来看看?
  9. STC89C51系列 EEPROM测试程序 证明扇区512个字节的擦除
  10. 【答学员问】有没有三十岁以上大龄转行的学员,我想跟他聊聊?
  11. 【第三方互联】11、创建支付宝(Alipay)互联应用
  12. 机器学习实验二 决策树
  13. 游戏开发20课 tilemap 绘制
  14. Excel表格成绩排名全攻略,让你事半功倍!
  15. 笔记本购机测试软件大全
  16. vipkid怎么样?来自家长的真实评价
  17. 3年级计算机课程安排,人教版三年级信息技术教学计划
  18. HDU3085 Nightmare Ⅱ —— 双向BFS + 曼哈顿距离
  19. ios+透明度+css,ios -css
  20. TCL雷鸟电视卸载内置应用

热门文章

  1. SBB:长期施肥降低了控制土壤微生物群落演替的随机性
  2. 单细胞转录组单飞第二期开课啦!!
  3. 创建属于自己的调色板
  4. 多元回归树分析Multivariate Regression Trees,MRT
  5. R语言使用ggplot2包使用geom_density()函数绘制基础密度图实战(density plot)
  6. python使用imbalanced-learn的RandomUnderSampler方法进行下采样处理数据不平衡问题
  7. 傅里叶(FFT)+小波变换+数据压缩
  8. IF、Isolation Forest、孤立森林算法
  9. java arraylist 序列化_专题二、ArrayList序列化技术细节详解
  10. 【效率工具】Linux服务器终端MobaXterm