проблема с 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) } } Суть проблемы: редактируемый слой изображения не сходится с фоновым ![]() ![]() |
Самый простой способ - сделать 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, что слегонца геморно. Хотя, впрочем, спозиционировать установленную рамку на реальную картинку всё равно придется, так что можно и сразу это делать) |
Кстати, картинка с размерами, к примеру, 600х500 неправильно посайзится в твоем кропе
|
навскидку, без 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); |
Alexandroppolus, спасибо тебе большое, очень помог
|
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); |
Часовой пояс GMT +3, время: 15:26. |