Як змінити непрозорість (альфа, прозорість) елемента в елементі полотна після його малювання?


196

Використовуючи <canvas>елемент HTML5 , я хотів би завантажити файл зображення (PNG, JPEG тощо), намалювати його на полотно повністю прозоро, а потім розтушувати. Я зрозумів, як завантажити зображення та намалювати його на полотно, але я не знаю, як змінити його непрозорість, як тільки його намалювали.

Ось код у мене поки що:

var canvas = document.getElementById('myCanvas');

if (canvas.getContext)
{
    var c           = canvas.getContext('2d');
    c.globalAlpha   = 0;

    var img     = new Image();
    img.onload  = function() {
        c.drawImage(img, 0, 0);
    }
    img.src     = 'image.jpg';
}

Хтось, будь ласка, вкаже мене в правильному напрямку, як властивість, яку потрібно встановити, або функцію для виклику, яка змінить непрозорість?

Відповіді:


307

Я також шукаю відповідь на це питання (щоб уточнити, я хочу мати змогу намалювати зображення із непрозорістю, визначеною користувачем, наприклад, як можна малювати фігури з непрозорістю), якщо ви малюєте з примітивними формами, ви можете встановити заливку та обведення колір з альфа для визначення прозорості. Наскільки я зараз зробив висновок, це, мабуть, не впливає на малювання зображення.

//works with shapes but not with images
ctx.fillStyle = "rgba(255, 255, 255, 0.5)";

Я зробив висновок, що налаштування globalCompositeOperationтворів із зображеннями.

//works with images
ctx.globalCompositeOperation = "lighter";

Цікаво, чи існує якийсь третій спосіб встановлення кольору, щоб ми могли тонувати зображення та робити їх прозорими легко.

Редагувати:

Після подальшого копання я зробив висновок, що ви можете встановити прозорість зображення, встановивши globalAlphaпараметр ДО ПЕРЕДМОГО малювати зображення:

//works with images
ctx.globalAlpha = 0.5

Якщо ви хочете досягти ефекту згасання з часом, вам потрібен певний цикл, який змінює значення альфа, це досить легко, один із способів досягти цього - setTimeoutфункція, шукайте, щоб створити цикл, з якого ви переймете альфа на час.


7
globalAlpha прекрасно працює. Є частиною стандарту: whatwg.org/specs/web-apps/current-work/multipage / ...
Aleris

42
Якщо бути точним, це не той canvasелемент, який має globalAlphaвластивість, а контекст, який ви отримуєте з полотна.
Стів Блеквелл

8
Коментар Яна до ctx.save () та ctx.restore () заважає глобальній Альфі впливати на решту полотна.
Аросборо

1
Мені здається, а не контролювати непрозорість того, що намальовано на полотні, було б простіше і все-таки служити меті просто контролювати непрозорість самого полотна після нанесення зображення (лише один раз). Використовуйте звичайні методи CSS / style для цього (canvaselement.style.opacity = '0,3'; і т.д.). Пізніше за допомогою CSS3 ви можете взагалі відмовитись від циклу і просто дозволити браузеру замість цього переходити із завмиранням (щось на зразок переходу: NNNms непрозорість легкого в’їзду) або навіть «оживити» згасання.
Чак Колларс

1
На жаль, canvas2d.fillStyle = "rgba(255, 255, 255, 0.5)";не працює. Значення повинно бути в шістнадцятковій формі.
WebWanderer

113

Деякі простіші приклади коду для використання globalAlpha:

ctx.save();
ctx.globalAlpha = 0.4;
ctx.drawImage(img, x, y);
ctx.restore();

Якщо вам потрібно imgзавантажити:

var img = new Image();
img.onload = function() {
    ctx.save();
    ctx.globalAlpha = 0.4;
    ctx.drawImage(img, x, y);
    ctx.restore()
};
img.src = "http://...";

Примітки:

  • Встановіть 'src'останнє, щоб гарантувати, що ваш onloadобробник викликається на всіх платформах, навіть якщо зображення вже є в кеші.

  • Оберніть зміни на такі речі, як globalAlphaміж ( saveі restoreнасправді використовуйте їх безліч), щоб переконатися, що ви не налаштовуєте налаштування з інших місць, особливо коли біти коду малювання будуть викликані з подій.


globalAlpha розмиє всі зображення чи малюнки на полотні, це не те, що ви хочете.
Бурхливий

6
@Grumpy - ні, globalAlphaнічого не розмиває. Він встановить альфа для всіх наступних креслень (він не змінює нічого вже намальованого), саме тому в прикладі коду я його загортаю saveі restore, щоб обмежити те, що воно стосується.
Ян

не впевнений, що ctx.restore () відновить globalAlpha, можливо, вам також знадобиться зробити це наприкінці (принаймні, мені довелося в попередніх версіях Chrome) ctx.globalAlpha = 1;
Шон

1
@Sean - якщо ви не впевнені, слід перевірити. Це, мабуть, був дуже старий Chrome, він працює на всіх платформах зараз: jsfiddle.net/y0z9h9m7
Ian

14

Редагувати: Відповідь, позначена як "правильна", не вірна.

Це легко зробити. Спробуйте цей код, замінивши "ie.jpg" будь-якою картинкою, яка вам зручна:

