uniapp二次封装image 包含主色调识别,默认图,加载失败图
uniapp 二次封装image 包含主色调识别,默认图,加载失败图
·
前言
由于项目原因,直接用image 繁琐而麻烦,所以将其二次封装
实现 image渲染市默认图片,加载失败的底图,识别图片得主色调等功能
一、image?
二、使用步骤
1.image的二次封装
代码如下(示例):
<template>
<view class="y-image">
<view class="y-image" :class="{ nodispaly: imgLoaded }">
<image class="y-image" :src="src" @error="onErrorImg" @load="onSuccessImg" />
</view>
<div class="default" :class="{ nodispaly: !imgLoaded }">
<image
class="y-image-default"
:style="defaultSryle"
:src="require('@/assets/bank_no_networ-icon.png')"
/>
</div>
//识别主色调的时候要用
<template v-if="isBgColor">
<view class="canvasstyle" v-if="isCanvas">
<canvas :canvas-id="pid" id="pid"></canvas>
</view>
</template>
</view>
</template>
<script>
// 引用的解析图片的主色调的方法在下边
import { getImageThemeColor } from '@/utils/getImageThemeColorCanvas'
export default {
name: 'imageModel',
props: {
// 是否开启获取主色调
isBgColor: {
type: Boolean,
default: false,
},
// 默认随生成Pid canvas
pid: {
type: String,
default: () => {
return Math.random().toString(36).slice(3, 10)
},
},
// 默认iocn 大小
defaultSize: {
type: String,
default: '100%',
},
//图片裁剪、缩放的模式
mode: {
type: String,
default: 'center',
},
//图片资源地址
src: String,
},
data() {
return {
imgLoaded: true,
isCanvas: true,
}
},
computed: {
defaultSryle() {
return `width:${this.defaultSize};height:${this.defaultSize}`
},
},
created() {
if (!this.src) {
this.$emit('onSuccessImg', '')
this.isCanvas = false
}
},
methods: {
// 图片加载成功
async onSuccessImg(event) {
let color = ''
if (this.isBgColor) {
try {
color = await getImageThemeColor(this.src, this.pid)
} catch (error) {
console.err('解析图片报错':error)
}
}
this.$emit('onSuccessImg', color)
this.isCanvas = false
this.imgLoaded = false
},
// 图片加载失败
onErrorImg(event) {
this.$emit('onSuccessImg', '')
this.imgLoaded = true
this.isCanvas = false
},
},
}
</script>
<style lang="scss" scoped>
.nodispaly {
display: none !important;
}
.y-image {
width: 100%;
height: 100%;
overflow: hidden;
}
.default {
background: #f2f2f2;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.y-image-default {
width: 100%;
height: 100%;
}
}
.canvasstyle {
position: absolute;
top: -9999999rpx;
}
</style>
注意 因为使用canvas 画出当前图片 所以 注意因为图片跨域而失败
因为性能原因 页面默认是不渲染canvas标签,只有需要的时候主动开启,解析出颜色值后销毁canvas
2.解析图片主色调
代码如下(示例):
文件名字 getImageThemeColorCanvas.js
/**
* 获取图片主题色
* @param {String} path
* 图片的路径,可以是相对路径,临时文件路径,存储文件路径,网络图片路径
* @param {String} canvasId
* 画布表示
* return 返回色值的promise
*/
export async function getImageThemeColor(path, canvasId) {
return await new Promise((resolve, reject) => {
uni.getImageInfo({
src: path,
success: function (img) {
// 创建一个 Canvas 对象
const ctx = uni.createCanvasContext(canvasId)
// 将图片绘制到 Canvas 上
const imgWidth = 300
const imgHeight = 150
ctx.drawImage(img.path, 0, 0, imgWidth, imgHeight)
ctx.save()
ctx.draw(true, () => {
uni.canvasGetImageData({
canvasId: canvasId,
x: 0,
y: 0,
width: imgWidth,
height: imgHeight,
success(res) {
let data = res.data
let arr = []
let r = 1,
g = 1,
b = 1
// 取所有像素的平均值
for (let row = 0; row < imgHeight; row++) {
for (let col = 0; col < imgWidth; col++) {
if (row == 0) {
r += data[imgWidth * row + col]
g += data[imgWidth * row + col + 1]
b += data[imgWidth * row + col + 2]
arr.push([r, g, b])
} else {
r += data[(imgWidth * row + col) * 4]
g += data[(imgWidth * row + col) * 4 + 1]
b += data[(imgWidth * row + col) * 4 + 2]
arr.push([r, g, b])
}
}
}
// 求取平均值
r /= imgWidth * imgHeight
g /= imgWidth * imgHeight
b /= imgWidth * imgHeight
// 将最终的值取整
r = Math.round(r)
g = Math.round(g)
b = Math.round(b)
//最终返回的主色调
resolve(`${r},${g},${b}`)
fail: (fail) => {
console.log(fail)
reject(fail)
},
})
})
},
fail: (fail) => {
console.log(fail)
reject(fail)
},
})
})
}
/**
* 同步请求所有 Promise
* @param {Array} asyncFunctions
* Promise 数组
* @returns 返回Promise值
*/
export async function executeAsyncFunctions(asyncFunctions) {
const results = []
for (const asyncFunction of asyncFunctions) {
const result = await asyncFunction()
results.push(result)
}
return results
}
注意 引用的页面内一定要有canvas标签存在。
解析主色调方法可以单独引用, 一个页面如果多张图片进行解析主色调,一定要等上一个解下完成,再进行下一个!!! 坑自己去踩 你可以试试 自己封装了一个同步请求的方法 可以参考下
总结
生活不易,处处是坑,既然还活着,那就风雨兼程
更多推荐
已为社区贡献3条内容
所有评论(0)