Frage Transparenter Farbverlauf auf Bild (per CSS), auch zum Drucken

  • Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Dieter!

Neues Mitglied
8 Juni 2021
11
0
1
Oldenburg
Hallo, ich versuche krampfhaft ein Bild von seitlich links stark transparent bis nach rechts weniger transparent aufzuhellen. Davor soll dann der Text platziert werden.

Mit z.B. background: linear-gradient(100deg, white 70%, white 70%, transparent 120%) auf vorgelegtem div funktioniert das auch ganz gut. Beim Ausdruck verschwindet allerdings die transparente Aufhellung. Andere Ansätze mit opacity oder filter funktionieren zwar für den Ausdruck, aber damit kann ich keinen fließenden Übergang erzeugen.

Gibt es noch weitere Möglichkeiten?
 

Anhänge

  • farbverlauf.jpg
    farbverlauf.jpg
    74,3 KB · Aufrufe: 9

basti1012

Senior HTML'ler
26 November 2017
1.600
173
63
Minden
basti1012.de
Habe mal etwas gegoogelt.
Versuche mal einen anderen Browser,
oder
Ich habe auch das gleiche Problem gehabt, aber festgestellt, dass es kein CSS-Problem war. Es könnte ein Problem mit der Druckoption sein. Aktivieren Sie "Hintergrundgrafiken" im Druckbildschirm.
 

Dieter!

Neues Mitglied
8 Juni 2021
11
0
1
Oldenburg
Ja, wenn man Hintergrund drucken im Browser auswählt, wird es auch gedruckt. Das funktioniert auch in allen Browsern gleich. Ich hätte aber gerne, dass das aufgehellte Bild mit Farbverlauf ohne Hintergrundoption gedruckt wird.
 

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.406
462
83
68
Der Grund ist, dass Tinte/Toner gespart werden soll. Auch wenn es bei deinem Bild nicht so ins Gewicht fallen würde.
Gibt es noch weitere Möglichkeiten?
Eine Möglichkeit wäre, das Ganze mit Canvas als Bild zu generieren und dieses einzubinden. Aber fraglich, ob der Aufwand in einem vernünftigen Verhältnis zum Nutzen stehen würde.
 

Dieter!

Neues Mitglied
8 Juni 2021
11
0
1
Oldenburg
Canvas ist ja eine spannende Geschichte, kannte ich noch gar nicht. Allerdings möchte kein Bild zeichnen oder animieren, sondern nur z.B. ein Sonnenuntergang oder ein Tannenbaum schwach im Hintergrund anzeigen lassen. Gelegentlich soll dann einfach das Foto gegen ein anderes getauscht werden und fertig, also ohne an den Bild was ändern zu müssen (langfristig pflegeleicht). Kann man so ein transparenten Verlauf vielleicht mit JavaScript/jQuery erzeigen?
 

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.406
462
83
68
Du brauchst ja das Bild weder zeichnen noch animieren, sondern in deinem Fall musst Du nur die Helligkeit von rechts nach links anheben, bis zu weiß links.
Hier ist eine gute Einführung:
Dort wird auf eine kleine Bibliothek für das Ändern der Farben hin gewiesen:
Was Du brauchst ist die Funktion lighten().
Und wenn Du dem Bild eine geeignete ID gibst, brauchst Du das Skript nicht anzufassen, wenn Du das Bild bzw. das src-Attribut austauschst.
 

Dieter!

Neues Mitglied
8 Juni 2021
11
0
1
Oldenburg
Erstmal vielen Dank Sempervivum, das hört sich sehr gut an. Leider habe ich keine Ahnung wie ich die Funktion lighten() auf das Bild anwende. Bitte um weitere Hilfe.

HTML:
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <script type="text/javascript" src="js/TinyColor-master/tinycolor.js"></script>
    </head>


    <body>
        <img id="palmen" src="images/palmen.jpg">
              
              

        <script type="text/javascript">
//            lighten: function(amount = 10) -> TinyColor. Lighten the color a given amount, from 0 to 100. Providing 100 will always return white.
//            tinycolor("#f00").lighten().toString(); // "#ff3333"
//            tinycolor("#f00").lighten(100).toString(); // "#ffffff"
        </script>
    </body>
