13.05.2019, 14:34
|
Аспирант
|
|
Регистрация: 02.06.2016
Сообщений: 36
|
|
проблема с canvas image
Добрый день уважаемые. столкнулся с проблемой на канвас. цель сделать простой кропер.
1)загруженное изображение скалируется под разрешение canvas (разрешение полотна 600х400)
2)на данное изображение накладывается черно-белый фильтр и блюр
3)создается второй слой этого же изображения, но уже цветно и обрезанное под нужное разрешение (разрешение можно динамически менять)
4) это слой можно передвигать по всему канвас-полотну и видеть какое изображение будет в результате на выходе
вот часть кода:
handleCanvas = () => {
let { posX, posY, img} = this.state
/*
img - загруженное изображение
posX - координаты нового слоя с изобращением по Х
posY - координаты нового слоя с изобращением по Y
*/
let c=document.getElementById('canvas_t');
if(c){
//
let MAX_WIDTH = 600;
let MAX_HEIGHT = 400;
let width = img.width;
let height = img.height;
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}
//
let ctx
c.width = width
c.height = height
ctx = c.getContext('2d')
ctx.clearRect(0, 0, 600, 400);
ctx.filter = 'grayscale(100) blur(3px)'
//рендерим фон изображения на полотне
ctx.drawImage(img, 0, 0, width, height )
//очищаем фильтр
ctx.filter = 'grayscale(0) blur(0)'
ctx.strokeRect(posX, posY, this.state.w, this.state.h)
//рендерим новое изображение с позициями и указанным форматом
ctx.drawImage(img , posX, posY,this.state.w,this.state.h, posX, posY, this.state.w,this.state.h)
ctx.fillStyle = 'rgba(138, 196, 235, 0.7)'
ctx.fillRect(posX + this.state.w - 5,posY + this.state.h - 5, 10,10)
}
}
Суть проблемы:
редактируемый слой изображения не сходится с фоновым
|
|
13.05.2019, 14:59
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
Самый простой способ - сделать clip на основе текущей выбранной рамки кропа и зарядить ctx.drawImage(img, 0, 0, width, height ) повторно - отрисуется только тот квадратик, который в клипе.
Набросок:
...
ctx.save();
ctx.beginPath();
ctx.rect(posX, posY, this.state.w, this.state.h);
ctx.clip();
ctx.drawImage(img, 0, 0, width, height );
ctx.restore();
...
Плюс этого способа - не придется морочить голову сдвигами и размерами (если картинка не сжимается в размерах и рисуется как есть, то всё просто, иначе надо правильно подобрать параметры для самой полной версии drawImage, что слегонца геморно. Хотя, впрочем, спозиционировать установленную рамку на реальную картинку всё равно придется, так что можно и сразу это делать)
Последний раз редактировалось Alexandroppolus, 13.05.2019 в 15:09.
|
|
13.05.2019, 15:17
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
Кстати, картинка с размерами, к примеру, 600х500 неправильно посайзится в твоем кропе
|
|
13.05.2019, 15:31
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
навскидку, без clip
let MAX_WIDTH = 600;
let MAX_HEIGHT = 400;
let width = img.width;
let height = img.height;
let ratio = 1;
if (width > MAX_WIDTH || height > MAX_HEIGHT) {
ratio = Math.max(width / MAX_WIDTH, height / MAX_HEIGHT);
width = width / ratio;
height = height / ratio;
}
......
//рендерим новое изображение с позициями и указанным форматом
ctx.drawImage(img, posX * ratio, posY * ratio, this.state.w * ratio, this.state.h * ratio,
posX, posY, this.state.w, this.state.h);
|
|
13.05.2019, 15:40
|
Аспирант
|
|
Регистрация: 02.06.2016
Сообщений: 36
|
|
Alexandroppolus, спасибо тебе большое, очень помог
|
|
13.05.2019, 16:16
|
|
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
Alexandroppolus, korih,
const MAX_WIDTH = 600;
const MAX_HEIGHT = 400;
let width = img.width;
let height = img.height;
const ρ = 1 / Math.min(MAX_WIDTH / width, MAX_HEIGHT / height, 1);
width /= ρ;
height /= ρ;
// ......
// дорисовываем новое изображение с позициями и указанным форматом
ctx.drawImage(img, posX * ρ, posY * ρ, this.state.w * ρ, this.state.h * ρ,
posX, posY, this.state.w, this.state.h);
|
|
|
|