canvas实现动态替换人物的背景颜色
生活随笔
收集整理的這篇文章主要介紹了
canvas实现动态替换人物的背景颜色
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
起因
今天遇見一個特別有意思的小功能。
就是更換人物圖像的背景顏色。
大致操作步驟就是:點擊人物-實現背景顏色發生變化
將圖片繪畫到canvas畫布上
我們需要將圖片繪制到canvas畫布上。
這樣做的目的是為了方便我們去操作像素點來更改顏色。
首先創建 Image 的實例。將圖片的地址賦值給圖片實例src。
當圖片加載完成后,onload 事件可以知道圖片是否加載完成
根據 Image的實例將圖片大小賦值給畫布,讓他們大小保持一致。
最后使用 ctx.drawImage來進行繪畫就行
特別提醒的是:src 屬性一定要寫到 onload 的后面,否則程序在 IE 中會出錯。
<body>
<canvas id="canvas">
</body>
<script type="text/javascript">
// 獲取dom節點
const canvas = document.getElementById('canvas')
//獲取上下文
const ctx = canvas.getContext('2d');
// 將圖片繪制到canvas畫布上
function initPic(picInfo){
// 創建一個圖片的實例
const img = new Image()
// 引入圖片的地址
img.src = picInfo.url
img.onload =()=>{
// 設置畫布的寬高與圖片的保持一致
canvas.width= img.width
canvas.height= img.height
// 開始繪畫
ctx.drawImage(img, 0, 0 );
}
}
initPic({
url: './src/assets/person.png'
})
</script>
drawImage 的簡單介紹
canvas的drawImage()提供了更多在canvas上繪制圖像的方法。
drawImage() 方法有三種形式:
drawImage(image, dx, dy) 在指定的 (dx, dy) 位置繪制圖像。
drawImage(image, dx, dy, width, height) 在指定的 (dx, dy) 位置,并使用指定的寬度和高度繪制圖像。
drawImage(image, sourceX, sourceY, sourceWidth, sourceHeight, dx, dy, width, height) 在指定的 (dx, dy) 位置,并使用指定的寬度和高度繪制圖像。圖像的源坐標和尺寸也指定了。
image:允許任何的畫布圖像源
注冊事件獲取點擊時的坐標對應的顏色
我們通過 e.offsetX, e.offsetY 可以輕松拿到點擊的坐標x,y。
可以通過 getImageData 獲取到圖片的所有像素點的顏色。
但是怎么通過點擊的位置(x,y)獲取到對應的的像素索引呢?
其實他們的關系是這樣的:
// 每個像素占用4個字節(RGBA)
const index = (y * image.width + x) * 4;
根據上面這個公式,我們可以知道坐標對應的像素索引。
有了索引,我們可以拿到坐標對應的顏色
function clickMy(e){
// 獲取點擊時的坐標
let x = e.offsetX
let y = e.offsetY
// 獲取所有的像素點顏色
let imagedata = ctx.getImageData(0, 0, canvas.width, canvas.height);
console.log('獲取所有的像素點顏色', imagedata)
// 這個坐標點對應的顏色
let clickColor = getColor(x,y, imagedata)
console.log('這個坐標點對應的顏色', clickColor)
}
// 計算點擊坐標對應的像素索引
function bgIndex(x,y){
return (y * canvas.width + x) * 4;
}
// 根據索引得到顏色值
function getColor(x,y,imgData){
let i = bgIndex(x,y)
return [
imgData.data[i],
imgData.data[i+1],
imgData.data[i+2],
imgData.data[i+3]
]
}
// 注冊事件
canvas.addEventListener("click", clickMy, false)
更改當前像素點的顏色
現在我們希望點擊的這個點的顏色變成紅色。
現在的我們可以拿到所有像素點,當前的坐標,坐標對應的顏色。
現在我們的主角出場了(此時燈光閃爍,五彩的光打在他的身上)
context.putImageData(imageData, x, y);
第1個參數:imageData: 包含了圖像的所有像素數據,
通過ctx.getImageData(0, 0, canvas.width, canvas.height)可以獲取到;
第2,3個參數表示坐標。
它用于將圖像數據繪制到畫布上。
這個方法允許開發者操作和繪制像素級別的數據,
從而實現復雜的圖像效果和處理。
function clickMy(e){
// 獲取點擊時的坐標
let x =e.offsetX
let y = e.offsetY
// 獲取所有的像素點顏色
let imagedata = ctx.getImageData(0, 0, canvas.width, canvas.height);
console.log('獲取所有的像素點顏色', imagedata)
// 這個坐標點對應的顏色
let clickColor = getColor(x,y, imagedata)
console.log('這個坐標點對應的顏色', clickColor)
// 最后更改為紅色的rgba值
let targetBgArr = [255,0,0,255]
// 更改顏色
function changeColor(x,y){
let i = bgIndex(x,y)
imagedata.data.set(targetBgArr, i)
}
changeColor(x,y)
// 更改當前像素點的顏色
ctx.putImageData(imagedata, 0, 0);
}
將被點擊的點的相似顏色全部變為紅色
我們通過兩個顏色的rgba值相減,看rgba的各個絕對值之和。
來判斷顏色的相似。
同時我頁需要注意邊界范圍與顏色已經變為了目標顏色。
這個時候我們就需要停止調用函數了
核心代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="canvas">
</body>
<script type="text/javascript">
// 獲取dom節點
const canvas = document.getElementById('canvas')
// 獲取上下文
const ctx = canvas.getContext('2d',{
willReadFrequently:true
});
function initPic(picInfo){
// 創建一個圖表的實例
const img = new Image()
img.onload =()=>{
// 設置畫布的寬高與圖片的保持一致
canvas.width= img.width
canvas.height= img.height
// 開始繪畫
ctx.drawImage(img, 0, 0 );
}
// 引入圖片的地址
img.src = picInfo.url
}
function clickMy(e){
// 獲取點擊時的坐標
let x =e.offsetX
let y = e.offsetY
// 獲取所有的像素點顏色
let imagedata = ctx.getImageData(0, 0, canvas.width, canvas.height);
console.log('獲取所有的像素點顏色', imagedata)
// 這個坐標點對應的顏色
let clickColor = getColor(x,y, imagedata)
console.log('這個坐標點對應的顏色', clickColor)
// 最后更改為紅色的rgba值
let targetBgArr = [255,0,0,255]
function changeColor(x,y){
// 邊界范圍
if(x<0 || x>canvas.width || y<0 || y>canvas.height){
return
}
let color = getColor(x,y,imagedata )
// 相似顏色的相差值
if(diffBg(color,clickColor)>150){
return
}
// 已經變為了目標色(紅色)
if(diffBg(color,targetBgArr)==0){
return
}
let i = bgIndex(x,y)
// 在內存中更改像素的顏色
imagedata.data.set(targetBgArr, i)
// 改變周圍(上下左右)的顏色
changeColor(x+1,y)
changeColor(x-1,y)
changeColor(x,y+1)
changeColor(x,y-1)
}
changeColor(x,y)
// 將內存中的像素點的顏色(重新繪制在畫布上)
ctx.putImageData(imagedata, 0, 0);
}
// 計算點擊坐標對應的像素索引
function bgIndex(x,y){
return (y * canvas.width + x) * 4;
}
// 根據索引得到顏色值
function getColor(x,y,imgData){
let i = bgIndex(x,y)
return [
imgData.data[i],
imgData.data[i+1],
imgData.data[i+2],
imgData.data[i+3]
]
}
// 查看兩個顏色的相差值
function diffBg(color1,color2){
// 我們是取兩個顏色的絕對值相加
return Math.abs(color1[0] -color2[0]) +
Math.abs(color1[1] -color2[1]) +
Math.abs(color1[2] -color2[2]) +
Math.abs(color1[3] -color2[3])
}
// 注冊事件
canvas.addEventListener("click", clickMy, false)
initPic({
url: '../assets/person1.png'
})
</script>
</html>
更改為按鈕,背景發生改變
上面我們實現了,點擊背景色,實現顏色的更改。
但是實際的過程中。
我們是不知道背景顏色的,怎么去確認背景顏色呢?
其實,可以默認坐標為(4,4)是背景顏色。
在實際的過程中,其實這個位置99.9999%是背景色。
我們是先選擇顏色,然后點擊確定,實現顏色的更改
現在我們來優化一下。讓用戶自己選擇背景色,選擇好后。
點擊確定,背景顏色就發生變化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
</style>
</head>
<body>
<div>
<canvas id="canvas">
</div>
<input type="color" id="color" >
<button id="red">確定</button>
</body>
<script type="text/javascript">
// 獲取dom節點
const canvas = document.getElementById('canvas')
// 獲取上下文
const ctx = canvas.getContext('2d',{
willReadFrequently:true
});
// 將16進制轉化為rgba的顏色值
function changeRGBA(hex) {
// 去除 # 開頭的第一個字符
hex = hex.slice(1);
// 將16進制字符串轉換rgba
let rgba = [];
for (let i = 0; i < 6; i += 2) {
let byte = parseInt(hex.substr(i, 2), 16);
rgba.push(byte);
}
// 添加 alpha 通道
rgba.push(255);
// 返回 RGBA 顏色值
return rgba;
}
function initPic(picInfo){
// 創建一個圖表的實例
const img = new Image()
img.onload =()=>{
// 設置畫布的寬高與圖片的保持一致
canvas.width= img.width
canvas.height= img.height
// 開始繪畫
ctx.drawImage(img, 0, 0 );
}
// 引入圖片的地址
img.src = picInfo.url
}
function clickMy(e, type){
let color = document.getElementById('color')
// 4,4的地方默認為是背景顏色
let x = 4
let y = 4
// 獲取所有的像素點顏色
let imagedata = ctx.getImageData(0, 0, canvas.width, canvas.height);
// 這個坐標點對應的顏色
let clickColor = getColor(x,y, imagedata)
console.log('這個坐標點對應的顏色', clickColor)
// 顏色為用戶選擇的值
let targetBgArr = changeRGBA(color.value)
function changeColor(x,y){
// 邊界范圍
if(x<0 || x>canvas.width || y<0 || y>canvas.height){
return
}
let color = getColor(x,y,imagedata )
// 相似顏色的相差值
if(diffBg(color,clickColor)>150){
return
}
// 已經變為了目標色(紅色)
if(diffBg(color,targetBgArr)==0){
return
}
let i = bgIndex(x,y)
// 在內存中更改像素的顏色
imagedata.data.set(targetBgArr, i)
// 改變周圍(上下左右)的顏色
changeColor(x+1,y)
changeColor(x-1,y)
changeColor(x,y+1)
changeColor(x,y-1)
}
changeColor(x,y)
// 將內存中的像素點的顏色(重新繪制在畫布上)
ctx.putImageData(imagedata, 0, 0);
}
// 計算點擊坐標對應的像素索引
function bgIndex(x,y){
return (y * canvas.width + x) * 4;
}
// 根據索引得到顏色值
function getColor(x,y,imgData){
let i = bgIndex(x,y)
return [
imgData.data[i],
imgData.data[i+1],
imgData.data[i+2],
imgData.data[i+3]
]
}
// 查看兩個顏色的相差值
function diffBg(color1,color2){
// 我們是取兩個顏色的絕對值相加
return Math.abs(color1[0] -color2[0]) +
Math.abs(color1[1] -color2[1]) +
Math.abs(color1[2] -color2[2]) +
Math.abs(color1[3] -color2[3])
}
// 注冊事件
canvas.addEventListener("click", clickMy, false)
red.addEventListener("click", clickMy, false)
initPic({
url: '../assets/person1.png'
})
</script>
</html>
最后的功能-下載
上面我們已經成功實現讓用戶選擇顏色。
更換用戶自己選擇的顏色。
下載我們只需要實現下載功能就好了。
下載功能主要使用 canvas.toDataURL
然后利用a標簽進行下載
<button id="down">下載</button>
down.addEventListener('click',()=>{
let imgURL = canvas.toDataURL({format: "image/png", quality:1, width:canvas.width, height:canvas.height});
let link = document.createElement('a');
link.download = "人物圖片";
link.href = imgURL;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
總結
以上是生活随笔為你收集整理的canvas实现动态替换人物的背景颜色的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 探索人工智能的世界:构建智能问答系统之前
- 下一篇: MIT实验警示:人类或需要人工智能辅助才