remark icon indicating copy to clipboard operation
remark copied to clipboard

Add drawable canvas

Open mmoelle1 opened this issue 7 years ago • 3 comments

Dear Ole,

I like remark very much and use it for lecturing since about half a year. Would it be possible to insert a drawable canvas in a slide so that one can write on the slides during the lectures and, ideally, save the written content online.

Best regards, Matthias

mmoelle1 avatar Nov 25 '17 13:11 mmoelle1

I was kinda looking for this feature, but I think in particular saving it should be pretty tricky :-/

amueller avatar Feb 07 '18 22:02 amueller

Perhaps some ready-made canvas library out there that does that (let you draw and save) can be embedded in Remark slides. If so, this shouldn't be a Remark feature, imho (but it would be nice to have a link or a how-to in the wiki for other users).

I would start looking around here: https://github.com/search?l=JavaScript&q=canvas+draw+save&type=Repositories&utf8=%E2%9C%93

tripu avatar Feb 14 '18 12:02 tripu

For anyone coming here looking for the same thing, here's how I did this:

First, add a canvas with a wrapper to your page's body like this:

<div id=cw><canvas id=c></canvas></div>

Next, add FabricJS to the page:

<script src="https://unpkg.com/[email protected]/dist/fabric.min.js"></script>

Next, change your init script that calls remark.create(), to do some extra stuff as below:

<script>
window.onload = () => {
	const show = remark.create({
		countIncrementalSlides: false,
	})

	const canvas = new fabric.Canvas("c", {
		isDrawingMode: true,
		width: window.innerWidth,
		height: window.innerHeight,
	});

	fabric.Object.prototype.transparentCorners = false;

	const cw = document.getElementById("cw")
	document.body.addEventListener("keydown", event => {
		if (event.key === "x") {
			canvas.clear()
		} else if (event.key === "v") {
			cw.style.zIndex = cw.style.zIndex > 0 ? -1 : 9
		}
	})

	const sketches = {}

	show.on("showSlide", slide => {
		canvas.clear()
		const sketch = sketches[slide.getSlideNumber()]
		sketch && canvas.loadFromJSON(sketch)
	})

	show.on("beforeHideSlide", slide => {
		sketches[slide.getSlideNumber()] = canvas.toJSON()
		canvas.clear()
	})

	if (canvas.freeDrawingBrush) {
		canvas.freeDrawingBrush.color = "#ff0099";
		canvas.freeDrawingBrush.width = 2;
	}
}
</script>

With this, on any slide, just hit v and you can draw anywhere on the slide. Switching to another slide will clear the canvas, but we can hit x to clear it without switching slide.

Preview:

https://user-images.githubusercontent.com/120119/135736863-2b8550e2-ec2b-4817-9955-ee27325e3089.mov

I can contribute a PR if there's interest in having this in core or as an official plugin or something. Thanks!

sharat87 avatar Oct 03 '21 02:10 sharat87