</html>
 

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.406
462
83
68
Ich war heute unterwegs, daher kann ich erst jetzt antworten.
Die schlechte Nachricht: Das lighten() von tinycolor.js hat sich leider als unbrauchbar erwiesen, denn die Zeichnung in den hellen Bereichen geht beim Aufhellen vollkommen verloren.
Die gute: Es war ziemlich leicht, das Aufhellen selber zu programmieren.
So funktioniert es vom Prinzip her:
Code:
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Background Image Canvas</title>
</head>


<body>
    <img src="images/dia0.jpg"><br>
    <canvas id="bgimg"></canvas>
    <script>
        const imgPath = 'images/dia0.jpg',
            // Canvas und 2D-Context bereit stellen:
            cv = document.getElementById('bgimg'),
            ctx = cv.getContext("2d"),
            img = new Image();
        // Eventhandler fuer das Laden des Bildes registrieren:
        img.onload = () => {
            // Breite und Hoehe des Bildes bereit stellen:
            const wImg = img.width, hImg = img.height;
            // Abmessungen des Canvas an das Bild anpassen:
            cv.width = wImg;
            cv.height = hImg;
            // Bild auf Canvas zeichnen:
            ctx.drawImage(img, 0, 0, wImg, hImg);
            // Bilddaten bereit stellen:
            const imgData = ctx.getImageData(0, 0, wImg, hImg);
            const data = imgData.data;
            // Schleife ueber die Bilddaten
            // Parallel fuehren wir die x- und y-Position:
            for (let i = 0, x = 0, y = 0; i < data.length; i += 4, x++) {
                if (x == wImg) {
                    x = 0;
                    y++;
                }
                // Faktor (0 ... 1) der Aufhellung ermitteln:
                const factor = 1 - x / wImg;
                // Farbe des aktuellen Pixels bereit stellen:
                const color = [data[i], data[i + 1], data[i + 2]];
                // Farbe um Faktor aufhellen:
                let newColor = color.map((val) => {
                    // Differenz zu weiss bereit stellen:
                    const delta = 256 - val,
                        // Differenz zu weiss um Faktor verringern:
                        newVal = val + delta * factor;
                    return newVal;
                });
                // Neue Farbe in Bilddaten eintragen:
                data[i] = newColor[0];
                data[i + 1] = newColor[1];
                data[i + 2] = newColor[2];
            }
            // Geaenderte Bilddaten auf Canvas zeichnen:
            ctx.putImageData(imgData, 0, 0);
        }
        img.src = imgPath;
    </script>
</body>

</html>
Was jetzt noch zu tun ist: Einblenden des Bildes soll ja weiter rechts erst beginnen und schräg. Das ist dann nur noch etwas Rechnerei um den Faktor abhängig von x und y zu bestimmen.
 

Dieter!

Neues Mitglied
8 Juni 2021
11
0
1
Oldenburg
Vielen Dank, leicht sieht das für mich alles nicht aus; genauer gesagt verstehe ich kein Wort.
Leider läuft das Skript bei mir auch nicht. Ich bekomme zwei gleiche Bilder untereinander. Ich habe nur die beiden dia0.jpg durch meine palmen.jpg ausgetauscht. wImg und hImg liefern noch Werte per console.log, aber bei ctx.getImageData hörts auf. Folgende Fehlermeldungen geben die Browser

Chrome: Uncaught DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data. .. at Image.img.onload

Firefox: Uncaught DOMException: The operation is insecure.
 

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.406
462
83
68
Daran hatte ich jetzt nicht gedacht. Ich hatte dieses Problem nicht, weil ich einen lokalen Webserver benutze. Das Problem tritt nur auf, wenn man die Datei durch das File-Protokoll anzeigt mit file:/// am Anfang der URL, z. B. durch Doppelklick auf die Datei. Da Du wahrscheinlich keinen lokalen Webserver hast, musst Du sie auf deinen Webspace hoch laden, damit es funktioniert.

Ich war in der Zwischenzeit nicht untätig und habe den Verlauf geändert, so dass es mehr aussieht wie in deinem Bild im Eingangsposting:
Code:
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Background Image Canvas</title>
</head>


