Skip to content

Commit 415266f

Browse files
authored
Merge pull request #21 from jaulz/fix/use-dynamic-size
fix: use dynamic size
2 parents 39a3fae + c576d4c commit 415266f

File tree

2 files changed

+63
-51
lines changed

2 files changed

+63
-51
lines changed

index.html

+9
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,13 @@ <h1 class="title">Value</h1>
178178

179179
document.getElementById('set').addEventListener('click', () => {
180180
const value = document.getElementById('value').value
181+
localStorage.setItem('value', value)
181182
badgin.set(value ? parseInt(value, 10) : value, options)
182183
})
183184

184185
document.getElementById('clear').addEventListener('click', () => {
185186
document.getElementById('value').value = ''
187+
localStorage.setItem('value', '')
186188
badgin.clear()
187189
})
188190

@@ -232,6 +234,13 @@ <h1 class="title">Value</h1>
232234
script.src = isLocalhost
233235
? '/build/index.iife.js'
234236
: 'https://unpkg.com/badgin/build/index.iife.js'
237+
script.onload = () => {
238+
const value = localStorage.getItem('value')
239+
if (value) {
240+
document.getElementById('value').value = localStorage.getItem('value')
241+
document.getElementById('set').click()
242+
}
243+
}
235244

236245
document.head.appendChild(script)
237246
</script>

src/favicon.ts

+54-51
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ type Favicon = HTMLLinkElement
1212

1313
type BestFavicon = Favicon | null
1414

15+
export const DefaultValue: Value = 0
16+
17+
export const DefaultOptions: Options = {
18+
backgroundColor: '#424242',
19+
color: '#ffffff',
20+
indicator: '!',
21+
}
22+
1523
// Get all favicons of the page
1624
const getFavicons = (): Favicon[] => {
1725
const links = document.head.getElementsByTagName('link')
@@ -86,34 +94,34 @@ const getBestFavicon = (): BestFavicon => {
8694
return bestFavicon
8795
}
8896

89-
// Calculate the size of the font and canvas element based on device's ratio
90-
const ratio = Math.ceil(window.devicePixelRatio) || 1
91-
const size = 16 * ratio
92-
93-
// Options
94-
export const defaultOptions: Options = {
95-
backgroundColor: '#424242',
96-
color: '#ffffff',
97-
indicator: '!',
98-
}
99-
10097
// References to the favicons that we need to track in order to reset and update the counters
10198
const current: {
102-
canvas: HTMLCanvasElement | null
103-
context: CanvasRenderingContext2D | null
10499
favicons: Favicon[] | null
105100
bestFavicon: BestFavicon
106101
bestFaviconImage: HTMLImageElement | null
107102
value: Value
108103
options: Options
109104
} = {
110-
canvas: null,
111-
context: null,
112105
favicons: null,
113106
bestFavicon: null,
114107
bestFaviconImage: null,
115-
value: 0,
116-
options: defaultOptions,
108+
value: DefaultValue,
109+
options: DefaultOptions,
110+
}
111+
112+
// Get size depending on screen density
113+
const devicePixelRatioListener = window.matchMedia(
114+
'screen and (min-resolution: 2dppx)'
115+
)
116+
const getRatio = () => {
117+
return Math.ceil(window.devicePixelRatio) || 1
118+
}
119+
const handleRatioChange = () => {
120+
console.log('handleRatioChange')
121+
set(current.value, current.options)
122+
}
123+
const getSize = () => {
124+
return 16 * getRatio()
117125
}
118126

119127
// Update favicon
@@ -145,31 +153,25 @@ const drawFavicon = (
145153
value: Value,
146154
options: Options
147155
) => {
148-
if (!current.canvas || !current.context) {
156+
const size = getSize()
157+
const canvas = document.createElement('canvas')
158+
canvas.width = size
159+
canvas.height = size
160+
const context = canvas.getContext('2d')
161+
if (!context) {
149162
return
150163
}
151164

152-
// Clear old canvas
153-
current.context.clearRect(0, 0, size, size)
154-
155165
// Draw new image
156-
current.context.drawImage(
157-
image,
158-
0,
159-
0,
160-
image.width,
161-
image.height,
162-
0,
163-
0,
164-
size,
165-
size
166-
)
166+
image.width = size
167+
image.height = size
168+
context.drawImage(image, 0, 0, image.width, image.height)
167169

168170
// Draw bubble on the top
169-
drawBubble(current.context, value, options)
171+
drawBubble(context, value, options)
170172

171173
// Refresh tag in page
172-
setFavicon(current.canvas.toDataURL())
174+
setFavicon(canvas.toDataURL())
173175
}
174176

175177
// Draws the bubble on the canvas
@@ -198,14 +200,16 @@ const drawBubble = (
198200
}
199201

200202
// Calculate position etc.
203+
const size = getSize()
204+
const ratio = getRatio()
201205
const length = finalValue.length - 1
202-
const width = 8 * ratio + 4 * ratio * length
206+
const width = Math.min(8 * ratio + 4 * ratio * length, size)
203207
const height = 7 * ratio
204208
const top = size - height
205-
const left = size - width - ratio
209+
const left = size - width
206210
const bottom = 16 * ratio
207211
const right = 16 * ratio
208-
const radius = 5 * ratio
212+
const radius = 3 * ratio
209213

210214
// Bubble
211215
context.save()
@@ -232,21 +236,12 @@ const drawBubble = (
232236
context.fillStyle = options.color
233237
context.textAlign = 'center'
234238
context.textBaseline = 'top'
235-
context.fillText(finalValue, left + width / 2 + 1, 9 * ratio + 1)
239+
context.fillText(finalValue, left + width / 2, 9 * ratio + 1)
236240
context.restore()
237241
}
238242

239243
export function isAvailable() {
240-
if (!current.context) {
241-
const canvas = document.createElement('canvas')
242-
canvas.width = size
243-
canvas.height = size
244-
245-
current.canvas = canvas
246-
current.context = canvas.getContext ? canvas.getContext('2d') : null
247-
}
248-
249-
return !!current.context && !!getBestFavicon()
244+
return !!getBestFavicon()
250245
}
251246

252247
export function set(value: Value, options?: Partial<Options>) {
@@ -264,8 +259,6 @@ export function set(value: Value, options?: Partial<Options>) {
264259

265260
if (bestFavicon) {
266261
const bestFaviconImage = document.createElement('img')
267-
bestFaviconImage.width = size
268-
bestFaviconImage.height = size
269262

270263
// Allow cross origin resource requests if the image is not a data:uri
271264
if (!bestFavicon.href.match(/^data/)) {
@@ -279,12 +272,15 @@ export function set(value: Value, options?: Partial<Options>) {
279272
current.bestFavicon = bestFavicon
280273
current.bestFaviconImage = bestFaviconImage
281274
}
275+
276+
// Once the device pixel ratio changes we set the value again
277+
devicePixelRatioListener.addListener(handleRatioChange)
282278
}
283279
if (!current.favicons) {
284280
current.favicons = getFavicons()
285281
}
286282

287-
// Draw icon
283+
// The image is required for setting the badge
288284
if (!current.bestFaviconImage) {
289285
return false
290286
}
@@ -308,6 +304,13 @@ export function clear() {
308304
return
309305
}
310306

307+
// Reset value and options
308+
current.value = DefaultValue
309+
current.options = DefaultOptions
310+
311+
// Remove old listener
312+
devicePixelRatioListener.removeListener(handleRatioChange)
313+
311314
if (current.favicons) {
312315
// Remove current favicons
313316
for (const favicon of getFavicons()) {

0 commit comments

Comments
 (0)