前言
两篇以前的文章还是很有用的:
canvas将图片转成点阵
vue基于html2canvas和jspdf 生成pdf 、解决jspdf中文乱码问题
实现
将图片添加到canvas中
<template>
<div>
<el-button type="primary" @click="loadImage">加载图片</el-button>
<canvas id="myCanvas" width="200" height="200" style="border:1px solid #000000;">
</canvas>
</div>
</template>
<script setup lang="ts">
import { nextTick } from 'vue';
// 加载图片
import imgSrc from '../../../assets/logo.png';
const loadImage = () => {
nextTick(() => {
// 创建图片
const image = document.createElement('img');
image.src = imgSrc;
image.width = 200;
image.height = 200;
// 获取canvas
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// 将图片添加到画布上
ctx.drawImage(image, 0, 0);
});
};
</script>
获取像素点的颜色值
// 图片像素,获取从(20,20)开始宽高为10的图片的像素
const imageData = ctx.getImageData(20, 20, 10, 10).data;
console.log('像素:', imageData);
四个数字是一组代表rgba
,像素点的个数是 宽度 * 长度 * 4
获取rgba
获取颜色还是比较简单的无非是进行循环,四个数字一组转成rgba
的格式。
不过有一个点要注意:
css中的rgba的a
是 0~1,0完全透明,1完全不透明。具体见:CSS rgba() 函数
getImageData
返回的a是 0~255,0完全透明,255是不透明的(即完全可见)。具体见:canvas getImageData() 方法
const rgbaList = [];
// 将像素转为rgba
for (let i = 0; i < imageData.length; i += 4) {
const r = imageData[i];
const g = imageData[i + 1];
const b = imageData[i + 2];
const a = imageData[i + 3] / 255;
rgbaList.push(`rgba(${r},${g},${b},${a})`);
}
console.log('颜色:', rgbaList);
rgba与16进制颜色之间的转换
rgba转16进制
// 数字转16进制
const toHex = (n:number) => {
return `${n > 15 ? '' : 0}${n.toString(16)}`;
};
// rgba 转16进制
const toHexString = (rgba:string) => {
const rgbaStr = rgba.replace(/[rgba|(|)]/g, '');
const rbgaList = rgbaStr.split(',').map(e => parseInt(e));
const hexStr = `#${toHex(rbgaList[0])}${toHex(rbgaList[1])}${toHex(rbgaList[2])}${rbgaList[3] === 1 ? '' : toHex(Math.floor(rbgaList[3] * 255))}`;
console.log(hexStr);
return hexStr;
};
16进制转rgba
// 16进制转rgba
const parseHexColor = (color: string) => {
let hex = color.slice(1);
let a = 1;
if (hex.length === 3) {
hex = `${hex[0]}${hex[0]}${hex[1]}${hex[1]}${hex[2]}${hex[2]}`;
}
if (hex.length === 8) {
a = parseInt(hex.slice(6), 16) / 255;
hex = hex.slice(0, 6);
}
const bigint = parseInt(hex, 16);
return {
r: (bigint >> 16) & 255,
g: (bigint >> 8) & 255,
b: bigint & 255,
a
};
};