canvas渲染上下文设置填充样式,在安卓机型上不生效

本博客 hjy-xh,转载请申明出处

探究起因

省流:当设置透明度时,尽量使用ctx.fillStyle = 'rgb(174, 238, 238, 0.5)';的形式,而非ctx.fillStyle = '#AEEEEE80';后者在安卓真机(华为自带浏览器下必现)下无效

最近客户反馈在安卓机型下打开我们的签署页面,水印的颜色和透明度不管如何设置,都不生效,而IOS的表现正常

关键代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const canvas = document.createElement('canvas');
ctx.fillStyle = colorRgb(color, transparency);

/**
* 获取颜色的16进制 (颜色+透明度)
*
* @param color 颜色
* @param transparency 透明度
* @returns
*/
const convertColor = (color: string, transparency: number) => {

const getPureColor = (color: string) => {
const plainColor = color?.substring(1); // 去掉#
const isColorShort = plainColor?.length === 3;
return isColorShort ? plainColor.split('').map(v => `${v}${v}`).join('') : plainColor;
};

const getAlpha = (transparency: number) => {
const alpha = parseInt(String(256 * transparency), 10).toString(16);
return alpha.length > 1 ? alpha : `0${alpha}`;
};

return `#${getPureColor(color)}${getAlpha(transparency)}`;
};

以 颜色:#AEEEEE,透明度:0.5 为例,转化后得到结果#AEEEEE80,将结果赋值给ctx.fillStyle,在PC端使用chrome浏览器调试表现正常,但是在安卓真机上无效

左图为透明度为1,右图透明度为0.2,在华为自带浏览器下测试结果对比图如下:

完整demo如下,可以用node起一个服务,在手机上打开:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas颜色和透明度不生效</title>
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
</head>

<body>
<canvas id="canvas"></canvas>

<script type="text/javascript">
window.onload = function () {
new window.VConsole();

const canvas = document.getElementById("canvas");
canvas.width = 1000;
canvas.height = 1000;
const ctx = canvas.getContext("2d");
ctx.font = "20px Microsoft YaHei";
// ctx.fillStyle = convertColor('#AEEEEE', 0.2);
ctx.fillStyle = convertColor('#AEEEEE', 1);

// 绘制文字水印
for (let i = 0; i < 100; i++) {
for (let j = 0; j < 100; j++) {
ctx.fillText("Hello world", 150 * (i), 50 * (j + 1));
}
}
}

/**
* 获取颜色的16进制 (颜色+透明度)
*
* @param color 颜色
* @param transparency 透明度
* @returns
*/
const convertColor = (color, transparency) => {

const getPureColor = (color) => {
const plainColor = color?.substring(1); // 去掉#
const isColorShort = plainColor?.length === 3;
return isColorShort ? plainColor.split('').map(v => `${v}${v}`).join('') : plainColor;
};

const getAlpha = (transparency) => {
const alpha = parseInt(String(256 * transparency), 10).toString(16);
return alpha.length > 1 ? alpha : `0${alpha}`;
};

return `#${getPureColor(color)}${getAlpha(transparency)}`;
};
</script>
</body>

</html>