如果让你用代码实现图片将彩色图片变成灰白,你会怎么实现?
CSS的filter属性
filter: grayscale(100%)
遇到的兼容性问题
在之前的活动页面中,对于上面的这个需求,我使用了CSS的属性filter: grayscale(100%)完美实现,一开始我还想着会不会有兼容性问题,测了几部机器都正常,测试同事也没有提出有问题,用filter: grayscale(100%)一行代码实在是太方便了。
就这样活动页面上线了一个月,前几天刚吃瓜说有人升级iOS16后微信打不开还是咋的,我就笑笑,庆幸我不是苹果用户。没想到今天刚上班测试就给我提了个bug,说他的手机iPhone12升级到iOS16后页面显示异常了,iPhone13也是,我一看

我使用了CSS的filter属性的部分一片空白了。 于是开始调试: 去掉filter,显示为彩色,filter加在body上,居然能正常整个页面灰色显示。但加在body上不是我想要的效果,于是尝试将原来的元素加transform:translateZ(0)提升为渲染层。结果就能正常显示。amazing~ but why?哪位大佬可以赐教一下,iOS16升级后浏览器是有什么更改吗?
canvas实现
使用canvas用JS实现,用canvas绘制彩色图片后,用getImageData获取canvas区域隐含的像素数据,替换每个点的rgba值为灰色对应的rgba。然后将数据从修改后的ImageData对象绘制到canvas上。 注意:JS读取图片的内容,所以需要解决访问图片资源跨域的问题。需要让运维或者服务端配置返回跨域资源响应头。
export function convertToGray(originImg, canvasId) {
const imgIns = new Image();
imgIns.setAttribute('crossOrigin', 'anonymous');
imgIns.onload = function() {
const canvas = document.getElementById(canvasId);
canvas.width = imgIns.width;
canvas.height = imgIns.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(imgIns, 0, 0);
const greyImg = getColorData(canvas, ctx);
putColorData(ctx, greyImg);
};
imgIns.src = originImg;
}
function getColorData(canvas, ctx) {
const length = canvas.width * canvas.height;
console.log(canvas.width, canvas.height);
const myImage = ctx.getImageData(0, 0, canvas.width, canvas.height);
for (let i = 0; i < length * 4; i += 4) {
const myRed = myImage.data[i];//红色通道
const myGreen = myImage.data[i + 1];//绿色通道
const myBlue = myImage.data[i + 2];//蓝色通道
const myGray = parseInt((myRed + myGreen + myBlue) / 3);
myImage.data[i] = myGray;
myImage.data[i + 1] = myGray;
myImage.data[i + 2] = myGray;
}
return myImage;
}
function putColorData(ctx, myImage) {
ctx.putImageData(myImage, 0, 0);
}
图片切换
简单粗暴的方法,如果图比较少且固定的话,可以让设计同学切彩色的和灰色的图,不同情况下切换图片