[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: WebDrawingArea to Image


Hello Bruce,

Here is the code I use to initiate the print mecanism of a browser Firefox or Chrome) with the content of a Canvas (WebDrawingArea -> html <canvas></canvas>)

I just need to prepare a Web page that I want to print and include a variable that will be replaced by the content of the canvas tag, provide to my Javascript function the ID of the WebDrawingArea (WebDrawingArea.Name) and inject the Javascript function into the Web Page of the Browser.

All works perfectly for me.

Also Benoit has added a new method to get in line the content of a WebDrawingArea as Image so now I have all pieces I need in both way.


1. Javascript function to start printing a simple WebPage by the Browser:

          ' Injection of Javascript Code to start print
          CodeJs &= "(() => {"
          CodeJs &= "  try {"
          CodeJs &= "    const iframe = document.createElement('iframe');"
          CodeJs &= "    iframe.style.cssText = 'position:absolute; top:-1000px; left:-1000px; width:800px; height:1200px; border:none;';"
          CodeJs &= "    document.body.appendChild(iframe);"
          CodeJs &= "    const doc = iframe.contentWindow.document;"
          CodeJs &= "    doc.open();"
          CodeJs &= "    doc.write(\"" & HtmlPage & "\");"
          CodeJs &= "    doc.close();"
          CodeJs &= "    iframe.onload = () => {"
          CodeJs &= "      setTimeout(() => {"
          CodeJs &= "        iframe.contentWindow.focus();"
          CodeJs &= "        iframe.contentWindow.print();"
          CodeJs &= "        setTimeout(() => { if(document.body.contains(iframe)) document.body.removeChild(iframe); }, 2000);"
          CodeJs &= "      }, 1000);"
          CodeJs &= "    };"
          CodeJs &= "    if (iframe.contentDocument && iframe.contentDocument.readyState === 'complete') {"
          CodeJs &= "       iframe.onload();"
          CodeJs &= "    }"
          CodeJs &= "  } catch(e) { console.error('ERR', e); }"
          CodeJs &= "})();"

          Try Me.Exec(CodeJs)


2. Javascript function to start printing a Web page and including a canvas image corresponding to the WebDrawingArea provided by ID

            ' 1. Encodage sécurisé de la page HTML côté Gambas
            Dim EncodedHtml As String = Url.Encode(HtmlPage)

            ' 2. Injection JS pour l'impression
            CodeJs &= "(() => {"
            CodeJs &= "  try {"
            CodeJs &= "    const canvasId = '" & sCanvasId & ":canvas" & "';"             CodeJs &= "    const canvas = document.getElementById(canvasId);"
            CodeJs &= ""
            ' Injection sécurisée via decodeURIComponent pour éviter les SyntaxError             CodeJs &= "    let processedHtml = decodeURIComponent('" & EncodedHtml & "');"
            CodeJs &= "    const placeholder = '{{CANVAS}}';"
            CodeJs &= ""
            ' 3. Sérialisation du canvas en <img> portable
            CodeJs &= "    if (canvas) {"
            CodeJs &= "      try {"
            CodeJs &= "        const dataUrl = canvas.toDataURL('image/png');"             CodeJs &= "        const w = Math.round(canvas.width || canvas.getBoundingClientRect().width);"             CodeJs &= "        const h = Math.round(canvas.height || canvas.getBoundingClientRect().height);"
            CodeJs &= "        const w90 = Math.round(w * 0.75);"
            CodeJs &= "        const h90 = Math.round(h * 0.75);"
            CodeJs &= "        processedHtml = processedHtml.replace(placeholder, `<div class='is-rouded-light is-border-light'><img src=\"${dataUrl}\" width=\"${w90}\" height=\"${h90}\" style=\"width: 90%; max-width: 100%; margin: 0.5% auto; display:block;\"></div>`);"             ' CodeJs &= "        processedHtml = processedHtml.replace(placeholder, `<div class='is-rouded-light is-border-light'><img src=\"${dataUrl}\" width=\"${w}\" height=\"${h}\" style=\"max-width:100%; display:block;\"></div>`);"             CodeJs &= "      } catch(e) { processedHtml = processedHtml.replace(placeholder, canvas.outerHTML); }"
            CodeJs &= "    } else { console.warn('Canvas introuvable.'); }"
            CodeJs &= ""
            ' 4. Création et injection dans l'iframe
            CodeJs &= "    const iframe = document.createElement('iframe');"             CodeJs &= "    iframe.style.cssText = 'position:absolute; top:-1000px; left:-1000px; width:800px; height:1200px; border:none;';"
            CodeJs &= " document.body.appendChild(iframe);"
            CodeJs &= "    const doc = iframe.contentWindow.document;"
            CodeJs &= ""
            CodeJs &= "    doc.open();"
            CodeJs &= "    doc.write(processedHtml);"
            CodeJs &= "    doc.close();"
            CodeJs &= ""
            ' 5. Workflow d'impression
            CodeJs &= "    iframe.onload = () => {"
            CodeJs &= "      setTimeout(() => {"
            CodeJs &= " iframe.contentWindow.focus();"
            CodeJs &= " iframe.contentWindow.print();"
            CodeJs &= "        setTimeout(() => { if(document.body.contains(iframe)) document.body.removeChild(iframe); }, 2000);"
            CodeJs &= "      }, 1000);"
            CodeJs &= "    };"
            CodeJs &= ""
            ' 6. Fallback synchrone
            CodeJs &= "    if (iframe.contentDocument && iframe.contentDocument.readyState === 'complete') {"
            CodeJs &= "       iframe.onload();"
            CodeJs &= "    }"
            CodeJs &= "  } catch(e) { console.error('ERR impression:', e); }"
            CodeJs &= "})();"

