Image resize

I couldn’t find a solution for resizing images and would like to get some advice on how to approach this problem.

When isolating the problem from ProseMirror, one could simply use resize: both; styling on a div and then put an image inside that div, as shown here: http://jsfiddle.net/hv4nP/ (using resize on img directly doesn’t work for some reason).

This leaves two problems:

  • how do we listen for resize events?
  • how can we keep the aspect ratio?

Using css resize is probably not good enough, and a more powerful approach would be to use JavaScript. Take the resize module for Quill as an inspiration: https://github.com/kensnyder/quill-image-resize-module

It works by putting an “overlay” div over the image when clicking it and then providing four handles for interaction.

This sounds like a really good solution. How would one go ahead and implement this for ProseMirror?

3 Likes

A node view could do something like that—render a resize handle, handle drag events on it, and dispatch transactions that resize the actual node. You might have to be careful to write the node view’s update method so that it doesn’t redraw the node that’s being resized, as that could cause event handler weirdness (or maybe not, depending on how you implement the event handling).

Here is a first draft: https://glitch.com/edit/#!/wide-heron

It works like this:

  • it provides a handle on every image on which a mousedown handler will deploy both a mousemove and a mouseup handler on document
  • mousemove handler will mutate the dom directly to show resize interaction
  • mouseup will read the new width from the element and mutate the respective node via transaction, then remove mousemove handler and itself

It works surprisingly well and i have three questions:

First of all, do you think this approach is in line with the prosemirror way of doing things?

There’s a small glitch: when resizing the image a couple of times in a row, at some point there will be some kind of “flicker”, as if the image resizes briefly to it’s original size, then back. Any ideas why this is happening?

And: after resizing the image, the image gets unselected. I don’t understand why.

1 Like

Looks great, and about the way I would implement it. I’m not sure where the flicker could be coming from.

Here’s an updated version https://glitch.com/edit/#!/fan-haddock

I changed the image spec to be a separate one from the original image spec. That way, it is possible to have both resizable and fixed-size images.

I’m struggling now with a menu item which allows to toggle between normal and resizable images. I tried to create a menu item with the blockTypeItem helper from prosemirror-menu, but that doesn’t work. May i ask for advice on how to implement such a toggle?

blockType works on textblocks, and I think you’re trying to change single nodes here. You’d write a command that returns false when the selection isn’t a node selection that has an image selected, and when it received a dispatch function, calls that with a transaction that replaces that node with an image of the other type. You can then wrap that in a menu item to put it in your menu.

Here’s the updated version with the command: https://glitch.com/edit/#!/toothsome-shoemaker

This version allows to

  • display standard images at 100% width
  • turn standard images into resizable images
  • resize the resizable images (measured in em)

There is room for improvement:

  • as mentioned before, there’s a weird flicker glitch when resizing. Seems to happen only in Safari though!
  • after resizing an image, the node is unselected automatically. I can’t figure out how to fix that. Maybe it’s because ProseMirror is redrawing that node. I’m not sure if it is default behavior and/or how to work around it.

I’m pretty happy with this solution. Any advice on how to solve above issues is highly appreciated. Thanks

4 Likes

I think that’s just because the selection is mapped for the change (which technically replaces the node with a new one). You can call setSelection on the transaction that does the replace to set it back to a node selection on the replaced node.

Indeed! Perfect! toothsome-shoemaker is hereby updated. Thanks for the sunday support :smiley:

Thank you for sharing

Ah, I may find why.

After testing, I find the flicker exists when the browser devtools open and disable the cache, every update will refetch img, then the flicker happens. Close devtools, everything works fine. :joy: