Вопрос или проблема
Я пытаюсь замаскировать изображение с помощью другого изображения (использующегося в качестве маски) и добавить обводку вокруг формы, определяемой маской, с помощью элемента в JavaScript.
Вот код, который я использую:
function applyFiltersAndConvertToBase64(imageUrl, materialImage) {
return new Promise((resolve, reject) => {
const maskImg = new Image();
const mainImg = new Image();
maskImg.crossOrigin = "anonymous"; // Важно для изображений с другого домена
mainImg.crossOrigin = "anonymous";
let imagesLoaded = 0;
const onLoad = () => {
imagesLoaded++;
if (imagesLoaded === 2) {
// Создаем элемент canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Устанавливаем размеры canvas в размер маски
canvas.width = maskImg.width;
canvas.height = maskImg.height;
// Рисуем маску
ctx.drawImage(maskImg, 0, 0);
// Меняем режим композитинга для использования маски для обрезки
ctx.globalCompositeOperation = 'source-in';
// Рисуем основное изображение для обрезки
ctx.drawImage(mainImg, 0, 0, maskImg.width, maskImg.height);
// Сбрасываем режим композитинга
ctx.globalCompositeOperation = 'source-over';
// Преобразуем canvas в Base64
const base64Image = canvas.toDataURL('image/png');
resolve(base64Image);
}
};
maskImg.onload = onLoad;
mainImg.onload = onLoad;
maskImg.onerror = reject;
mainImg.onerror = reject;
// Устанавливаем источники
maskImg.src = imageUrl; // Изображение маски
mainImg.src = materialImage; // Основное изображение
});
}
Эта функция хорошо работает для применения маски и обрезки основного изображения, но мне сложно добавить обводку вокруг формы маски. Обводка либо появляется как прямоугольник, либо вообще не появляется, в зависимости от подхода, который я пробовал.
Как я могу добавить обводку, которая будет следовать форме, определяемой маской, а не прямоугольным границам canvas? Я хочу, чтобы обводка точно следовала краям маски.
Любая помощь будет оценена!
Как я могу добавить обводку, которая будет следовать форме, определяемой маской, а не прямоугольным границам canvas? Я хочу, чтобы обводка точно следовала краям маски.
Ответ или решение
Чтобы добавить рамку, которая обрисовывает форму маски, а не прямоугольные границы канваса, можно использовать несколько техник на основе Canvas API. Основная идея заключается в том, чтобы сначала нарисовать маску на канвасе с помощью метода ctx.clip()
, а затем нарисовать рамку после завершения обрезки. Вот как это можно реализовать:
function applyFiltersAndConvertToBase64(imageUrl, materialImage, borderWidth = 5, borderColor = 'black') {
return new Promise((resolve, reject) => {
const maskImg = new Image();
const mainImg = new Image();
maskImg.crossOrigin = "anonymous"; // Важно для кросс-доменных изображений
mainImg.crossOrigin = "anonymous";
let imagesLoaded = 0;
const onLoad = () => {
imagesLoaded++;
if (imagesLoaded === 2) {
// Создаем элемент canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Устанавливаем размеры canvas по размерам маски
canvas.width = maskImg.width;
canvas.height = maskImg.height;
// Рисуем маску
ctx.drawImage(maskImg, 0, 0);
// Применяем композитный режим для обрезки
ctx.globalCompositeOperation = 'source-in';
ctx.drawImage(mainImg, 0, 0, maskImg.width, maskImg.height);
ctx.globalCompositeOperation = 'source-over'; // Сбрасываем композитный режим
// Рисуем рамку
ctx.lineWidth = borderWidth; // Устанавливаем ширину рамки
ctx.strokeStyle = borderColor; // Устанавливаем цвет рамки
// Создаем путь для рамки, который повторяет форму маски
ctx.beginPath();
ctx.drawImage(maskImg, 0, 0); // Рисуем маску для определения её контура
ctx.globalCompositeOperation = 'destination-atop'; // Применяем режим, который позволит рисовать только внутри маски
ctx.rect(0, 0, maskImg.width, maskImg.height); // Рисуем прямоугольник
ctx.stroke(); // Рисуем рамку
ctx.globalCompositeOperation = 'source-over'; // Сбрасываем композитный режим
// Конвертируем канвас в Base64
const base64Image = canvas.toDataURL('image/png');
resolve(base64Image);
}
};
maskImg.onload = onLoad;
mainImg.onload = onLoad;
maskImg.onerror = reject;
mainImg.onerror = reject;
// Устанавливаем источники изображений
maskImg.src = imageUrl; // Маска
mainImg.src = materialImage; // Основное изображение
});
}
Пояснение к коду
- Создание канваса: Размер канваса совпадает с размерами маски.
- Рисование маски и основного изображения: Маска и основное изображение рисуются на канвасе. Композитный режим
source-in
используется для обрезки основного изображения по форме маски. - Рисование рамки: Рамка рисуется после того, как основное изображение было обрезано. Сначала устанавливаем ширину и цвет рамки. Мы используем
globalCompositeOperation = 'destination-atop'
, чтобы рамка применялась только в области, где есть форма маски. Это гарантирует, что рамка будет следовать контурам маски. - Конвертация в Base64: После всех операций канвас преобразуется в Base64 изображение, которое можно использовать по вашему усмотрению.
Теперь рама будет корректно отображаться, следуя контурам маски, а не создавая прямоугольник.