<!DOCTYPE HTML>
<html>
    <head>
        <script>
            var canvas;
            var context;
            var ga = 0.0;
            var timerId = 0;

            function init()
            {
                canvas = document.getElementById("myCanvas");
                context = canvas.getContext("2d");
                timerId = setInterval("fadeIn()", 100);
            }

            function fadeIn()
            {
                context.clearRect(0,0, canvas.width,canvas.height);
                context.globalAlpha = ga;
                var ie = new Image();
                ie.onload = function()
                {
                    context.drawImage(ie, 0, 0, 100, 100);
                };
                ie.src = "ie.jpg";

                ga = ga + 0.1;
                if (ga > 1.0)
                {
                    goingUp = false;
                    clearInterval(timerId);
                }
            }
        </script>
    </head>
    <body onload="init()">
        <canvas height="200" width="300" id="myCanvas"></canvas>
    </body>
</html>

Ключовим є властивість globalAlpha.

Тестовано на IE 9, FF 5, Safari 5 та Chrome 12 на Win7.


13

Пост старий, поки я піду зі своєю пропозицією. Пропозиція заснована на маніпуляції пікселями в полотні 2d контексту. Від MDN:

Ви можете безпосередньо маніпулювати піксельними даними на полотнах на рівні байтів

Для маніпулювання пікселями ми використаємо дві функції тут - getImageData та putImageData

Використання функції getImageData:

var myImageData = context.getImageData (зліва, вгорі, ширина, висота);

і синтаксис putImageData:

context.putImageData (myImageData, dx, dy); // dx, dy - x і y зміщено на вашому полотні

Де контекст - це ваш полотно, 2d контекст

Отже, щоб отримати червоно-зелений синій та альфа-значення, ми зробимо наступне:

var r = imageData.data[((x*(imageData.width*4)) + (y*4))];
var g = imageData.data[((x*(imageData.width*4)) + (y*4)) + 1];
var b = imageData.data[((x*(imageData.width*4)) + (y*4)) + 2];
var a = imageData.data[((x*(imageData.width*4)) + (y*4)) + 3];

Де х - зміщення, y - зміщення на полотні

Тож у нас код робить зображення напівпрозорим

var canvas = document.getElementById('myCanvas');
var c = canvas.getContext('2d');
var img = new Image();
img.onload  = function() {
   c.drawImage(img, 0, 0);
   var ImageData = c.getImageData(0,0,img.width,img.height);
   for(var i=0;i<img.height;i++)
      for(var j=0;j<img.width;j++)
         ImageData.data[((i*(img.width*4)) + (j*4) + 3)] = 127;//opacity = 0.5 [0-255]
   c.putImageData(ImageData,0,0);//put image data back
}
img.src = 'image.jpg';

Ви можете зробити власні "шейдери" - дивіться повну статтю MDN тут


7

Ти можеш. Прозорий полотно може бути швидко втрачено, використовуючи цільової вихід глобальної складову операції. Це не на 100% досконало, іноді він залишає сліди, але його можна підробити, залежно від необхідного (наприклад, використовуйте "джерело" та заповніть його білим кольором з альфа на 0,13, а потім зів'януть, щоб підготувати полотно).

// Fill canvas using 'destination-out' and alpha at 0.05
ctx.globalCompositeOperation = 'destination-out';
ctx.fillStyle = "rgba(255, 255, 255, 0.05)";
ctx.beginPath();
ctx.fillRect(0, 0, width, height);
ctx.fill();
// Set the default mode.
ctx.globalCompositeOperation = 'source-over';

3

Я думаю, що це найкраще відповідає на запитання, воно фактично змінює альфа-значення того, що вже було намальовано. Можливо, це не було частиною api, коли це питання було задано.

враховуючи контекст 2d c.

function reduceAlpha(x, y, w, h, dA) {
    var screenData = c.getImageData(x, y, w, h);
    for(let i = 3; i < screenData.data.length; i+=4){
    screenData.data[i] -= dA; //delta-Alpha
    }
    c.putImageData(screenData, x, y );
}

Чим ця відповідь відрізняється від відповіді Soul_man, даної більш докладно за 7 років до цього?
BReddy

-2

Якщо ви використовуєте бібліотеку jCanvas, ви можете використовувати властивість непрозорості під час малювання. Якщо вам потрібен ефект згасання, просто перемалюйте їх із різними значеннями.


-11

Ви не можете. Це графіка негайного режиму. Але ви можете їх моделювати, намалювавши над ним прямокутник у кольорі фону з непрозорістю.

Якщо зображення над чим-небудь іншим, ніж постійний колір, воно стає дещо складнішим. Ви повинні мати можливість використовувати методи маніпуляції пікселями в цьому випадку. Просто збережіть область перед нанесенням зображення, а потім змішайте цю поверхню з непрозорістю після цього.


5
Це не правильна відповідь див нижче
Райан Бадур

Ви правильно, хоча ви не можете змінити непрозорість одного з елементів, які ви намалювали на полотні, ви можете змінити непрозорість всього полотна. У деяких випадках цього може бути достатньо.
MPG

2
MPG - ваш коментар (11 травня) також неправильний. Ви можете змінити непрозорість полотна, але це не те, чого хотів ОП, ані те, що пропонується у відповідях вище.
Ян
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.