1. 原生canvas實現(xiàn)用到的API
1) getContext(contextID) ---返回一個用于在畫布上繪圖的環(huán)境
Canvas.getContext('2d') // 返回一個 CanvasRenderingContext2D 對象,使用它可以繪制到 Canvas 元素中
2)drawImage
drawImage(imgObj, x, y) // 按原圖大小繪制, x、y為圖片在畫布中的位置坐標
drawImage(imgObj, x, y, width, height) // 按指定寬高繪制
drawImage(imgObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight) // 從原來圖片上某一個位置開始(sourceX,sourceY),指定長寬進行剪切(sourceWidth,sourceHeight),然后將剪切的內(nèi)容放到位置為(destX,destY),寬度為(destWidth),高度為(destHeight)的位置上
![](/d/20211016/bdb4058c9970b2cde2b2ad7cfa9a24e7.gif)
3) getImageData(x, y, width, height) ---獲取矩形區(qū)域的圖像信息
ctx.getImageData(0, 0, 10, 10) // 獲取左上角坐標為(0, 0),寬高為區(qū)域內(nèi)的圖像信息
// 返回ImageData: { width: 10, height: 10, data: Uint8ClampedArray[400] }
4)beginPath() ---開始一條路徑,或重置當前的路徑 5)rect(x, y, width, height) ---繪制矩形
6)lineWidth ---設(shè)置或返回當前線條的寬度
7)fillStyle ---設(shè)置或返回用于填充繪畫的顏色、漸變或模式
ctx.fillStyle = color|gradient|pattern
8)strokeStyle ---設(shè)置或返回用于筆觸的顏色、漸變或模式
9)globalAlpha ---設(shè)置或返回繪圖的當前透明值
10)fill() ---填充當前的圖像(路徑)。默認顏色是黑色
【注】如果路徑未關(guān)閉,那么 fill() 方法會從路徑結(jié)束點到開始點之間添加一條線,以關(guān)閉該路徑,然后填充該路徑。
11)stroke() ---會實際地繪制出通過 moveTo() 和 lineTo() 方法定義的路徑。默認顏色是黑色
12)toDataURL(type, encoderOptions) ---導(dǎo)出圖片,type為圖片類型, encoderOptions圖片質(zhì)量,[0, 1]
Canvas.toDataURL("image/png", 1)
2. fabric.js
簡化canvas編寫的庫,為canvas提供所缺少的對象模型
fabric.js能做的事
1)在canvas上創(chuàng)建、填充圖形(包括圖片、文字、規(guī)則圖形和復(fù)雜路徑組成圖形)
2)給圖形填充漸變顏色
3)組合圖形(包括組合圖形、圖形文字、圖片等)
4)設(shè)置圖形動畫集用戶交互
5)生成JSON, SVG數(shù)據(jù)等
3.使用fabric.js實現(xiàn)用到的API
1)聲明畫布
let canvas =new fabric.Canvas('canvas') {
width: 200,
height: 200
}
插入圖片
let imgInstance = new fabric.Image(imgElement,{
left: 0,
top: 0,
width: 100,
height: 100,
angle: 0
}
3)設(shè)置背景圖片 setBackgroundImage
canvas.setBackgroundImage(imgInstance)
4)renderAll() 重新繪制
5)on() 用戶交互
canvas.on('mouse:down', function(options) {
console.log(options.e.clientX, options.e.clientY)
})
// 監(jiān)聽事件
/*
mouse:down :鼠標按下時
mouse:move :鼠標移動時
mouse:up :鼠標抬起時
after:render :畫布重繪后
object:selected:對象被選中
object:moving:對象移動
object:rotating:對象被旋轉(zhuǎn)
object:added:對象被加入
object:removed對象被移除
*/
6)getPointer()
7)setWidth()、setHeight() 設(shè)置canvas的寬高
8)畫矩形
let rect = new fabric.Rect({
left: 0,
top: 0,
width: 100,
height: 100
})
add(obj) 添加圖形
10)remove(obj) 移除圖形
11)set() 設(shè)置對象內(nèi)容
12)toDataURL(obj)
4.原生canvas實現(xiàn)代碼
<template>
<div class="container">
<div class="operations">
<ul>
<li @click="mosaic">馬賽克</li>
<li @click="addText">添加文字</li>
<li @click="tailor">裁剪</li>
<li @click="rotate">旋轉(zhuǎn)</li>
<li @click="exportImg">導(dǎo)出圖片</li>
</ul>
</div>
<canvas ref="imgContent" class="img-wrap">
你的瀏覽器太low🌶
</canvas>
</div>
</template>
<script>
export default {
data () {
return {
context: '',
canvas: '',
isMasic: false,
isText: false,
isTailor: false,
isTranslate: false,
squareEdgeLength: 20,
angle: 0,
img: ''
}
},
mounted () {
this.initData()
},
methods: {
initData () {
let imgContent = this.$refs.imgContent
this.canvas = imgContent
this.context = imgContent.getContext('2d')
let Img = new Image()
this.image = Img
Img.crossOrigin = "Anonymous"
Img.src = 'http://oia85104s.bkt.clouddn.com/PictureUnlock_193139.pictureunlock.jpg'
this.canvas.setAttribute('width', Img.width)
this.canvas.setAttribute('height', Img.height)
let self = this
Img.onload = () => {
let beginX, beginY, endX, endY
self.context.drawImage(Img, 0, 0)
self.context.save()
self.canvas.addEventListener('mousedown', e => {
beginX = e.offsetX
beginY = e.offsetY
self.canvas.addEventListener('mouseup', e => {
endX = e.offsetX
endY = e.offsetY
if (self.isMasic) {
self.makeGrid(beginX, beginY, endX - beginX, endY - beginY)
return
}
if (self.isTailor) {
self.context.drawImage(Img, beginX, beginY, endX - beginX, endY - beginY, 0, 0, endX - beginX, endY - beginY)
return
}
})
})
}
},
drawRect (x, y, width, height, fillStyle, lineWidth, strokeStyle, globalAlpha) {
this.context.beginPath()
this.context.rect(x, y, width, height)
this.context.lineWidth = lineWidth
this.context.strokeStyle = strokeStyle
fillStyle && (this.context.fillStyle = fillStyle)
globalAlpha && (this.context.globalAlpha = globalAlpha)
this.context.fill()
this.context.stroke()
},
// 打馬賽克
mosaic () {
let self = this
this.resetClickStatus()
this.isMasic = true
},
makeGrid (beginX, beginY, rectWidth, rectHight) {
const row = Math.round(rectWidth / this.squareEdgeLength) + 1
const column = Math.round(rectHight / this.squareEdgeLength) + 1
for (let i = 0; i < row * column; i++) {
let x = (i % row) * this.squareEdgeLength + beginX
let y = parseInt(i / row) * this.squareEdgeLength + beginY
this.setColor(x, y)
}
},
setColor (x, y) {
const imgData = this.context.getImageData(x, y, this.squareEdgeLength, this.squareEdgeLength).data
let r = 0, g = 0, b = 0
console.log(this.context.getImageData(x, y, this.squareEdgeLength, this.squareEdgeLength), JSON.stringify(imgData))
for (let i = 0; i < imgData.length; i += 4) {
r += imgData[i]
g += imgData[i + 1]
b += imgData[i + 2]
}
r = Math.round(r / (imgData.length / 4))
g = Math.round(g / (imgData.length / 4))
b = Math.round(b / (imgData.length / 4))
this.drawRect(x, y, this.squareEdgeLength, this.squareEdgeLength, `rgb(${r}, ${g}, $)`, 2, `rgb(${r}, ${g}, $)`)
},
// 添加文字
addText () {
this.resetClickStatus()
this.isText = true
console.log('添加文字')
},
// 裁剪
tailor () {
this.resetClickStatus()
this.isTailor = true
console.log('裁剪')
} ,
// 旋轉(zhuǎn)
rotate () {
// if (this.angle === 360) {
// this.angle = 90
// } else {
// this.angle += 90
// }
// if ([90, 270].includes(this.angle)) {
// this.canvas.setAttribute('width', this.image.height)
// this.canvas.setAttribute('height', this.image.width)
// } else {
// this.canvas.setAttribute('width', this.image.width)
// this.canvas.setAttribute('height', this.image.height)
// }
const x = this.image.width / 2
const y = this.image.height / 2
this.context.clearRect(0,0, this.canvas.width, this.canvas.height) // 清理畫布內(nèi)容
this.context.translate(x, y)
this.context.rotate(90 * Math.PI / 180)
this.context.translate(-x, -y)
this.context.drawImage(this.image, 0, 0)
},
resetClickStatus () {
this.isMasic = false
this.isText = false
this.isTailor = false
this.isTranslate = false
},
exportImg () {
this.resetClickStatus()
const exportUrl = this.canvas.toDataURL("image/jpeg")
let a = document.createElement('a')
a.setAttribute('download', '')
a.href = exportUrl
document.body.appendChild(a)
a.click()
}
}
}
</script>
<style scoped lang="less">
.operations {
width: 1200px;
margin: 0 auto;
ul {
display: flex;
align-items: center;
margin-bottom: 30px;
li {
list-style: none;
margin-right: 20px;
cursor: pointer;
}
}
}
.img-wrap {
display: block;
margin: 0 auto;
}
</style>
效果圖如下:
![](/d/20211016/d175c0a0cc6c826cfde435a59d569a87.gif)
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。