<body>
    <img src="images/pano-stabkirche-small.jpg"><br>
    <canvas id="bgimg"></canvas>
    <script>
        const imgPath = 'images/pano-stabkirche-small.jpg',
            // Start der Einblendung des Bildes oben und unten, relativ zur Bildbreite:
            startTop = 0.9, startBtm = 0.7,
            delta = Math.max(1 - startTop, 1 - startBtm),
            // Canvas und 2D-Context bereit stellen:
            cv = document.getElementById('bgimg'),
            ctx = cv.getContext("2d"),
            img = new Image();
        // Eventhandler fuer das Laden des Bildes registrieren:
        img.onload = () => {
            // Breite und Hoehe des Bildes bereit stellen:
            const wImg = img.width, hImg = img.height;
            // Abmessungen des Canvas an das Bild anpassen:
            cv.width = wImg;
            cv.height = hImg;
            // Bild auf Canvas zeichnen:
            ctx.drawImage(img, 0, 0, wImg, hImg);
            // Bilddaten bereit stellen:
            const imgData = ctx.getImageData(0, 0, wImg, hImg);
            const data = imgData.data;
            // Schleife ueber die Bilddaten
            // Parallel fuehren wir die x- und y-Position:
            for (let i = 0, x = 0, y = 0; i < data.length; i += 4, x++) {
                if (x == wImg) {
                    x = 0;
                    y++;
                }
                // Faktor (0 ... 1) der Aufhellung ermitteln
                // start = relative Position fuer den Beginn des Einblendens
                const start = startTop + (startBtm - startTop) * y / hImg,
                    // startX = absolute Position fuer den Beginn des Einblendens:
                    startX = start * wImg,
                    // deltaY = Bereich, in dem eingeblendet wird:
                    deltaX = delta * wImg;
                let factor = 0;
                // Ist x kleiner als der Start des Einblendens ist der Faktor 1:
                if (x < startX) {
                    factor = 1;
                    // } else if (x > startX + deltaX) {
                    //     factor = 0;
                } else {
                    // Andernfalls berechnen wir den Faktor für das Aufhellen
                    // und wenden die Quadratwurzel an, um einen natuerlicheren
                    // Verlauf zu erzielen:
                    factor = Math.sqrt(1 - (x - startX) / deltaX);
                }
                // Farbe des aktuellen Pixels bereit stellen:
                const color = [data[i], data[i + 1], data[i + 2]];
                // Farbe um Faktor aufhellen:
                let newColor = color.map((val) => {
                    // Differenz zu weiss bereit stellen:
                    const delta = 256 - val,
                        // Differenz zu weiss um Faktor verringern:
                        newVal = val + delta * factor;
                    return newVal;
                });
                // Neue Farbe in Bilddaten eintragen:
                data[i] = newColor[0];
                data[i + 1] = newColor[1];
                data[i + 2] = newColor[2];
            }
            // Geaenderte Bilddaten auf Canvas zeichnen:
            ctx.putImageData(imgData, 0, 0);
        }
        img.src = imgPath;
    </script>
</body>

</html>
 
Zuletzt bearbeitet:

Dieter!

Neues Mitglied
8 Juni 2021
11
0
1
Oldenburg
Perfekt, besser als ich mir das jemals vorgestellt hätte. Tausend Dank dafür. Ich habe für die Webseite zwei Schieber eingebaut womit man startTop und startBtm einstellen kann. Dadurch hat man dann die größte Flexibilität, auch für den späteren Ausdruck.

Eigentlich lasse ich alles über XAMMP (also localhost) laufen, da ich mehr mit PHP programmiere. In diesen Fall habe ich aber tatsächlich den Code einfach in die Datei kopiert und gedoppelklickt. Nun denn jetzt läuft‘s und ich bin sehr mit dem Ergebnis zufrieden.

Ich habe versuchsweise den delta-Wert verändert in der Hoffnung man könnte die Grundhelligkeit einstellen, leider ohne Erfolg. Wenn das mit sehr wenig Aufwand geht, würde ich noch einen weiteren Schieber für Helligkeit einbauen. Ansonsten lasse ich das so, das ist ja sehr gut so.
 

Anhänge

  • 1623365872209.png
    1623365872209.png
    548,2 KB · Aufrufe: 4

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.406
462
83
68
man könnte die Grundhelligkeit einstellen, leider ohne Erfolg. Wenn das mit sehr wenig Aufwand geht, würde ich noch einen weiteren Schieber für Helligkeit einbauen.
Das geht garantiert, ich weiß nur nicht genau, was Du meinst: Soll das Bild links, wo jetzt der Hintergrund weiß ist, auch ein wenig durchscheinen? Oder möchtest Du, dass es nach rechts hin auch aufgehellt bleibt?
 

