jonobr1 / two.js

A renderer agnostic two-dimensional drawing api for the web.
https://two.js.org
MIT License
8.27k stars 454 forks source link

svg fill-opacity [Bug] #710

Closed detrothe closed 10 months ago

detrothe commented 10 months ago

Hi, I create a technical drawing on screen that also needs to be printed. I use svg. The result is as expected on screen but if I take the svg content and save it on disk (as demonstrated in the examples), and open in in inkscape, libreoffice or microsoft office 2019 (no difference between ubuntu and windows), then the area inside the path is black. This happens with my own moment arrow (left) as well as with your makeArrow (right side). my code in Javascript for the arc segmentt:

   var vertices = [];
    dalpha = Math.PI / (teilung + 1)
    alpha = 0.0
    for (let i = 0; i < teilung - 2; i++) {
        x = tr.Pix0(-radius * Math.sin(alpha))
        z = tr.Pix0(radius * Math.cos(alpha))
        vertices.push(new Two.Anchor(x, z));
        alpha += dalpha
    }
    let curve = new Two.Path(vertices, false, true)
    curve.linewidth = linewidth;
    curve.stroke = color;
    curve.noFill()

    group.add(curve)
    // arrowhead  follows

I can fix the problem by hand,if I exchange in the svg-file in both cases: fill-opacity="1" to fill-opacity="0". fill="transparent" in the svg-file seems to have no impact and I have not found a hint that this is part of the specs. But I'm not an expert on svg.

Result on screen: screen

in inkscape without any changes: generated-by-two-js

corrected with fill-opacity="0" modified

Additional question: Is there a method in Two.Path to use fill-opacity?

Thank you, I like your library

jonobr1 commented 10 months ago

Have you tried curve.fill = "none";?

detrothe commented 10 months ago

Hi,

if I use curve.fill="none", there is still transparent in the svg-file. On screen it works like nofill().

But if I edit the svg-file to fill="none", then in all cases ( inkscape, libre office and microsoft office 2019 ) the filling is gone.  Hope you can fix it easily.

I would also need a npm version for netlify. Sorry.

Detlef

Am 09.10.23 um 21:55 schrieb Jono:

Have you tried |curve.fill = "none";|?

— Reply to this email directly, view it on GitHub https://github.com/jonobr1/two.js/issues/710#issuecomment-1753649452, or unsubscribe https://github.com/notifications/unsubscribe-auth/AXNO53LN7GZF4IUR6BVXX7TX6RJEZAVCNFSM6AAAAAA5YUP5MOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONJTGY2DSNBVGI. You are receiving this because you authored the thread.Message ID: @.***>

jonobr1 commented 10 months ago

Unfortunately different browsers have different implementations of "none", so it's not a great option for Two.js.

Have you tried curve.fill = "rgba(0, 0, 0, 0);"?

detrothe commented 10 months ago

Hi,

rgba doesn't work in inkscape, ... Only curve.fill="none" does the job.

I have tested it on following browsers: chrome (chromium), Firefox, iOS Safari 16.6 on old Apple tablett, Firefox and google chrome on Android

I looked at the following page: https://www.w3.org/TR/SVG2/painting.html

They only use fill="none" in all examples, no transparent or rgba is mentioned.

Am 10.10.23 um 00:40 schrieb Jono:

Unfortunately different browsers have different implementations of |"none"|, so it's not a great option for Two.js.

Have you tried |curve.fill = "rgba(0, 0, 0, 0);"|?

— Reply to this email directly, view it on GitHub https://github.com/jonobr1/two.js/issues/710#issuecomment-1754005357, or unsubscribe https://github.com/notifications/unsubscribe-auth/AXNO53IY232RNZQCT4JOSHLX6R4N5AVCNFSM6AAAAAA5YUP5MOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONJUGAYDKMZVG4. You are receiving this because you authored the thread.Message ID: @.***>

jonobr1 commented 10 months ago

Got it. That makes sense. If this is a static image (not animating) and you are using the SVG Renderer then you can always access the underlying SVG element in code like this. But, be sure to call two.update(); or have the renderer render at least once beforehand so that the elements are created:

// Given your curve code
two.add(curve);
two.update();

const elem = curve.renderer.domElement;
elem.setAttribute('fill-opacity', 0);
detrothe commented 10 months ago

It is a static image. The image is created after a finite element calculation, and two.update() is always called. Your suggestion with curve.fill="none" serves me fine. I don't have to care about old browsers, because my students have current hardware, usually newer than mine. But two.makeArrow still has black background, see my first comment, (picture in the middle). Other users of your lib might have that problem too and .nofill() will not work as expected . Or am I wrong?

jonobr1 commented 10 months ago

Got it. I'll have to re-run tests to see if all the browsers support curve.fill = "none". At the time of writing, which was a long time ago, both Firefox and Safari did not support "none". This is why noFill yields transparent. They may now and if so then I'll replace it.

Easy fix.

detrothe commented 10 months ago

I found following Link: https://stackoverflow.com/questions/6042550/svg-fill-color-transparency-alpha Is there a way to specify fill-opacity directly in code via a member function for two.Path? Part of the link: image

jonobr1 commented 10 months ago

No, because fill-opacity is not available in all renderers. That is why it's recommended to use:

curve.renderer.domElement.setAttribute('fill-opacity', 0);
detrothe commented 10 months ago

ok

jonobr1 commented 10 months ago

v8.12 will have noFill and noStroke execute CSS commands "none" instead of "transparent"

detrothe commented 10 months ago

Thank you very much for the changes.--Diese Nachricht wurde von meinem Android Mobiltelefon mit WEB.DE Mail gesendet.Am 16.10.23, 20:00 schrieb Jono @.***>:

Closed #710 as completed. —Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you authored the thread.Message ID: @.***>