Olivier

Le 15/07/2026 à 03:49, Bruce Steers a écrit :
Ps.  it would probably be best to use your initial idea and "snapshot" the ready drawn canvas image using GetImageData.

All other options are probably going to be pretty complicated.

Respects
BruceS

On Tue, 14 Jul 2026, 21:04 Bruce Steers, <bsteers4@xxxxxxxxx> wrote:

    There is a javascript function in html canvas API , GetImageData
    https://www.w3schools.com/jsref/canvas_getimagedata.asp

    There is nothing like that built in to the WebDrawingArea though
    but you should be able to use javascript for the canvas api.

    Respects
    BruceS

    On Tue, 14 Jul 2026 at 18:44, Olivier Cruilles
    <olivier.cruilles@xxxxxxxx> wrote:

        In fact I would like to get all the
        <canvas><script>…</script></canvas> code produced sent to the
        Web Browser in the way to inject it into an <iframe></iframe>
        balise that will be used by the Web Browser to Print it.

        I’m already doing that for any html page I want to print by
        the Web Browser but I don’t find a way to catch the
        WebDrawingArea html+javascript code sent to the Browser by Gambas.

        Any idea


        Olivier

        Le 14 juill. 2026 à 11:21, Olivier Cruilles
        <olivier.cruilles@xxxxxxxx> a écrit :

        Hello,


        I would like to create an Image file from the drawing
        commands I use into a WebDrawingArea object, like we can do
        it for DrawingArea object.
        It is possible to do it like that ?

        Public Sub Create_Image()

          Dim hImg As New Image(Paint.Width, Paint.Height,
        Color.White, Image.Standard)

          Htmldata = WebDrawingAreaCourbe.ToHTML()

          Paint.Begin(hImg)
          Paint.Scale(1, 1)

            'Exemple of code to draw
            Paint.LineWidth = 1

            Paint.Rectangle(50, 50, 150, 150)
            Paint.Stroke(Color.Red, True)
        Paint.Fill(Color.SetAlpha(Color.SoftBlue, 192))

            Paint.Rectangle(80, 80, 150, 150)
        Paint.Stroke(Color.SetAlpha(Color.Yellow, 64))

            Paint.Arc(100, 100, 60)
            Paint.Fill(Color.Red)
            Paint.Rectangle(20, 20, 120, 70)
            Paint.Fill(Color.SetAlpha(Color.Royal, 64))

            Paint.Ellipse(20, 20, 120, 70, 0, -Pi / 2)
            Paint.Stroke(Color.Green)

            Paint.Rectangle(40, 80, 120, 70)
            Paint.Brush = Paint.LinearGradient(80, 140, 100, 120,
        [Color.Red, Color.Green, Color.Violet], [0, 0.5, 1])
            Paint.Fill()

            Paint.Rectangle(60, 90, 120, 70)
            Paint.Brush = Paint.LinearGradient(220, 200, 340, 200,
        [Color.Red, Color.Green, Color.Violet], [0, 0.5, 1])
            Paint.Fill()

            Paint.Arc(100, 320, 40)
            Paint.Brush = Paint.RadialGradient(100, 320, 2, 100, 320,
        40, ["red", "yellow", "lightblue"], [0, 0.6, 1])
            Paint.Fill()

          Paint.End()

          Try hImg.Save("/tmp/imagecourbe.png")
          If Error Then
            ModLogs.EcrireLogs("Error during image saving ! - Error:
        " & Error.Text)
          Endif

        End

        I know it's possible with Cairo library too, but through
        gb.gui.web component I not sure.

        Any idea ?

        Thank you

        -- Olivier



--
Olivier Cruilles


References:
WebDrawingArea to ImageOlivier Cruilles <olivier.cruilles@xxxxxxxx>
Re: WebDrawingArea to ImageOlivier Cruilles <olivier.cruilles@xxxxxxxx>
Re: WebDrawingArea to ImageBruce Steers <bsteers4@xxxxxxxxx>
Re: WebDrawingArea to ImageBruce Steers <bsteers4@xxxxxxxxx>