Skip to content

Instantly share code, notes, and snippets.

@daniil4udo
Created May 20, 2021 10:24
Show Gist options
  • Save daniil4udo/b77631e5f32599215825e2ff99b94ed4 to your computer and use it in GitHub Desktop.
Save daniil4udo/b77631e5f32599215825e2ff99b94ed4 to your computer and use it in GitHub Desktop.
Web Worker canvas
let options = {
padding: 15,
yRange: [0, 10, 20, 30, 40, 50],
fontSize: 12,
fillColor: '#00e5ff',
strokeColor: '#263238',
xRange: ["Cluster 1", "Cluster 2", "Cluster 3", "Cluster 4", "Cluster 5"]
}
const startButton = document.getElementById('start'),
stopButton = document.getElementById('stop')
const worker = ev => {
let { data } = ev
if (!data.op) {
ctx = data.canvas.getContext('2d')
let xRange = ["Cluster 1", "Cluster 2", "Cluster 3", "Cluster 4", "Cluster 5"],
yD = []
for (let i = 0; i < 6; i++) {
yD.push(Math.floor(Math.random() * 50))
}
return draw({ xRange, yD }, options, () => {
postMessage({ op: 0, message: 'Web worker running.' })
})
}
switch (data.op) {
case 1: return start(timer => {
postMessage({ op: 1 })
})
case 2: return draw(data.data, options, (() => {
postMessage({ op: 2 })
}))
case 9: return stop(() => {
postMessage({ op: 9 })
})
}
draw(ev.data.data, options, () => {
})
}
const blob = new Blob([('let ctx,\noptions =' + JSON.stringify(options) + '\n' + draw + '\n' + start + '\n' + stop + '\n' + 'let interval\n' + worker).replace('ev =>', 'onmessage = function(ev)')]),
blobURL = window.URL.createObjectURL(blob),
WebWorker = new Worker(blobURL),
canvas = document.getElementById('canvas'),
offscreen = canvas.transferControlToOffscreen(),
xRange = ["Cluster 1", "Cluster 2", "Cluster 3", "Cluster 4", "Cluster 5"]
let yD = []
for (let i = 0; i < 6; i++) {
yD.push(Math.floor(Math.random() * 50))
}
WebWorker.postMessage({ canvas: offscreen }, [offscreen])
WebWorker.onmessage = ({ data }) => {
switch (data.op) {
case 0: return (function () {
console.log(data.message)
yD = []
for (let i = 0; i < 6; i++) {
yD.push(Math.floor(Math.random() * 50))
}
postMessage({ op: 2, yD })
})()
case 1: return (function () {
startButton.disabled = true
stopButton.disabled = false
})()
case 9: return (function () {
startButton.disabled = false
stopButton.disabled = true
})()
}
}
function draw({ yD }, { fillColor, strokeColor, padding, fontSize, yRange, xRange }, callback) {
ctx.clearRect(0, 0, 700, 500)
ctx.beginPath()
ctx.fillStyle = strokeColor
ctx.moveTo(padding, 0)
ctx.lineTo(padding, 500 - padding)
ctx.stroke()
ctx.moveTo(padding, 500 - padding)
ctx.lineTo(700, 500 - padding)
ctx.stroke()
ctx.closePath()
let spacing = (500 - padding) / (yRange.length), nextPos = 0, valPerLength = 50 / 500,
spacingX = 700 / xRange.length
yRange.forEach(item => {
let textWidth = ctx.measureText(item).width
ctx.font = `${fontSize}px arial`;
ctx.fillText(item, 0, 500 - nextPos - fontSize)
nextPos += spacing + padding
})
let nextPosX = padding, barSpace = 10
xRange.forEach((item, i) => {
ctx.fillStyle = strokeColor
let textWidth = ctx.measureText(item).width,
barWidth = 5
ctx.font = `${fontSize}px arial`
ctx.fillText(item, i > 0 ? i == 1 ? padding + spacingX + spacingX / 2 - textWidth : nextPosX + spacing + spacingX / 2 - textWidth + 25 : padding + spacingX / 2 - textWidth, 500 - padding + fontSize)
let value = yD[i]
if (value > 0) {
ctx.beginPath()
ctx.rect(i > 0 ? nextPosX + spacing + barWidth + 11 : padding, 500 - value * 500 / 50 - padding - 1, i === 0 ? spacingX - padding - barWidth : spacingX - barWidth, value * 500 / 50)
ctx.fillStyle = fillColor
ctx.fill()
ctx.closePath()
}
nextPosX += i > 0 ? spacingX : spacingX / xRange.length
})
callback()
}
function start(callback) {
let started = false
interval = setInterval(() => {
let yD = []
for (let i = 0; i < 6; i++) {
yD.push(Math.floor(Math.random() * 50))
}
requestAnimationFrame(() => draw({ yD }, options, () => {
if (!started) {
started = true
callback()
}
}))
}, 50)
}
function stop(callback) {
clearInterval(interval)
started = false
callback()
}
window.start = () => {
WebWorker.postMessage({ op: 1 })
}
window.stop = () => {
WebWorker.postMessage({ op: 9 })
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment