源于 https://ask.csdn.net/questions/7797682
效果
輸入
輸出
環(huán)境
基礎(chǔ)庫版本 2.20.x使用的新版的canvas(也不算新兩三年了)。
知識(shí)點(diǎn)
-
canvas
-
base64轉(zhuǎn)臨時(shí)路徑
代碼
index.wxml
<canvas type="2d" id="photo" class="photo" disable-scroll="{{true}}" style="width: {{width}}rpx;height: {{height}}rpx;"></canvas>
<button type="primary" bindtap="chooseImage">選擇照片</button>
index.wxss
.photo {
margin: 80rpx auto;
background-color: rgb(68, 48, 247);
border: 4px solid #ddd;
}
index.js 重點(diǎn)
代碼沒有進(jìn)行封裝,僅僅只是方便預(yù)覽
const app = getApp()
Page({
data: {
canvas: null,
ctx: null,
height: 441,
width: 358,
},
onReady() {
// 創(chuàng)建一個(gè) SelectorQuery 對(duì)象,選擇器選取范圍為這個(gè)組件實(shí)例內(nèi)
const query = this.createSelectorQuery()
// 選擇wxml上id是photo的元素
query.select('#photo').fields({ node: true, size: true });
// 執(zhí)行
query.exec((res) => {
const canvas = res[0].node // 因?yàn)榉祷氐氖菙?shù)組 所以要去第一個(gè)
const ctx = canvas.getContext('2d') // 獲取畫布內(nèi)容
canvas.width = this.data.width // 真實(shí)寬度
canvas.height = this.data.height // 真實(shí)高度
this.data.canvas = canvas; // 暫存到data中方便其他方法調(diào)用
this.data.ctx = ctx; // 暫存到data中方便其他方法調(diào)用
})
},
chooseImage() { // 選擇圖片
wx.chooseMedia({ // 選擇媒體
count: 1, // 照片數(shù)量
mediaType: ['image'], // 圖片
sourceType: ['album'], // 相冊(cè)
success: (res) => {
let tempFilePath = res.tempFiles[0].tempFilePath
const canvas = this.data.canvas; // 畫布
const ctx = this.data.ctx;
const { width, height } = canvas; // 畫布的大小
let tempImage = canvas.createImage();
tempImage.src = tempFilePath;
tempImage.onload = () => {
// fill 填充模式
let originWidth = tempImage.width; // 原寬度
let originHeight = tempImage.height; // 原高度
let targetWidth = width; // 目標(biāo)寬度
let targetHeight = height; // 目標(biāo)高度
let scale = 0; // 臨時(shí)比例
// 當(dāng)原寬度小于原高度時(shí)
if (originWidth < originHeight) {
// 臨時(shí)比例暫存
scale = originWidth / originHeight;
originWidth = targetWidth;
originHeight = originWidth / scale;
}
// 非
else {
scale = originWidth / originHeight;
originHeight = targetHeight;
originWidth = originHeight * scale;
}
// 計(jì)算偏移量
const offsetX = - (originWidth - targetWidth) / 2
const offsetY = - (originHeight - targetHeight) / 2
// 清空畫布
ctx.clearRect(0, 0, canvas.width, canvas.height)
// 繪制圖片
ctx.drawImage(tempImage, offsetX, offsetY, originWidth, originHeight)
const base64 = canvas.toDataURL() // canvas輸出base64
const fs = wx.getFileSystemManager(); // 獲取獲取全局唯一的文件管理器
const filePath = wx.env.USER_DATA_PATH + '/tmp.png'; // 寫入臨時(shí)路徑
fs.writeFile({
filePath,
data: base64.replace(/^data:image\/\w+;base64,/, ""), // 剔除base64特有前綴
encoding: 'base64',
success: (res) => {
wx.saveImageToPhotosAlbum({ // 保存到手機(jī)相冊(cè)
filePath,
success: (res) => {
wx.showToast({
title: '保存成功',
})
}
})
}
});
}
}
})
}
})
源碼
完整代碼片段
https://developers.weixin.qq.com/s/ERW91Dma7QCP
私信的問題
Q: Camera 如何放置遮罩層?
如果想用cover-image組件,也是一樣,建議使用直接使用image組件。
<camera device-position="back" flash="off" binderror="error" style="width: 100%; height: 300px;">
<image src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Finews.gtimg.com%2Fnewsapp_bt%2F0%2F13210298185%2F1000&refer=http%3A%2F%2Finews.gtimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1667063277&t=74fe7de947f94409ff089e9b123d87ef"></image>
</camera>
評(píng)論的問題
Q: 使用Camera組件如何套用該案例?
將canvas組件復(fù)制到頁面中,把拍照返回的臨時(shí)圖片路徑替換到選擇圖片回調(diào)返回的臨時(shí)圖片。
代碼部分
index.wxml 節(jié)選
<!-- 追加到頁面 -->
<canvas type="2d" id="photo" class="photo" disable-scroll="{{true}}" style="width: {{width}}rpx;height: {{height}}rpx;"></canvas>
index.js 重點(diǎn) 全
const app = getApp()
Page({
data: {
canvas: null,
ctx: null,
height: 441,
width: 358,
},
onReady() {
// 創(chuàng)建一個(gè) SelectorQuery 對(duì)象,選擇器選取范圍為這個(gè)組件實(shí)例內(nèi)
const query = this.createSelectorQuery()
// 選擇wxml上id是photo的元素
query.select('#photo').fields({ node: true, size: true });
// 執(zhí)行
query.exec((res) => {
const canvas = res[0].node // 因?yàn)榉祷氐氖菙?shù)組 所以要去第一個(gè)
const ctx = canvas.getContext('2d') // 獲取畫布內(nèi)容
canvas.width = this.data.width // 真實(shí)寬度
canvas.height = this.data.height // 真實(shí)高度
this.data.canvas = canvas; // 暫存到data中方便其他方法調(diào)用
this.data.ctx = ctx; // 暫存到data中方便其他方法調(diào)用
})
},
onLoad() {
this.ccc = wx.createCameraContext()
},
takePhoto() {
this.ccc.takePhoto({
quality: 'high',
success: (res) => {
let tempFilePath = res.tempImagePath
const canvas = this.data.canvas; // 畫布
const ctx = this.data.ctx;
const { width, height } = canvas; // 畫布的大小
let tempImage = canvas.createImage();
tempImage.src = tempFilePath;
tempImage.onload = () => {
// fill 填充模式
let originWidth = tempImage.width; // 原寬度
let originHeight = tempImage.height; // 原高度
let targetWidth = width; // 目標(biāo)寬度
let targetHeight = height; // 目標(biāo)高度
let scale = 0; // 臨時(shí)比例
// 當(dāng)原寬度小于原高度時(shí)
if (originWidth < originHeight) {
// 臨時(shí)比例暫存
scale = originWidth / originHeight;
originWidth = targetWidth;
originHeight = originWidth / scale;
}
// 非
else {
scale = originWidth / originHeight;
originHeight = targetHeight;
originWidth = originHeight * scale;
}
// 計(jì)算偏移量
const offsetX = - (originWidth - targetWidth) / 2
const offsetY = - (originHeight - targetHeight) / 2
// 清空畫布
ctx.clearRect(0, 0, canvas.width, canvas.height)
// 繪制圖片
ctx.drawImage(tempImage, offsetX, offsetY, originWidth, originHeight)
const base64 = canvas.toDataURL() // canvas輸出base64
const fs = wx.getFileSystemManager(); // 獲取獲取全局唯一的文件管理器
const filePath = wx.env.USER_DATA_PATH + '/tmp.png'; // 寫入臨時(shí)路徑
fs.writeFile({
filePath,
data: base64.replace(/^data:image\/\w+;base64,/, ""), // 剔除base64特有前綴
encoding: 'base64',
success: (res) => {
wx.saveImageToPhotosAlbum({ // 保存到手機(jī)相冊(cè)
filePath,
success: (res) => {
wx.showToast({
title: '保存成功',
})
}
})
}
});
}
}
})
},
error(e) {
console.log(e.detail)
}
})
源碼
https://developers.weixin.qq.com/s/DxGSlEmD7wCu
拓展
處理圖片的顏色值文章來源:http://www.zghlxwxcb.cn/news/detail-487791.html
index.js 節(jié)選文章來源地址http://www.zghlxwxcb.cn/news/detail-487791.html
// 繪制圖片
ctx.drawImage(tempImage, offsetX, offsetY, originWidth, originHeight)
// getImageData
// 按照從左到右,從上到下的順序去存儲(chǔ)像素點(diǎn)信息
// 每四個(gè)數(shù)組元素代表了一個(gè)像素點(diǎn)的RGBA信息
const imageData = ctx.getImageData(0, 0, originWidth, originHeight)
// 灰度范圍
const minGray = 230;
// 目標(biāo)色
const white = 255;
for (let i = 0; i < imageData.data.length; i += 4) {
let tmpRed = imageData.data[i]
let tmpGreen = imageData.data[i + 1]
let tmpBlue = imageData.data[i + 2]
let tmpAlpha = imageData.data[i + 3]
if (tmpRed > minGray && tmpGreen > minGray && tmpBlue > minGray && tmpAlpha > minGray) {
imageData.data[i] = white;
imageData.data[i + 1] = white;
imageData.data[i + 2] = white;
imageData.data[i + 3] = white;
}
}
ctx.putImageData(imageData, 0, 0)
到了這里,關(guān)于微信小程序 Canvas裁切案例的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!