viliusle / miniPaint

online image editor
http://viliusle.github.io/miniPaint/
Other
2.59k stars 602 forks source link

How to use it in react? #405

Open execriss opened 1 month ago

execriss commented 1 month ago

Hello, I love miniPaint. It's just what I was needing for my project, but I'm having a hard time integrating it into React.

Do you have any guide or example using it in React js? I can now render the Iframe within a modal, but I am having a hard time understanding how I can send two images to the iframe, so that it can paint them one on top of the other, and I would also like to know how I can save the final image. If anyone has an example using it in React js, it would do me a great favor.

import React, { useEffect, useCallback, useRef } from "react";
import { ENV } from "../utils/constants";

export default function ModalEditTemplate({
  showModal,
  setShowModal,

}) {
  return (
    <div>
      {showModal && (
        <div
          id="default-modal"
          tabIndex="1"
          aria-hidden="true"
          className="fixed inset-0 overflow-y-auto overflow-x-hidden z-50 flex items-center justify-center bg-black bg-opacity-50"
        >
          <div className="relative">
            <div className="relative bg-gray-700 rounded-lg shadow dark:bg-gray-700">
              <div className="flex items-center justify-between md:p-2 border-b rounded-t dark:border-gray-600">
                <h3 className="text-xl font-semibold text-gray-900 dark:text-white">
                  Editar Plantilla
                </h3>
                <button
                  type="button"
                  className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"
                  data-modal-hide="default-modal"
                  onClick={() => setShowModal(false)}
                >
                  <svg
                    className="w-3 h-3"
                    aria-hidden="true"
                    xmlns="http://www.w3.org/2000/svg"
                    fill="none"
                    viewBox="0 0 14 14"
                  >
                    <path
                      stroke="currentColor"
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth="2"
                      d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"
                    />
                  </svg>
                  <span className="sr-only">Cerrar modal</span>
                </button>
              </div>
              <div className="p-1 px-5">
                <iframe
                  style={{ width: "70vw", height: "70vh" }}
                  id="miniPaint"
                  src={`https://viliusle.github.io/miniPaint/?image=${ENV.SERVER_HOST}/uploads/amex_67402d8f7e.png`}
                  allow="camera"
                ></iframe>
                <button
                  className="mt-4 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
                  onClick={() => {}}
                >
                  Guardar Plantilla
                </button>
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
Giwayume commented 4 weeks ago

This is an example of loading and saving images https://github.com/viliusle/miniPaint/blob/master/examples/open-edit-save.html

For React specifically, you can add a ref to the iframe element to retrieve it if you don't want to use the id.

import { useRef, useEffect } from 'react';

export default function ModalEditTemplate() {
    const minipaintIframe = useRef(null);
    const isMinipaintIframeLoaded = useRef(false);

    useEffect(() => {
        if (minipaintIframe.current && isMinipaintIframeLoaded.current) {
            // When the iframe ref is populated from the component template,
            // call API to load image...
            const Layers = minipaintIframe.current.contentWindow.Layers;
            const newLayer = {
                // Reference example I linked above
            };
            Layers.insert(newLayer);
        }
    }, []);

    function onMinipaintIframeLoad() {
        isMinipaintIframeLoaded.current = true;
    }

    return (
        <iframe
              ref={minipaintIframe}
              style={{ width: "70vw", height: "70vh" }}
              src={`https://YOURWEBSITE.COM/miniPaint/`}
              allow="camera"
              onLoad={onMinipaintIframeLoad}
        ></iframe>
    );
}

I haven't tested this code, but theoretically it should work. You need to wait for both the ref for the iframe element to be assigned, and for the iframe to load the minipaint page.

Giwayume commented 4 weeks ago

Also, I didn't notice this at first, but you'll need to self-host minipaint on your own server, not reference it from https://viliusle.github.io/.

Javascript won't talk across iframes on different domains.

exequiel-criss commented 3 weeks ago

Also, I didn't notice this at first, but you'll need to self-host minipaint on your own server, not reference it from https://viliusle.github.io/.

Javascript won't talk across iframes on different domains.

Thank you very much for your previous response, it has been very helpful to me. One more question, I have my project separated into client with react and server with strapi (node.js). I have the client hosted on netlify, and the server on railway. Where should I host mini paint? On railway or on netlify?

Giwayume commented 3 weeks ago

Minipaint is all client code. A bunch of js, css, and html file. It doesn't really matter, the only real requirement is that it is served from the same domain that your react code is running on, so the Javascript can communicate across the boundaries of the iframe.

Giwayume commented 1 week ago

@viliusle may want to consider adding a postMessage API so people can do basic things like load and save images from viliusle.github.io/miniPaint/ without having to self-host.

geeeeeeeek commented 1 week ago

great

在 2024年6月19日星期三,Giwayume @.***> 写道:

@viliusle https://github.com/viliusle may want to consider adding a postMessage API so people can do basic things like load and save images from viliusle.github.io/miniPaint/ without having to self-host.

— Reply to this email directly, view it on GitHub https://github.com/viliusle/miniPaint/issues/405#issuecomment-2176774364, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABLPAHBXSICTD2K6EI3JOX3ZICAJNAVCNFSM6AAAAABITTCVA2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNZWG43TIMZWGQ . You are receiving this because you are subscribed to this thread.Message ID: @.***>