【Tank】2.0 canvas-画布实现
文件结构
index.html如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<link rel="icon" type="image/svg+xml" href="favicon.svg"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Vite App</title>
</head>
<body>
<!--<div id="app"></div>-->
<canvas id="canvas" width="600" height="300" style="overflow: hidden;width: 600px;height: 300px;"></canvas>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
src/style.css
body{
height: 100vh;
width: 100vw;
background-color:#34459e;
margin: 0;
padding: 0;
}
src/main.ts
import './style.css'
//写构造函数
class Blackboard {
//public/private :写就会变为对象属性,不然只是形参
constructor(
public el = document.querySelector<HTMLCanvasElement>("#canvas")!,
private app = el.getContext("2d"),
private width: number = el.width,
private height: number = el.height,
) {
// @ts-ignore
this.app.fillStyle='#000'
// @ts-ignore
this.app.fillRect(0,0,this.width,this.height)
}
}
const instance = new Blackboard()
效果如下
修改src/style.css
body {
height: 100vh;
width: 100vw;
background-color: #34459e;
margin: 0;
padding: 0;
display: flex;
/*主轴*/
justify-content: center;
/*交叉轴*/
align-items: center;
}
画布居中:
鼠标划线
import './style.css'
//写构造函数
class Blackboard {
//public/private :写就会变为对象属性,不然只是形参
constructor(
public el = document.querySelector<HTMLCanvasElement>("#canvas")!,
private app = el.getContext("2d"),
private width: number = el.width,
private height: number = el.height,
) {
this.initCanvas()
// 绑定事件
this.bindEvent();
}
// 绑定事件
private bindEvent() {
// 创建唯一实例
const callback = this.drawLine.bind(this)
// 鼠标按下事件
this.el.addEventListener('mousedown', () => {
// @ts-ignore
this.app.beginPath()
// @ts-ignore
this.app.strokeStyle = '#fff'
// 鼠标移动事件
this.el.addEventListener('mousemove', callback)
// 鼠标松开事件
this.el.addEventListener('mouseup', () => {
// 划线
this.el.removeEventListener('mousemove', callback)
})
})
}
private drawLine(event: MouseEvent) {
// @ts-ignore
this.app.lineTo(event.offsetX, event.offsetY)
// @ts-ignore
this.app.stroke()
}
private initCanvas() {
// @ts-ignore
this.app.fillStyle = '#000'
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
}
}
export const instance = new Blackboard()
防止冒泡,优化如下:
......
// 鼠标松开事件
document.addEventListener('mouseup', () => {
// 划线
this.el.removeEventListener('mousemove', callback)
})
......
增加按钮
import './style.css'
//写构造函数
class Blackboard {
//public/private :写就会变为对象属性,不然只是形参
constructor(
public el = document.querySelector<HTMLCanvasElement>("#canvas")!,
private app = el.getContext("2d"),
private width: number = el.width,
private height: number = el.height,
private btns:HTMLDivElement=document.createElement('div')
) {
this.initCanvas()
// 绑定事件
this.bindEvent();
}
// 绑定事件
private bindEvent() {
// 创建唯一实例
const callback = this.drawLine.bind(this)
// 鼠标按下事件
this.el.addEventListener('mousedown', () => {
// @ts-ignore
this.app.beginPath()
// @ts-ignore
this.app.strokeStyle = '#fff'
// 鼠标移动事件
this.el.addEventListener('mousemove', callback)
// 鼠标松开事件
document.addEventListener('mouseup', () => {
// 划线
this.el.removeEventListener('mousemove', callback)
})
})
}
private drawLine(event: MouseEvent) {
// @ts-ignore
this.app.lineTo(event.offsetX, event.offsetY)
// @ts-ignore
this.app.stroke()
}
private initCanvas() {
// @ts-ignore
this.app.fillStyle = '#000'
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
this.el.insertAdjacentElement('afterend',this.btns)
}
}
export const instance = new Blackboard()
import './style.css'
//写构造函数
class Blackboard {
//public/private :写就会变为对象属性,不然只是形参
constructor(
public el = document.querySelector<HTMLCanvasElement>("#canvas")!,
private app = el.getContext("2d"),
private width: number = el.width,
private height: number = el.height,
private btns: HTMLDivElement = document.createElement('div')
) {
this.initCanvas()
// 绑定事件
this.bindEvent();
}
// 清屏操作
public clear() {
const el = document.createElement('button')
el.innerText = '清屏'
this.btns.insertAdjacentElement('afterbegin', el)
}
// 绑定事件
private bindEvent() {
// 创建唯一实例
const callback = this.drawLine.bind(this)
// 鼠标按下事件
this.el.addEventListener('mousedown', () => {
// @ts-ignore
this.app.beginPath()
// @ts-ignore
this.app.strokeStyle = '#fff'
// 鼠标移动事件
this.el.addEventListener('mousemove', callback)
// 鼠标松开事件
document.addEventListener('mouseup', () => {
// 划线
this.el.removeEventListener('mousemove', callback)
})
})
}
private drawLine(event: MouseEvent) {
// @ts-ignore
this.app.lineTo(event.offsetX, event.offsetY)
// @ts-ignore
this.app.stroke()
}
private initCanvas() {
// @ts-ignore
this.app.fillStyle = '#000'
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
this.el.insertAdjacentElement('afterend', this.btns)
}
}
const instance = new Blackboard()
instance.clear()
修改src/style.css
body {
height: 100vh;
width: 100vw;
background-color: #34459e;
margin: 0;
padding: 0;
display: flex;
/*按列来排列*/
flex-direction: column;
/*主轴*/
justify-content: center;
/*交叉轴*/
align-items: center;
}
稍微调整一下
......
private initCanvas() {
// @ts-ignore
this.app.fillStyle = '#000'
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
this.btns.style.cssText='margin-top:10px'
this.el.insertAdjacentElement('afterend', this.btns)
}
......
背景颜色修改
import './style.css'
const BLACK_BACKGROUND = '#000'
const LINE_COLOR = '#fff'
//写构造函数
class Blackboard {
//public/private :写就会变为对象属性,不然只是形参
constructor(
public el = document.querySelector<HTMLCanvasElement>("#canvas")!,
private app = el.getContext("2d"),
private width: number = el.width,
private height: number = el.height,
private btn: HTMLDivElement = document.createElement('div'),
private bgColor: string = BLACK_BACKGROUND,
private lineColor: string = LINE_COLOR
) {
this.initCanvas()
// 绑定事件
this.bindEvent();
}
// 清屏操作
public clear() {
const el = document.createElement('button')
el.innerText = '清屏'
this.btn.insertAdjacentElement('afterbegin', el)
//点击事件
el.addEventListener('click', () => {
// @ts-ignore
this.app.fillStyle = this.bgColor
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
})
}
// 背景颜色修改
public setBgColor(color: string) {
this.bgColor = color
// @ts-ignore
this.app.fillStyle = color
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
return this
}
// 绑定事件
private bindEvent() {
// 创建唯一实例
const callback = this.drawLine.bind(this)
// 鼠标按下事件
this.el.addEventListener('mousedown', () => {
// @ts-ignore
this.app.beginPath()
// @ts-ignore
this.app.strokeStyle = this.lineColor
// 鼠标移动事件
this.el.addEventListener('mousemove', callback)
// 鼠标松开事件
document.addEventListener('mouseup', () => {
// 划线
this.el.removeEventListener('mousemove', callback)
})
})
}
private drawLine(event: MouseEvent) {
// @ts-ignore
this.app.lineTo(event.offsetX, event.offsetY)
// @ts-ignore
this.app.stroke()
}
private initCanvas() {
// @ts-ignore
this.app.fillStyle = this.bgColor
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
this.btn.style.cssText = 'margin-top:10px'
this.el.insertAdjacentElement('afterend', this.btn)
}
}
const instance = new Blackboard()
instance.clear()
instance.setBgColor("#16a085")
修改粉笔颜色
import './style.css'
const BLACK_BACKGROUND = '#000'
const LINE_COLOR = '#fff'
//写构造函数
class Blackboard {
//public/private :写就会变为对象属性,不然只是形参
constructor(
public el = document.querySelector<HTMLCanvasElement>("#canvas")!,
private app = el.getContext("2d"),
private width: number = el.width,
private height: number = el.height,
private btns: HTMLDivElement = document.createElement('div'),
private bgColor: string = BLACK_BACKGROUND,
private lineColor: string = LINE_COLOR
) {
this.initCanvas()
// 绑定事件
this.bindEvent();
}
// 清屏操作
public clear() {
const el = document.createElement('button')
el.innerText = '清屏'
this.btns.insertAdjacentElement('afterbegin', el)
//点击事件
el.addEventListener('click', () => {
// @ts-ignore
this.app.fillStyle = this.bgColor
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
})
}
// 背景颜色修改
public setBgColor(color: string) {
this.bgColor = color
// @ts-ignore
this.app.fillStyle = color
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
return this
}
// 修改粉笔颜色
public setLineColor() {
const colors = ['#fff', "#1abc9c", "#f1c40f"];
//定义一个容器
const container = document.createElement('div')
// 增加样式
colors.forEach(item => {
const div = document.createElement('div')
div.style.cssText = `width:20px;height:20px;background:${item}`
container.insertAdjacentElement('afterbegin', div)
})
this.btns.insertAdjacentElement('beforeend', container)
}
// 绑定事件
private bindEvent() {
// 创建唯一实例
const callback = this.drawLine.bind(this)
// 鼠标按下事件
this.el.addEventListener('mousedown', () => {
// @ts-ignore
this.app.beginPath()
// @ts-ignore
this.app.strokeStyle = this.lineColor
// 鼠标移动事件
this.el.addEventListener('mousemove', callback)
// 鼠标松开事件
document.addEventListener('mouseup', () => {
// 划线
this.el.removeEventListener('mousemove', callback)
})
})
}
private drawLine(event: MouseEvent) {
// @ts-ignore
this.app.lineTo(event.offsetX, event.offsetY)
// @ts-ignore
this.app.stroke()
}
private initCanvas() {
// @ts-ignore
this.app.fillStyle = this.bgColor
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
this.btns.style.cssText = 'margin-top:10px'
this.el.insertAdjacentElement('afterend', this.btns)
}
}
const instance = new Blackboard()
instance.clear()
instance.setBgColor("#16a085")
instance.setLineColor()
调整css样式
import './style.css'
const BLACK_BACKGROUND = '#000'
const LINE_COLOR = '#fff'
//写构造函数
class Blackboard {
//public/private :写就会变为对象属性,不然只是形参
constructor(
public el = document.querySelector<HTMLCanvasElement>("#canvas")!,
private app = el.getContext("2d"),
private width: number = el.width,
private height: number = el.height,
private btns: HTMLDivElement = document.createElement('div'),
private bgColor: string = BLACK_BACKGROUND,
private lineColor: string = LINE_COLOR
) {
this.initCanvas()
// 绑定事件
this.bindEvent();
}
// 清屏操作
public clear() {
const el = document.createElement('button')
el.innerText = '清屏'
this.btns.insertAdjacentElement('afterbegin', el)
//点击事件
el.addEventListener('click', () => {
// @ts-ignore
this.app.fillStyle = this.bgColor
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
})
}
// 背景颜色修改
public setBgColor(color: string) {
this.bgColor = color
// @ts-ignore
this.app.fillStyle = color
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
return this
}
// 修改粉笔颜色
public setLineColor() {
const colors = ['#fff', "#1abc9c", "#f1c40f","#9b59b6"];
//定义一个容器
const container = document.createElement('div')
// 增加样式
container.classList.add('line-color-container')
colors.forEach(item => {
const div = document.createElement('div')
div.style.cssText = `width:20px;height:20px;background:${item}`
container.insertAdjacentElement('afterbegin', div)
})
this.btns.insertAdjacentElement('beforeend', container)
}
// 绑定事件
private bindEvent() {
// 创建唯一实例
const callback = this.drawLine.bind(this)
// 鼠标按下事件
this.el.addEventListener('mousedown', () => {
// @ts-ignore
this.app.beginPath()
// @ts-ignore
this.app.strokeStyle = this.lineColor
// 鼠标移动事件
this.el.addEventListener('mousemove', callback)
// 鼠标松开事件
document.addEventListener('mouseup', () => {
// 划线
this.el.removeEventListener('mousemove', callback)
})
})
}
private drawLine(event: MouseEvent) {
// @ts-ignore
this.app.lineTo(event.offsetX, event.offsetY)
// @ts-ignore
this.app.stroke()
}
private initCanvas() {
// @ts-ignore
this.app.fillStyle = this.bgColor
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
// this.btns.style.cssText = 'margin-top:10px'
this.btns.classList.add('btns')
this.el.insertAdjacentElement('afterend', this.btns)
}
}
const instance = new Blackboard()
instance.clear()
instance.setBgColor("#16a085")
instance.setLineColor()
修改src/style.css
body {
height: 100vh;
width: 100vw;
background-color: #34459e;
margin: 0;
padding: 0;
display: flex;
/*按列来排列*/
flex-direction: column;
/*主轴*/
justify-content: center;
/*交叉轴*/
align-items: center;
}
.btns {
margin-top: 10px;
display: flex;
/*主轴*/
align-items: center;
}
.line-color-container {
display: flex;
}
增加事件
......
// 修改粉笔颜色
public setLineColor() {
const colors = ['#fff', "#1abc9c", "#f1c40f", "#9b59b6"];
//定义一个容器
const container = document.createElement('div')
// 增加样式
container.classList.add('line-color-container')
colors.forEach(item => {
const div = document.createElement('div')
div.style.cssText = `width:20px;height:20px;background:${item}`
container.insertAdjacentElement('afterbegin', div)
// 循环时添加事件
div.addEventListener('click', () => this.lineColor = item)
})
this.btns.insertAdjacentElement('beforeend', container)
}
......
橡皮擦、铅笔
import './style.css'
const BLACK_BACKGROUND = '#000'
const LINE_COLOR = '#fff'
//写构造函数
class Blackboard {
//public/private :写就会变为对象属性,不然只是形参
constructor(
public el = document.querySelector<HTMLCanvasElement>("#canvas")!,
private app = el.getContext("2d"),
private width: number = el.width,
private height: number = el.height,
private btns: HTMLDivElement = document.createElement('div'),
private bgColor: string = BLACK_BACKGROUND,
private lineColor: string = LINE_COLOR
) {
this.initCanvas()
// 绑定事件
this.bindEvent();
}
// 清屏操作
public clear() {
const el = document.createElement('button')
el.innerText = '清屏'
this.btns.insertAdjacentElement('afterbegin', el)
//点击事件
el.addEventListener('click', () => {
// @ts-ignore
this.app.fillStyle = this.bgColor
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
})
}
// 背景颜色修改
public setBgColor(color: string) {
this.bgColor = color
// @ts-ignore
this.app.fillStyle = color
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
return this
}
// 修改粉笔颜色
public setLineColor() {
const colors = ['#fff', "#1abc9c", "#f1c40f", "#9b59b6"];
//定义一个容器
const container = document.createElement('div')
// 增加样式
container.classList.add('line-color-container')
colors.forEach(item => {
const div = document.createElement('div')
div.style.cssText = `width:20px;height:20px;background:${item}`
container.insertAdjacentElement('afterbegin', div)
// 循环时添加事件
div.addEventListener('click', () => {
this.lineColor = item;
// @ts-ignore
this.app.lineWidth = 1
})
})
this.btns.insertAdjacentElement('beforeend', container)
}
// 橡皮擦功能
public erase() {
const el = document.createElement('button')
el.innerText = '橡皮擦'
this.btns.insertAdjacentElement('afterbegin', el)
//点击事件
el.addEventListener('click', () => {
// @ts-ignore
this.lineColor = this.bgColor
// 线的宽度
// @ts-ignore
this.app.lineWidth = 10
})
}
// 铅笔功能
public draw() {
const el = document.createElement('button')
el.innerText = '铅笔'
this.btns.insertAdjacentElement('afterbegin', el)
//点击事件
el.addEventListener('click', () => {
// @ts-ignore
this.lineColor = "white"
// 线的宽度
// @ts-ignore
this.app.lineWidth = 1
})
}
// 绑定事件
private bindEvent() {
// 创建唯一实例
const callback = this.drawLine.bind(this)
// 鼠标按下事件
this.el.addEventListener('mousedown', () => {
// @ts-ignore
this.app.beginPath()
// @ts-ignore
this.app.strokeStyle = this.lineColor
// 鼠标移动事件
this.el.addEventListener('mousemove', callback)
// 鼠标松开事件
document.addEventListener('mouseup', () => {
// 划线
this.el.removeEventListener('mousemove', callback)
})
})
}
private drawLine(event: MouseEvent) {
// @ts-ignore
this.app.lineTo(event.offsetX, event.offsetY)
// @ts-ignore
this.app.stroke()
}
private initCanvas() {
// @ts-ignore
this.app.fillStyle = this.bgColor
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
// this.btns.style.cssText = 'margin-top:10px'
this.btns.classList.add('btns')
this.el.insertAdjacentElement('afterend', this.btns)
}
}
const instance = new Blackboard()
instance.clear()
instance.erase()
instance.draw()
// instance.setBgColor("#16a085")
instance.setLineColor()
画布截图
import './style.css'
const BLACK_BACKGROUND = '#000'
const LINE_COLOR = '#fff'
//写构造函数
class Blackboard {
//public/private :写就会变为对象属性,不然只是形参
constructor(
public el = document.querySelector<HTMLCanvasElement>("#canvas")!,
private app = el.getContext("2d"),
private width: number = el.width,
private height: number = el.height,
private btns: HTMLDivElement = document.createElement('div'),
private bgColor: string = BLACK_BACKGROUND,
private lineColor: string = LINE_COLOR
) {
this.initCanvas()
// 绑定事件
this.bindEvent();
}
// 清屏操作
public clear() {
const el = document.createElement('button')
el.innerText = '清屏'
this.btns.insertAdjacentElement('afterbegin', el)
//点击事件
el.addEventListener('click', () => {
// @ts-ignore
this.app.fillStyle = this.bgColor
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
})
return this
}
// 背景颜色修改
public setBgColor(color: string) {
this.bgColor = color
// @ts-ignore
this.app.fillStyle = color
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
return this
}
// 修改粉笔颜色
public setLineColor() {
const colors = ['#fff', "#1abc9c", "#f1c40f", "#9b59b6"];
//定义一个容器
const container = document.createElement('div')
// 增加样式
container.classList.add('line-color-container')
colors.forEach(item => {
const div = document.createElement('div')
div.style.cssText = `width:20px;height:20px;background:${item}`
container.insertAdjacentElement('afterbegin', div)
// 循环时添加事件
div.addEventListener('click', () => {
this.lineColor = item;
// @ts-ignore
this.app.lineWidth = 1
})
})
this.btns.insertAdjacentElement('beforeend', container)
return this
}
// 橡皮擦功能
public erase() {
const el = document.createElement('button')
el.innerText = '橡皮擦'
this.btns.insertAdjacentElement('afterbegin', el)
//点击事件
el.addEventListener('click', () => {
// @ts-ignore
this.lineColor = this.bgColor
// 线的宽度
// @ts-ignore
this.app.lineWidth = 10
})
return this
}
// 铅笔功能
public draw() {
const el = document.createElement('button')
el.innerText = '铅笔'
this.btns.insertAdjacentElement('afterbegin', el)
//点击事件
el.addEventListener('click', () => {
// @ts-ignore
this.lineColor = "white"
// 线的宽度
// @ts-ignore
this.app.lineWidth = 1
})
return this
}
// 截图保存
public printScreen() {
const el = document.createElement('button')
el.innerText = '截图保存'
this.btns.insertAdjacentElement('afterbegin', el)
const img = document.createElement('img')
//点击事件
el.addEventListener('click', () => {
img.src = this.el.toDataURL('image/jpeg')
img.classList.add('img-print-screen')
})
this.btns.insertAdjacentElement('afterend', img)
return this
}
// 绑定事件
private bindEvent() {
// 创建唯一实例
const callback = this.drawLine.bind(this)
// 鼠标按下事件
this.el.addEventListener('mousedown', () => {
// @ts-ignore
this.app.beginPath()
// @ts-ignore
this.app.strokeStyle = this.lineColor
// 鼠标移动事件
this.el.addEventListener('mousemove', callback)
// 鼠标松开事件
document.addEventListener('mouseup', () => {
// 划线
this.el.removeEventListener('mousemove', callback)
})
})
}
private drawLine(event: MouseEvent) {
// @ts-ignore
this.app.lineTo(event.offsetX, event.offsetY)
// @ts-ignore
this.app.stroke()
}
private initCanvas() {
// @ts-ignore
this.app.fillStyle = this.bgColor
// @ts-ignore
this.app.fillRect(0, 0, this.width, this.height)
// this.btns.style.cssText = 'margin-top:10px'
this.btns.classList.add('btns')
this.el.insertAdjacentElement('afterend', this.btns)
}
}
const instance = new Blackboard()
instance.clear()//清屏操作
.erase()//橡皮擦功能
.draw()//铅笔功能
.printScreen()//截图保存
// .setBgColor("#16a085")
.setLineColor()//修改粉笔颜色
修改src/style.css
body {
height: 100vh;
width: 100vw;
background-color: #34459e;
margin: 0;
padding: 0;
display: flex;
/*按列来排列*/
flex-direction: column;
/*主轴*/
justify-content: center;
/*交叉轴*/
align-items: center;
}
.btns {
margin-top: 10px;
display: flex;
/*主轴*/
align-items: center;
}
.line-color-container {
display: flex;
}
.img-print-screen {
margin-top: 15px;
width: 300px;
height: 150px;
}
该图片可以右击保存。
发表评论 (审核通过后显示评论):