Dieter!

Neues Mitglied
8 Juni 2021
11
0
1
Oldenburg
Ich meinte das man Bild ingesamt etwas dunkler regeln kann. Also das was man im CSS mit filter:brightness() oder opacity() einstellen kann, nur eben in Richtung dunkler.
 

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.406
462
83
68
Meinst Du rechts in dem Bereich wo es eingeblendet wird? Geht das nicht, wenn Du die Grenzen weiter nach links verschiebst? Dann würde das Bild dort seine originale Helligkeit annehmen.
 

Dieter!

Neues Mitglied
8 Juni 2021
11
0
1
Oldenburg
Also für startTop und startBtm kann ich einstellen was ich will, rechts wird das Bild nie dunkel. Ich würde schätzen bei opacity(0.5) vom Original bleibt es stehen.
 

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.406
462
83
68
Ich habe mal ein Abdunkeln hinzu gefügt. Das funktioniert aber leider reduziert sich dabei auch der Kontrast.
Zunächst einen Faktor für das Abdunkeln definieren:
Code:
        const imgPath = 'images/pano-stabkirche-small.jpg',
            // Start der Aufhellung oben und unten, relativ zur Bildbreite:
            startTop = 0.9, startBtm = 0.7,
            // Faktor fuer das Abdunkeln des Bildes
            // 1 bewirkt kein Abdunkeln
            // 0 bewirkt max. Abdunkeln nach schwarz:
            factorDarken = 0.5,
            delta = 0.3, //delta = Math.max(1 - startTop, 1 - startBtm),
            // Canvas und 2D-Context bereit stellen:
            cv = document.getElementById('bgimg'),
            ctx = cv.getContext("2d"),
            img = new Image();
        // Eventhandler fuer das Laden des Bildes registrieren:
        img.onload = () => {

// usw.

Dann gibt es zwei Möglichkeiten:
1. Das Abdunkeln vor dem Aufhellen vornehmen, dann bleibt der Bereich links weiß:
Code:
// davor wie bisher
                // Farbe um Faktor aufhellen:
                let newColor = color.map((val) => {
                    // 1. Pixel um factorDarken abdunkeln:
                    let newVal = val * factorDarken;
                    // 2. Pixel um factor aufhellen:
                    // Differenz zu weiss bereit stellen:
                    const delta = 256 - newVal;
                    // Differenz zu weiss um Faktor verringern:
                    newVal = newVal + delta * factor;
                    return newVal;
                });
// usw.
Oder 2. das Abdunkeln nach dem Aufhellen, dann wird der aufgehellte Bereich einbezogen und wird grau:
Code:
                // Farbe um Faktor aufhellen:
                let newColor = color.map((val) => {
                    // 1. Pixel um factor aufhellen:
                    // Differenz zu weiss bereit stellen:
                    const delta = 256 - val;
                    // Differenz zu weiss um Faktor verringern:
                    let newVal = val + delta * factor;
                    // 2. Pixel um factorDarken abdunkeln:
                    newVal = newVal * factorDarken;
                    return newVal;
                });
 

Dieter!

Neues Mitglied
8 Juni 2021
11
0
1
Oldenburg
Wenn ich es nur besser beschreiben könnte, würde es die Sache sicherlich vereinfachen, sorry dafür.
Die Variante 2. ist ungünstig da links ein dunkler Rand entsteht.
Bei Variante 1. wird zwar der rechte Teil dunkler, aber irgendwie auch grauer. Ideal wäre wenn nur der rechte Teil dem Original näher kommen würde. Ist das dann der Kontrast? Ich weiß es nicht.
 

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.406
462
83
68
Der rechte Teil vergraute bisher weil wir das Ende des Einblendens am rechten Bildrand lag, so dass nur aufgehellte Anteile sichtbar waren.
Versuche, ob dies besser ist, ich habe einen Schalter darken eingeführt, der eine zusätzliche Abdunklung bewirkt:
Code:
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Background Image Canvas</title>
</head>


<body>
    <img src="images/pano-stabkirche-small.jpg"><br>
    <canvas id="bgimg"></canvas>
    <div id="log"></div>
    <script>
        const log = document.getElementById('log');
        const imgPath = 'images/pano-stabkirche-small.jpg',
            // Start des Einblendens oben und unten, relativ zur Bildbreite:
            startTop = 0.8, startBtm = 0.6,
            // Bereich in dem aufgehellt wird:
            delta = 0.2,
            // Wenn wir die Werte so setzen bleibt rechts ein Streifen 
            // wo das Bild nicht aufgehellt ist.

            // Abdunkeln rechts ein- bzw. ausschalten:
            darken = false,
            // Canvas und 2D-Context bereit stellen:
            cv = document.getElementById('bgimg'),
            ctx = cv.getContext("2d"),
            img = new Image();
        // Eventhandler fuer das Laden des Bildes registrieren:
        img.onload = () => {
            // Breite und Hoehe des Bildes bereit stellen:
            const wImg = img.width, hImg = img.height;
            // Abmessungen des Canvas an das Bild anpassen:
            cv.width = wImg;
            cv.height = hImg;
            // Bild auf Canvas zeichnen:
            ctx.drawImage(img, 0, 0, wImg, hImg);
            // Bilddaten bereit stellen:
            const imgData = ctx.getImageData(0, 0, wImg, hImg);
            const data = imgData.data;
            // Schleife ueber die Bilddaten
            // Parallel fuehren wir die x- und y-Position:
            for (let i = 0, x = 0, y = 0; i < data.length; i += 4, x++) {
                if (x == wImg) {
                    x = 0;
                    y++;
                }
                // Faktor (0 ... 1) der Aufhellung ermitteln
                // start = relative Position fuer das Ende des Aufhellens
                // von rechts gesehen:
                const start = startTop + (startBtm - startTop) * y / hImg,
                    // startX = absolute Position fuer das Ende des Aufhellens:
                    startX = start * wImg,
                    // deltaY = Bereich, in dem abgedunkelt wird:
                    deltaX = delta * wImg;
                let factor = 0;
                // Ist x kleiner als der Start des Aufhellens ist der Faktor 1:
                if (x < startX) {
                    factor = 1;
                } else if (x > startX + deltaX) {
                    factor = 0;
                } else {
                    // Andernfalls berechnen wir den Faktor für das Aufhellen
                    // und wenden die Quadratwurzel an, um einen natuerlicheren
                    // Verlauf zu erzielen:
                    // factor = Math.sqrt(1 - (x - startX) / deltaX);
                    factor = 1 - (x - startX) / deltaX;
                }
                // Farbe des aktuellen Pixels bereit stellen:
                const color = [data[i], data[i + 1], data[i + 2]];
                // Helligkeit des Pixels bereit stellen:
                const lightness = (data[i] + data[i + 1] + data[i + 2]) / 3 / 256;
                // Nur für mich zum Debuggen:
                // if (y == 499)
                //     log.innerHTML += x + ' ' + y + ' ' + factor + ' ' + lightness + '<br>';
                let newColor = color.map((val) => {
                    let newVal = val;
                    // 1. Pixel abdunkeln wenn dies konfiguriert ist:
                    if (darken) {
                        // Um den Kontrastumfang beizubehalten, verwenden
                        // wir einen quadratischen Verlauf:
                        newVal = val * lightness * lightness;
                    }
                    // 2. Pixel um factor aufhellen:
                    // Differenz zu weiss bereit stellen:
                    const delta = 251 - newVal;
                    // Differenz zu weiss um Faktor verringern:
                    newVal = newVal + delta * factor;
                    return newVal;
                });
                // Neue Farbe in Bilddaten eintragen:
                data[i] = newColor[0];
                data[i + 1] = newColor[1];
                data[i + 2] = newColor[2];
            }
            // Geaenderte Bilddaten auf Canvas zeichnen:
            ctx.putImageData(imgData, 0, 0);
        }
        img.src = imgPath;
    </script>
</body>

</html>
 

Dieter!

Neues Mitglied
8 Juni 2021
11
0
1
Oldenburg
Jetzt ist es wirklich perfekt :cool:
Ich habe mich für darken = false entschieden.
Nachdem ich gesehen dann habe, dass die Variable „delta“ für die Helligkeit verantwortlich ist, habe ich einen weiteren Schieber (0.1 – 1) damit gekoppelt. Nun kann alles so einstehen wie ich es mir vorgestellt habe.

Was soll ich sagen, tausend Dank für deine umfangreiche Unterstützung…
 

Anhänge

  • 1623459705724.png
    1623459705724.png
    450,6 KB · Aufrufe: 4
Werbung: