UNPKG

@syngrisi/syngrisi

Version:
168 lines (148 loc) 7.28 kB
/* eslint-disable no-console */ import { fabric } from 'fabric'; import { MainView } from '../Canvas/mainView'; export interface IGroup { minX: number maxX: number minY: number maxY: number imageData: any, members: { x: number, y: number }[], } function getDiffImageData(image: any) { const canvas = document.createElement('canvas'); canvas.width = image.width; canvas.height = image.height; const ctx = canvas.getContext('2d'); ctx!.drawImage(image, 0, 0); const imgData = ctx!.getImageData(0, 0, image.width, image.height); return imgData; } export function highlightDiff(mainView: MainView, highlightsGroups: IGroup[] | null, imageData: any) : Promise<{ groups: IGroup[], diffImageData: any }> { return new Promise((resolve) => { // remove highlights mainView.canvas.getObjects() .filter((x) => x.name === 'highlight') .forEach((x) => mainView.canvas.remove(x)); // get image data const urlData = mainView.diffImage.toDataURL({}); const img = new Image(); img.src = urlData; img.onload = () => { console.time('get_image_data'); const diffImageData = imageData || getDiffImageData(img); console.timeEnd('get_image_data'); console.time('process_data'); const createNewGroup = (x: number, y: number) => ({ minX: x, maxX: x, minY: y, maxY: y, members: [{ x, y }], }); // get pixel color string from flat array of image data e.g.: '255,0,255,255'(rgba) // eslint-disable-next-line max-len const getPixel = (x: number, y: number, curCount: number): string => diffImageData.data.slice(curCount, curCount + 4).join(); const diffColor = '255,0,255,255'; const groups: IGroup[] = highlightsGroups || []; console.time('group formation'); if (groups.length < 1) { let cursorCount = 0; for (let y = 0; y < diffImageData.height; y += 1) { for (let x = 0; x < diffImageData.width; x += 1) { // console.log(getPixel(x, y, cursorCount), diffColor); if (getPixel(x, y, cursorCount) === diffColor) { const suitableGroup = groups.find((group) => x >= group.minX - 1 && x <= group.maxX + 1 && y >= group.minY && y <= group.maxY + 1); if (!suitableGroup) { groups.push(createNewGroup(x, y)); } else if ( getPixel(x - 1, y, cursorCount) === diffColor // left || getPixel(x - 1, y - 1, cursorCount) === diffColor // top left || getPixel(x, y - 1, cursorCount) === diffColor // top || getPixel(x + 1, y - 1, cursorCount) === diffColor // top right || getPixel(x + 1, y, cursorCount) === diffColor // right || getPixel(x + 1, y + 1, cursorCount) === diffColor // bottom right || getPixel(x, y + 1, cursorCount) === diffColor // bottom || getPixel(x - 1, y + 1, cursorCount) === diffColor // bottom left ) { suitableGroup.members.push({ x, y }); if (x < suitableGroup.minX) suitableGroup.minX = x; if (x > suitableGroup.maxX) suitableGroup.maxX = x; if (y > suitableGroup.maxY) suitableGroup.maxY = y; } } cursorCount += 4; } } } console.timeEnd('group formation'); console.time('group handling'); // eslint-disable-next-line no-restricted-syntax for (const group of groups) { // console.log(group); const top = group.minY + (group.maxY - group.minY) / 2; const left = group.minX + (group.maxX - group.minX) / 2; const circle = new fabric.Circle({ name: 'highlight', originX: 'center', originY: 'center', left, top, // radius: 5, data: { group }, fill: '#D6336C', opacity: 0.3, strokeWidth: 0, selectable: false, }); mainView.canvas.add(circle); } console.timeEnd('group handling'); console.timeEnd('process_data'); const highlightRemoving = () => { mainView.canvas.getObjects() .filter((x) => x.name === 'highlight') .forEach((x) => mainView.canvas.remove(x)); }; // highlights animation setTimeout(() => { mainView.canvas.getObjects() .filter((x) => x.name === 'highlight') .forEach((circle) => { const suitableRadius = Math.max( circle.data.group.maxX - circle.data.group.minX, circle.data.group.maxY - circle.data.group.minY, ); const radius = ((suitableRadius > 25 ? suitableRadius : 25) + Math.floor(Math.random() * 10)) / mainView.canvas.getZoom(); circle.animate('opacity', '0.5', { onChange: mainView.canvas.renderAll.bind(mainView.canvas), duration: 500, }); circle.animate('radius', String(radius), { onChange: mainView.canvas.renderAll.bind(mainView.canvas), duration: 500, onComplete: () => { circle.animate('radius', '0.00', { onChange: mainView.canvas.renderAll.bind(mainView.canvas), // slowHighlight - for testing purposes duration: window?.slowHighlight ? 15000 : 700, onComplete: highlightRemoving, }); circle.animate('opacity', '0.30', { onChange: mainView.canvas.renderAll.bind(mainView.canvas), duration: window?.slowHighlight ? 3000 : 700, }); }, }); }); mainView.canvas.renderAll(); }, 0); return resolve({ groups, diffImageData }); }; }); }