JSFiddle - React, Tailwind, and code Playground
HTML
<canvas id=c></canvas>
CSS
#c {
transform: scale(1, -1);
outline: 1px solid;
}
JavaScript
class Graph {
canvas
startX
endX
startY
endY
samples
funcs = []
colors = ["red", "blue", "green", "orange"]
constructor(canvas, startX, endX, startY, endY) {
this.canvas = canvas
this.startX = startX
this.endX = endX
this.startY = startY
this.endY = endY
this.initSamples()
}
initSamples() {
const n = this.canvas.width
const dx = (this.endX - this.startX) / n
this.samples = [
...range(0, n).map(
i => [i + 0.5, this.startX + i * dx]
)]
}
add(func) {
this.funcs.push(func)
}
repaint() {
const ctx = this.canvas.getContext("2d")
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
for (let i = 0; i < this.funcs.length; i++) {
this.draw(ctx, this.funcs[i], this.colors[i % this.colors.length])
}
}
draw(ctx, fn, color) {
ctx.beginPath()
let m = "moveTo"
let scaleY = this.canvas.height / (this.endY - this.startY)
for (const [px, x] of this.samples) {
const y = fn(x)
const py = (y - this.startY) * scaleY
ctx[m](px, py)
m = "lineTo"
}
ctx.strokeStyle = color
ctx.stroke()
ctx.closePath()
}
}
function randomColor() {
return "#" + Math.floor(Math.random() * 0x1000000).toString(16)
}
function *range(start, end) {
for (let i = start; i < end; i++) yield i
}
range.prototype.map = function *(f) {
for (let v of this) {
yield f(v)
}
}
const g = new Graph(document.querySelector('#c'), -2 * Math.PI, 2 * Math.PI, -1, 1)
g.add(Math.sin)
g.add(Math.cos)
g.repaint()