Библиотека для нарезки изображении JS
Подскажите, пожалуйста, есть ли какая-то библиотека, которая может нарезать изображение на выбранное количество частей. Пишу паззл на JS Canvas. Хотелось бы реализовать возможность, чтобы пользователь мог загружать свое изображение и после собирать его. Такое вообще возможно? Или хотя бы, чтобы эта библиотека нарезала те изображение, которые представлены на выбор для игры.
Ответы (1 шт):
Это возможно. Не думаю, что нужна библиотека. Здесь слишком много вводимых переменных (констант), но это для лучшего понимания кода.
Здесь мы получаем изображение из input type="file". Создаем на основе данных элемент <img/>. Oтрисовываем его на скрытом холсте. Затем, в зависимости от количества колонок и рядов, получаем массив с перемешанными порядковыми номерами ячеек. И, исходя из этого порядка, отрисовываем ячейки (по сути нарезанное изображение) на наш основной холст.
Ширина холста константная, а высота подстраивается под соотношение сторон изображения. Эту логику можно поменять, разумеется.
Попробуйте разобраться с каждой отдельной функцией и выражением. Если будет совсем плохо, то дам подробные комментарии.
P.S. Можно нарезать изображение и на сложные куски, каждый раз применяя ctx.clip() к скрытому холсту и перенося результат на основной холст. Тут нужны уже пути отдельных элементов паззла.
И для дальнейшей манипуляции отдельными фрагментами подумайте над использованием SVG. Как минимум определять какой элемент (со сложными границами) будет выбран для перемещения (или даже вращения). Можно иметь либо подложенный canvas с разноцветными фрагментами - копиями сложных путей отдельных фрагментов паззла, по цвету "расшифровывать" нужный элемент. И тогда перемещать и сам элемент на основном холсте и цветной фрагмент одновременно.
А можно наложить SVG с такими же по форме фрагментами, но только с контурами. Снизу ваш холст. Менять атрибуты translate (или rotate) прозрачных path и на столько же перемещать фрагменты на основном холсте. В общем, работы много))
const col_num = 4;
const raw_num = 4;
document.querySelector('input[type="file"]').addEventListener('change', getImage);
const canvas = document.querySelector('canvas');
const w = canvas.width = 600;
let h;
const ctx = canvas.getContext('2d');
const canvas_hidden = document.createElement('canvas');
const ctx_hidden = canvas_hidden.getContext('2d');
function getImage(e){
const image = document.createElement('img');
image.addEventListener('load', cutImage);
image.src = URL.createObjectURL(e.target.files[0]);
}
function cutImage(e){
const img = e.target;
const [img_w,img_h] = [img.width,img.height];
const k = img_w/img_h;
h = canvas.height = w / k;
canvas_hidden.width = w;
canvas_hidden.height = h;
ctx_hidden.drawImage(img,0,0,w,h);
const cell_num = col_num * raw_num;
const cell_w = w / col_num;
const cell_h = h / raw_num;
const cell_order = [...getRandomizedArray(cell_num)];
for(let i = 0; i < cell_order.length; i++){
const s = cell_order[i];
const s_x = s % col_num * cell_w;
const s_y = Math.floor(s / col_num) * cell_h;
const d_x = i % col_num * cell_w;
const d_y = Math.floor(i / col_num) * cell_h;
ctx.drawImage(canvas_hidden,s_x,s_y,cell_w,cell_h,d_x,d_y,cell_w,cell_h);
}
}
function getRandomizedArray(len){
const arr = Array.from({length:len}, (_,i) => i);
for(let i=0; i < arr.length; i++){
let j = Math.floor(Math.random() * arr.length);
[arr[j],arr[i]] = [arr[i],arr[j]];
}
return arr;
}
<input type="file" accept=".jpg, .jpeg, .png">
<hr>
<canvas></canvas>
