-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.js
275 lines (227 loc) · 6.83 KB
/
main.js
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
const defaultColor = 'rgb(11,164,231)'
const genBtn = document.getElementById('genBtn')
genBtn.addEventListener('click', draw)
draw()
function draw() {
const uid = document.getElementById('uid').value
const username = document.getElementById('username').value
const color = document.getElementById('color').value
drawSignature(uid, username, color)
}
// 绘制签名档
function drawSignature (uid, username, color) {
color = color || defaultColor
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
ctx.fillStyle = 'rgba(0,0,0,0)'
ctx.clearRect(0, 0, 600, 110)
ctx.save()
drawLogo(ctx, 65, 50, color)
// 签名卡背景
ctx.globalCompositeOperation = 'destination-over'
ctx.fillStyle = 'rgb(238,238,238)'
drawRoundedPolygon(ctx, [{x: 0, y: 10}, {x: 600, y: 10}, {x: 600, y: 110}, {x: 0, y: 110}], 8)
ctx.fill()
// 个人信息
ctx.globalCompositeOperation = 'source-atop'
drawInfo(ctx, 130, 0, color, uid, username)
ctx.restore()
}
// 绘制logo
function drawLogo (ctx, x, y, color) {
ctx.save()
ctx.translate(x, y)
// 六边形
ctx.fillStyle = color
drawRoundedPolygon(ctx, getPolygonPoints(0, 0, 6, 50), 5)
ctx.fill()
ctx.globalCompositeOperation = 'source-atop'
// 六边形内阴影
ctx.fillStyle = 'rgba(0,0,0,0.05)'
drawRoundedPolygon(ctx, getPolygonPoints(-2, -4, 6, 50), 5)
ctx.fill()
// 斜光影
ctx.fillStyle = 'rgba(255,255,255,0.1)'
ctx.rotate(-Math.PI / 6)
ctx.beginPath()
ctx.rect(-50, -50, 100, 50)
ctx.closePath()
ctx.fill()
// 圆形光影1
ctx.fillStyle = 'rgba(255,255,255,0.18)'
ctx.beginPath()
ctx.arc(0, -30, 40, 0, Math.PI * 2)
ctx.closePath()
ctx.fill()
// 圆形光影2
ctx.fillStyle = 'rgba(255,255,255,0.3)'
ctx.beginPath()
ctx.arc(0, -60, 40, 0, Math.PI * 2)
ctx.closePath()
ctx.fill()
// 气泡长投影
ctx.fillStyle = 'rgba(0,0,0,0.08)'
ctx.beginPath()
ctx.rect(-30, 0, 60, 60)
ctx.closePath()
ctx.fill()
// 气泡投影
ctx.fillStyle = 'rgba(0,0,0,0.1)'
drawBubble(ctx, 0, 3, 30, 8, Math.PI / 2.3)
ctx.fill()
// 气泡
ctx.fillStyle = 'rgb(238,238,238)'
drawBubble(ctx, 0, 0, 30, 8, Math.PI / 2.3)
ctx.fill()
ctx.rotate(Math.PI / 6)
// HAYO (Consolas)
ctx.rotate(-Math.PI / 12)
ctx.font = '24px Consolas'
ctx.fillStyle = color
ctx.fillText('HAYO', -25, 8)
// Studio (Consolas)
// ctx.font = '12px Consolas' // 最小字体12px
// ctx.fillStyle = color
// ctx.fillText('Studio', -13, 16)
// ~ (华文隶书 STLiti bold)
ctx.rotate(Math.PI / 16)
ctx.font = 'bold 26px STLiti' // 最小字体12px
ctx.fillStyle = 'rgb(238,238,238)'
ctx.fillText('~', 26, -8)
// 六边形外阴影
ctx.globalCompositeOperation = 'destination-over'
ctx.rotate(0.06)
ctx.fillStyle = 'rgb(214,214,214)'
drawRoundedPolygon(ctx, getPolygonPoints(3, 3, 6, 52), 5)
ctx.fill()
ctx.restore()
}
// 绘制个人信息
function drawInfo (ctx, x, y, color, uid, username) {
ctx.save()
ctx.translate(x, y)
ctx.fillStyle = 'rgb(214,214,214)'
drawRoundedPolygon(ctx, [{x: 0, y: 0}, {x: 200, y: 0}, {x: 200, y: 25}, {x: 0, y: 25}], 5)
ctx.fill()
ctx.fillStyle = color
drawRoundedPolygon(ctx, [{x: 0, y: 31}, {x: 100, y: 31}, {x: 100, y: 56}, {x: 0, y: 56}], 5)
ctx.fill()
ctx.fillStyle = color
drawRoundedPolygon(ctx, [{x: 0, y: 62}, {x: 150, y: 62}, {x: 150, y: 87}, {x: 0, y: 87}], 5)
ctx.fill()
ctx.fillStyle = 'rgb(214,214,214)'
drawRoundedPolygon(ctx, [{x: 0, y: 93}, {x: 80, y: 93}, {x: 80, y: 118}, {x: 0, y: 118}], 5)
ctx.fill()
ctx.fillStyle = 'white'
ctx.font = '12px Microsoft Yahei'
ctx.fillText('UID', 5, 48)
ctx.font = '14px Microsoft Yahei'
ctx.fillText(uid, 30, 48)
ctx.font = '14px Microsoft Yahei'
ctx.fillText(username, 5, 80)
ctx.fillStyle = color
ctx.rotate(-Math.PI / 4)
ctx.beginPath()
ctx.rect(30, 200, 250, 50)
ctx.closePath()
ctx.fill()
ctx.font = '14px Microsoft Yahei'
ctx.fillStyle = 'rgb(238,238,238)'
ctx.fillText('HAYO Studio', 80, 220)
ctx.fillStyle = 'rgb(238,238,238)'
ctx.fillText('专用签名档', 130, 240)
ctx.restore()
ctx.fillStyle = 'rgb(255,255,255)'
ctx.beginPath()
ctx.rect(505, 15, 90, 90)
ctx.closePath()
ctx.fill()
const qrcode = document.getElementById('qrcode')
ctx.imageSmoothingEnabled = false
ctx.drawImage(qrcode, 505, 15, 90, 90)
ctx.fillStyle = 'rgb(180,180,180)'
ctx.font = '12px Microsoft Yahei'
ctx.fillText('HAYO Studio', 425, 85)
ctx.fillText('交流&审核群', 430, 100)
}
// 绘制普通多边形
// function drawPolygon (ctx, points) {
// if (!points.length) return
// ctx.beginPath()
// const len = points.len
// for (let i = 0; i < len; i++) {
// const p = points[i]
// if (i === 0) ctx.moveTo(p.x, p.y)
// else ctx.lineTo(p.x, p.y)
// }
// ctx.closePath()
// }
// 绘制圆角多边形
function drawRoundedPolygon (ctx, points, radius) {
if (!points.length) return
const pointGroups = getRoundedPointGroups(points, radius)
ctx.beginPath()
const len = pointGroups.length
for (let i = 0; i < len; i++) {
const group = pointGroups[i]
if (i === 0) ctx.moveTo(group.pre.x, group.pre.y)
else ctx.lineTo(group.pre.x, group.pre.y)
ctx.quadraticCurveTo(group.cur.x, group.cur.y, group.next.x, group.next.y)
}
ctx.closePath()
}
// 获取圆角坐标组(起始点,控制点,结束点)
function getRoundedPointGroups (points, radius) {
const len = points.length
const pointGroups = []
for (let i = 0; i < len; i++) {
let pre = (i - 1 < 0) ? points[len - 1] : points[i - 1]
let next = (i + 1 === len) ? points[0] : points[i + 1]
let cur = points[i]
pre = getRoundedPoint(pre, cur, radius, false)
next = getRoundedPoint(cur, next, radius, true)
pointGroups.push({
pre: pre,
cur: cur,
next: next
})
}
return pointGroups
}
// 获取圆角坐标(起始点或结束点)
function getRoundedPoint (p1, p2, radius, first) {
const total = Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2))
const percent = first ? radius / total : (total - radius) / total
return {
x: p1.x + (percent * (p2.x - p1.x)),
y: p1.y + (percent * (p2.y - p1.y))
}
}
// 获取多边形点集
function getPolygonPoints (x, y, sides, radius, startAngle) {
const points = []
let angle = startAngle || 0
for (let i = 0; i < sides; i++) {
points.push({
x: x + radius * Math.sin(angle),
y: y + radius * Math.cos(angle)
})
angle += Math.PI * 2 / sides
}
return points
}
// 绘制气泡
function drawBubble (ctx, x, y, radius, gap, rotate) {
const gapRadian = gap / radius
const startAngle = gapRadian / 2
const endAngle = -gapRadian / 2
rotate = rotate || 0
ctx.save()
ctx.translate(x, y)
ctx.beginPath()
ctx.rotate(rotate)
ctx.arc(0, 0, radius, startAngle, endAngle)
ctx.lineTo(radius + gap, 0)
ctx.closePath()
ctx.restore()
}