Created
May 20, 2021 10:24
-
-
Save daniil4udo/b77631e5f32599215825e2ff99b94ed4 to your computer and use it in GitHub Desktop.
Web Worker canvas
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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