-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
178 lines (159 loc) · 5.49 KB
/
index.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
/*!
* avatar-icon
* Copyright(c) 2023 Murat Motz
* MIT Licensed
* https://github.com/ztomm/avatar-icon
*/
'use strict'
/**
* Module dependencies
* ----------------------------------------------------------
*/
const { createCanvas } = require('canvas')
/**
* Module
* ----------------------------------------------------------
*/
module.exports = function avatarIcon(options) {
options = options || {}
// Documentation for the options under https://github.com/ztomm/avatar-icon
options = {
size : 48, // px
density : 6, // amount of shapes
colorRange : 12, // amount of different colors
brightness : 40, // make it bright: start at 40 from 255 colors
contrast : 50, // %, take similar colors
backgroundColor : '', // #hex or empty
fillRatio : 60, // %, let some white space
rectangleRatio : 60, // %, ratio of rectangles
triangleRatio : 40, // %, ratio of triangles
circleRatio : 0, // %, ratio of circles
returnType : '', // default dataURL || 'buffer'
...options // assign user options to default options
}
// redundant but more readable
let size = options.size
let density = options.density
let colorRange = options.colorRange
let brightness = options.brightness
let contrast = options.contrast
let backgroundColor = options.backgroundColor
let fillRatio = options.fillRatio
let rectangleRatio = options.rectangleRatio
let triangleRatio = options.triangleRatio
let circleRatio = options.circleRatio
let returnType = options.returnType
// canvas
let canvas = createCanvas(size, size)
let ctx = canvas.getContext('2d')
if (backgroundColor !== '') {
ctx.fillStyle = backgroundColor
ctx.fillRect(0, 0, canvas.width, canvas.height)
}
// quarter canvas
let quarterSize = size / 2
density = density / 2
let blockSize = quarterSize / density
// data to draw
let data = []
// create colorset
let rgba = []
for (let i = 0; i < 3; i++)
rgba.push(Math.round(Math.random() * (255 - brightness)) + brightness)
let colors = []
for (let i = 0; i < colorRange; i++)
colors.push([
Math.round(rgba[0] * (100 - (Math.random() * contrast)) / 100),
Math.round(rgba[1] * (100 - (Math.random() * contrast)) / 100),
Math.round(rgba[2] * (100 - (Math.random() * contrast)) / 100),
1
])
// fill up white space (%)
for (let i = 0; i < (density - Math.round(density * (fillRatio / 100))); i++)
colors.push([255, 255, 255, 0])
// triangle (x, y, size, direction, reverse)
let changeTriangelMatrix = Math.round(Math.random() * 1)
let getTriangle = function (x, y, s, d, r) {
let t = [
[x + s, y + 0, x + 0, y + 0, x + 0, y + s],
[x + s, y + s, x + s, y + 0, x + 0, y + 0],
[x + 0, y + 0, x + 0, y + s, x + s, y + s],
[x + 0, y + s, x + s, y + s, x + s, y + 0],
]
if (changeTriangelMatrix)
t = [t[2], t[3], t[0], t[1]]
return r ? ([...t].reverse())[d] : t[d]
}
// create random data
// loop rows
for (let i = 0; i < density; i++) {
// loop cols
for (let j = 0; j < density; j++) {
let c = colors[Math.floor(Math.random() * colors.length)]
let style = `rgba(${c[0]}, ${c[1]}, ${c[2]}, ${c[3]})`
let shape = ''
let triangelReverse = Math.round(Math.random() * 1)
let shapeRatioTotal = rectangleRatio + triangleRatio + circleRatio
let shapeRatioRanges = [0, circleRatio, triangleRatio + circleRatio, shapeRatioTotal]
let shapeType = Math.round(Math.random() * shapeRatioTotal)
if (shapeType <= shapeRatioRanges[3])
shape = 'rec'
if (shapeType < shapeRatioRanges[2])
shape = 'tri'
if (shapeType < shapeRatioRanges[1])
shape = 'arc'
// loop mirrors
for (let k = 0; k < 4; k++) {
let ctxData = { style }
let x = blockSize * j
let y = blockSize * i
if (k === 1) {
x = size - blockSize - (blockSize * j)
}
if (k === 2) {
y = size - blockSize - (blockSize * i)
}
if (k === 3) {
x = size - blockSize - (blockSize * j)
y = size - blockSize - (blockSize * i)
}
if (shape === 'rec') {
ctxData.rect = [x, y, blockSize, blockSize]
}
if (shape === 'tri') {
let t = getTriangle(x, y, blockSize, k, triangelReverse)
ctxData.triangle = [t[0], t[1], t[2], t[3], t[4], t[5]]
}
if (shape === 'arc') {
ctxData.arc = [x + (blockSize / 2), y + (blockSize / 2), blockSize / 2, 0, 2 * Math.PI]
}
data.push(ctxData)
}
}
}
// draw data
for (let i = 0; i < data.length; i++) {
ctx.fillStyle = data[i].style
if (data[i].rect) {
ctx.fillRect(data[i].rect[0], data[i].rect[1], data[i].rect[2], data[i].rect[3])
}
if (data[i].triangle) {
ctx.beginPath()
ctx.moveTo(data[i].triangle[0], data[i].triangle[1])
ctx.lineTo(data[i].triangle[2], data[i].triangle[3])
ctx.lineTo(data[i].triangle[4], data[i].triangle[5])
ctx.closePath()
ctx.fill()
}
if (data[i].arc) {
ctx.beginPath()
ctx.arc(data[i].arc[0], data[i].arc[1], data[i].arc[2], data[i].arc[3], data[i].arc[4])
ctx.closePath()
ctx.fill()
}
}
if (returnType === 'buffer')
return canvas.toBuffer('image/png')
// write buffer to disk: fs.writeFileSync('./image.png', buffer)
return canvas.toDataURL()
}