最近经常有人在微信朋友圈晒芝麻信用的分数, 虽然我的分数没有达到欧洲某小国申根的要求, 不过也不低. 今天台风"灿鸿" 袭来, 外边大风又大雨, 又是周末, 于是就想用 html5 的canvas 做一个假的芝麻信用截图.
下面是一个效果图:

如果你想查看源代码, 或者修改, 看jsfiddle上的share
https://jsfiddle.net/manecocomph/edkg8z5w/1/
源代码:
html 源代码:
<canvas id="fakeImg"></canvas>
Javascript 源代码:
function drawTextAlongArc(context, str, centerX, centerY, radius, angle) {
var len = str.length, s;
context.save();
context.translate(centerX, centerY);
context.rotate(-1 * angle / 2);
context.rotate(-1 * (angle / len) / 2);
for (var n = 0; n < len; n++) {
context.rotate(angle / len);
context.save();
context.translate(0, -1 * radius);
s = str[n];
context.fillText(s, -14, 0);
context.restore();
}
context.restore();
}
// init score
var score = 849;
var screenWidth = 640;
var screenHeight = 1080;
var generalWordColor = 'gray';
var halfScreenWidth = screenWidth / 2;
// calculate angle & desc
var scoreDesc = "信用极好";
var angle = 1.8;
if (score <= 350) {
angle = 0.9;
scoreDesc = "信用极差";
} else if (score > 350 && score <= 550) {
angle = 0.9 + ((score - 350) / 200) * ((2.1 - 0.9) / 5);
scoreDesc = "信用较差";
} else if (score > 550 && score <= 700) {
angle = 0.9 + (2.1 - 0.9) / 5 + ((score - 550) / 150) * ((2.1 - 0.9) / 5 * 3);
if (score > 550 && score <= 600) {
scoreDesc = "信用中等";
} else if (score > 600 && score <= 650) {
scoreDesc = "信用良好";
} else {
scoreDesc = "信用优秀";
}
} else if (score > 700 && score <= 950) {
angle = 0.9 + (2.1 - 0.9) / 5 * 4 + ((score - 700) / 250) * ((2.1 - 0.9) / 5);
scoreDesc = "信用极好";
} else {
angle = 2.1;
scoreDesc = "信用爆棚";
}
// get canvas and set width & height
var canvas = document.getElementById("fakeImg");
canvas.setAttribute("width", screenWidth);
canvas.setAttribute("height", screenHeight);
var ctx = canvas.getContext("2d");
///// 开始画顶端 ////////
//header
ctx.fillStyle = '#000000';
ctx.fillRect(0, 0, screenWidth, 90);
//手机顶端
ctx.fillStyle = '#FFFFFF';
ctx.font = '10px Arial';
ctx.fillText("中国移动 4G", 5, 12);
ctx.fillText("13:59", halfScreenWidth - 22, 12);
ctx.fillRect(screenWidth - 50, 3, 10, 9);
ctx.strokeStyle = '#FFFFFF';
ctx.strokeRect(screenWidth - 50, 3, 30, 9);
ctx.font = '4px Arial';
ctx.fillText("▍", screenWidth - 20, 9);
//标题顶端
ctx.font = '24px Arial';
ctx.fillText("ㄑ 财富", 15, 60);
ctx.font = '28px Arial';
ctx.fillText("芝麻信用", halfScreenWidth - 66, 60);
ctx.strokeStyle = '#FFFFFF';
ctx.beginPath();
ctx.arc(screenWidth - 50, 50, 13, Math.PI * 2, 0, true);
ctx.stroke();
ctx.font = '20px Arial';
ctx.fillText("?", screenWidth - 55, 57);
///// 搜索部分
ctx.fillStyle = '#E4EDEC';
ctx.fillRect(0, 90, screenWidth, 60);
ctx.fillStyle = '#FFFFFF';
ctx.fillRect(60, 95, screenWidth - 120, 50);
ctx.font = '20px Arial';
ctx.fillStyle = 'gray';
ctx.fillText("看看Ta的芝麻分", 228, 130);
//search
ctx.beginPath();
ctx.arc(100, 122, 11, Math.PI * 2, 0, true);
ctx.strokeStyle = 'gray';
ctx.moveTo(108, 130);
ctx.lineTo(116, 137);
ctx.stroke();
//情怀部分
ctx.font = '26px Arial';
ctx.fillStyle = 'gray';
ctx.fillText("一 滴滴珍贵 重在参与 一", halfScreenWidth - 157, 203);
//////// 开始画中间的数据 //////////////
// init liner gradient, prepare for rainbow diagram
var grd = ctx.createLinearGradient(screenWidth / 9, screenHeight / 2, screenWidth / 9 * 8, screenHeight / 2);
grd.addColorStop(0, 'red');
grd.addColorStop(0.25, '#F99501');
grd.addColorStop(0.35, '#C1D500');
grd.addColorStop(0.55, '#AAE400');
grd.addColorStop(1, '#06D780');
// set circle center x,y
var circleCenterX = halfScreenWidth;
var circleCenterY = screenHeight / 2;
ctx.lineWidth = 25;
ctx.strokeStyle = grd;
// circle center : halfScreenWidth, circleCenterY 扇形部分
for (var i = 0; i < 45; i++) {
ctx.beginPath();
if (8 == i % 9) {
ctx.arc(halfScreenWidth, circleCenterY, screenWidth / 8 * 3, Math.PI * ((i + 1) * 0.02666 + 0.897), Math.PI * (0.9 + i * 0.02666), true);
} else {
ctx.arc(halfScreenWidth, circleCenterY, screenWidth / 8 * 3, Math.PI * ((i + 1) * 0.02666 + 0.899), Math.PI * (0.9 + i * 0.02666), true);
}
ctx.stroke();
}
// draw credit level
ctx.fillStyle = generalWordColor;
ctx.font = '16px Arial';
ctx.lineWidth = 1;
var str = ['350', '较差', '550', '中等', '600', '良好', '650', '优秀', '700', '较好', '950'];
drawTextAlongArc(ctx, str, halfScreenWidth, circleCenterY, screenWidth / 8 * 3 - 35, 3.95);
// 画内圈虚线
ctx.lineWidth = 1;
ctx.strokeStyle = 'gray';
for (var i = 0; i < 120; i = i + 2) {
ctx.beginPath();
ctx.arc(halfScreenWidth, circleCenterY, screenWidth / 4, Math.PI * (0.9 + (i + 1) * 0.01), Math.PI * (0.9 + i * 0.01), true);
ctx.stroke();
}
// drow outer circle
ctx.lineWidth = 3;
if (angle > 0.92) {
ctx.beginPath();
ctx.arc(halfScreenWidth, circleCenterY, screenWidth / 16 * 5, Math.PI * (angle - 0.02), Math.PI * 0.9, true);
ctx.strokeStyle = '#06D780';
ctx.stroke();
}
if (angle < 2.08) {
ctx.beginPath();
ctx.arc(halfScreenWidth, circleCenterY, screenWidth / 16 * 5, Math.PI * 2.1, Math.PI * (angle + 0.02), true);
ctx.strokeStyle = 'gray';
ctx.stroke();
}
// 开始画指针 第一步 指针三角
var anchorX1 = halfScreenWidth + screenWidth / 16 * 5 * Math.cos((angle - 0.02) * Math.PI);
var anchorY1 = circleCenterY + screenWidth / 16 * 5 * Math.sin((angle - 0.02) * Math.PI);
var anchorX2 = halfScreenWidth + screenWidth / 16 * 5 * Math.cos((angle + 0.02) * Math.PI);
var anchorY2 = circleCenterY + screenWidth / 16 * 5 * Math.sin((angle + 0.02) * Math.PI);
var anchorX3 = halfScreenWidth + (screenWidth / 16 * 5 - 36) * Math.cos(angle * Math.PI);
var anchorY3 = circleCenterY + (screenWidth / 16 * 5 - 36) * Math.sin(angle * Math.PI);
ctx.fillStyle = '#06D780';
ctx.beginPath();
ctx.moveTo(anchorX1, anchorY1);
ctx.lineTo(anchorX3, anchorY3);
ctx.lineTo(anchorX2, anchorY2);
ctx.fill();
ctx.closePath();
// 指针后部的2个圆圈的中心
var anchorX = halfScreenWidth + screenWidth / 16 * 5 * Math.cos(angle * Math.PI);
var anchorY = circleCenterY + screenWidth / 16 * 5 * Math.sin(angle * Math.PI);
// 指针后部 外环圆
ctx.strokeStyle = '#06D780';
ctx.beginPath();
ctx.arc(anchorX, anchorY, 12, 0, 2 * Math.PI, false);
ctx.stroke();
// 指针后部 中间白色圆
ctx.strokeStyle = '#FFFFFF';
ctx.lineWidth = 10;
ctx.beginPath();
ctx.arc(anchorX, anchorY, 5, 0, 2 * Math.PI, false);
ctx.stroke();
// 指针后部 最内部绿色圆
ctx.fillStyle = '#06D780';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(anchorX, anchorY, 5, 0, 2 * Math.PI, false);
ctx.fill();
// 内部文字部分
ctx.fillStyle = generalWordColor;
ctx.fillText("BETA", halfScreenWidth - 24, (circleCenterY - screenWidth / 4 + 62));
ctx.font = '94px Arial';
ctx.fillStyle = '#08BC8C';
ctx.fillText(score, halfScreenWidth - 84, (circleCenterY - screenWidth / 4 + 162));
ctx.font = '44px Arial';
ctx.fillText(scoreDesc, halfScreenWidth - 89, (circleCenterY - screenWidth / 4 + 212));
ctx.fillStyle = 'gray';
ctx.font = '14px Arial';
ctx.fillText("评估时间: 2015.07.11", halfScreenWidth - 74, (circleCenterY - screenWidth / 4 + 238));
ctx.strokeStyle = '#08BC8C';
ctx.strokeRect(halfScreenWidth - 85, (circleCenterY - screenWidth / 4 + 342), 180, 60);
ctx.font = '30px Arial';
ctx.fillStyle = '#08BC8C';
ctx.fillText("嘚瑟一下", halfScreenWidth - 50, (circleCenterY - screenWidth / 4 + 386));
ctx.font = '16px Arial';
ctx.fillStyle = 'gray';
ctx.fillText("高粱信用是合法独立的信用评估机构及信用采集机构", halfScreenWidth - 161, (circleCenterY - screenWidth / 4 + 432));
/////////// 开始画底部
//footer 的 2个点
ctx.fillStyle = '#06D780';
ctx.beginPath();
ctx.arc(halfScreenWidth - 35, screenHeight - 100, 8, 0, 2 * Math.PI, false);
ctx.fill();
ctx.fillStyle = 'gray';
ctx.beginPath();
ctx.arc(halfScreenWidth + 35, screenHeight - 100, 8, 0, 2 * Math.PI, false);
// 低端标题
ctx.fill();
ctx.fillStyle = '#EFF6EF';
ctx.fillRect(0, screenHeight - 80, screenWidth, 80);
ctx.font = '34px Arial';
ctx.fillStyle = '#27876B';
ctx.fillText("信用猜猜", 80, screenHeight - 25);
ctx.fillText("信用生活", halfScreenWidth + 80, screenHeight - 25);
ctx.strokeStyle = '#DBE4DF';
ctx.beginPath();
ctx.moveTo(0, screenHeight - 80);
ctx.lineTo(screenWidth, screenHeight - 80);
ctx.moveTo(halfScreenWidth, screenHeight - 80);
ctx.lineTo(halfScreenWidth, screenHeight);
ctx.stroke();