mirror of
https://github.com/Doodle3D/Doodle3D-Core.git
synced 2024-11-04 21:53:24 +01:00
fix imports
This commit is contained in:
parent
08e88805c4
commit
20995d0ac7
177
src/reducer/contextReducer.js
Normal file
177
src/reducer/contextReducer.js
Normal file
@ -0,0 +1,177 @@
|
||||
import update from 'react-addons-update';
|
||||
import * as contextTools from 'src/js/constants/contextTools.js';
|
||||
import { COLOR_STRING_TO_HEX, COLOR_HEX_TO_STRING } from 'src/js/constants/general.js';
|
||||
import { ERASER_SIZES, BRUSH_SIZES } from 'src/js/constants/d2Constants.js';
|
||||
import * as actions from 'src/js/actions/index.js';
|
||||
import { select } from './menusReducer.js';
|
||||
import { getSelectedObjectsSelector, getBoundingBox } from 'src/js/utils/selectionUtils.js';
|
||||
import { Matrix } from 'cal';
|
||||
|
||||
export default function (state, action) {
|
||||
switch (action.category) {
|
||||
case actions.sketcher.CAT_SELECTION: {
|
||||
let menus = state.menus;
|
||||
|
||||
const [firstSelected] = state.selection.objects;
|
||||
const colorHex = firstSelected ? state.objectsById[firstSelected.id].color : state.context.color;
|
||||
// pick current draw color when color is unknown
|
||||
const color = COLOR_HEX_TO_STRING[colorHex] || COLOR_HEX_TO_STRING[state.context.color];
|
||||
menus = select(menus, color);
|
||||
|
||||
const fillBool = firstSelected && state.objectsById[firstSelected.id].fill;
|
||||
const fill = fillBool ? contextTools.FILL_TOGGLE_FILL : contextTools.FILL_TOGGLE_OUTLINE;
|
||||
menus = select(menus, fill);
|
||||
|
||||
return update(state, { menus: { $set: menus } });
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (action.type) {
|
||||
case actions.sketcher.D2_CHANGE_TOOL: {
|
||||
const color = COLOR_HEX_TO_STRING[state.context.color];
|
||||
return update(state, {
|
||||
menus: { $set: select(state.menus, color) }
|
||||
});
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (action.tool) {
|
||||
case contextTools.LIGHT_BLUE:
|
||||
case contextTools.LIGHT_GREEN:
|
||||
case contextTools.LIGHT_PINK:
|
||||
case contextTools.LIGHT_YELLOW:
|
||||
case contextTools.BLUE:
|
||||
case contextTools.GREEN:
|
||||
case contextTools.PINK:
|
||||
case contextTools.YELLOW:
|
||||
case contextTools.DARK_BLUE:
|
||||
case contextTools.DARK_GREEN:
|
||||
case contextTools.DARK_PINK:
|
||||
case contextTools.DARK_YELLOW: {
|
||||
const color = COLOR_STRING_TO_HEX[action.tool];
|
||||
return update(state, {
|
||||
objectsById: state.selection.objects.reduce((updateObject, { id }) => {
|
||||
updateObject[id] = { color: { $set: color } };
|
||||
return updateObject;
|
||||
}, {}),
|
||||
context: {
|
||||
color: { $set: color }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
case contextTools.ERASER_SIZE_SMALL:
|
||||
case contextTools.ERASER_SIZE_MEDIUM:
|
||||
case contextTools.ERASER_SIZE_LARGE: {
|
||||
const size = ERASER_SIZES[action.tool];
|
||||
return update(state, {
|
||||
d2: {
|
||||
eraser: {
|
||||
size: { $set: size }
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
case contextTools.BRUSH_SIZE_SMALL:
|
||||
case contextTools.BRUSH_SIZE_MEDIUM:
|
||||
case contextTools.BRUSH_SIZE_LARGE: {
|
||||
const size = BRUSH_SIZES[action.tool];
|
||||
return update(state, {
|
||||
d2: {
|
||||
brush: {
|
||||
size: { $set: size }
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
case contextTools.FILL_TOGGLE_FILL:
|
||||
case contextTools.FILL_TOGGLE_OUTLINE: {
|
||||
const fill = action.tool === contextTools.FILL_TOGGLE_FILL;
|
||||
|
||||
return update(state, {
|
||||
objectsById: state.selection.objects.reduce((updateObject, { id }) => {
|
||||
updateObject[id] = { fill: { $set: fill } };
|
||||
return updateObject;
|
||||
}, {})
|
||||
});
|
||||
}
|
||||
|
||||
case contextTools.ALIGN_LEFT:
|
||||
case contextTools.ALIGN_HORIZONTAL:
|
||||
case contextTools.ALIGN_RIGHT:
|
||||
case contextTools.ALIGN_TOP:
|
||||
case contextTools.ALIGN_VERTICAL:
|
||||
case contextTools.ALIGN_BOTTOM: {
|
||||
if (state.selection.objects < 2) return state;
|
||||
|
||||
const selection = state.selection;
|
||||
const selectedShapeDatas = getSelectedObjectsSelector(selection.objects, state.objectsById);
|
||||
const totalBoundingBox = getBoundingBox(selectedShapeDatas);
|
||||
|
||||
for (const shapeData of selectedShapeDatas) {
|
||||
const boundingBox = getBoundingBox([shapeData]);
|
||||
|
||||
let deltaX = 0;
|
||||
let deltaY = 0;
|
||||
switch (action.tool) {
|
||||
case contextTools.ALIGN_LEFT:
|
||||
deltaX = totalBoundingBox.min.x - boundingBox.min.x;
|
||||
break;
|
||||
case contextTools.ALIGN_HORIZONTAL:
|
||||
deltaX = totalBoundingBox.center.x - boundingBox.center.x;
|
||||
break;
|
||||
case contextTools.ALIGN_RIGHT:
|
||||
deltaX = totalBoundingBox.max.x - boundingBox.max.x;
|
||||
break;
|
||||
case contextTools.ALIGN_TOP:
|
||||
deltaY = totalBoundingBox.min.z - boundingBox.min.z;
|
||||
break;
|
||||
case contextTools.ALIGN_VERTICAL:
|
||||
deltaY = totalBoundingBox.center.y - boundingBox.center.y;
|
||||
break;
|
||||
case contextTools.ALIGN_BOTTOM:
|
||||
deltaY = totalBoundingBox.max.z - boundingBox.max.z;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const transform = state.objectsById[shapeData.UID].transform.translate(deltaX, deltaY);
|
||||
|
||||
state = update(state, {
|
||||
objectsById: {
|
||||
[shapeData.UID]: {
|
||||
transform: { $set: transform }
|
||||
}
|
||||
},
|
||||
selection: {
|
||||
objects: {
|
||||
[selection.objects.findIndex(({ id }) => id === shapeData.UID)]: {
|
||||
initialTransform: { $set: transform }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
state = update(state, {
|
||||
selection: {
|
||||
transform: { $set: new Matrix() }
|
||||
}
|
||||
});
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
@ -1,16 +1,14 @@
|
||||
import update from 'react-addons-update';
|
||||
import fillPath from 'fill-path';
|
||||
import ClipperShape from 'clipper-js';
|
||||
import * as actions from '../../../actions/index.js';
|
||||
import { SHAPE_TYPE_PROPERTIES } from '../../../constants/shapeTypeProperties.js';
|
||||
import { LINE_WIDTH, CLIPPER_PRECISION } from '../../../constants/d2Constants.js';
|
||||
import createDebug from 'debug';
|
||||
import { shapeToPoints, applyMatrixOnShape, pathToVectorPath } from '../../../utils/shapeDataUtils.js';
|
||||
import { shapeToPoints, applyMatrixOnShape, pathToVectorPath } from '../../../shape/shapeDataUtils.js';
|
||||
import { addObject } from '../../../reducers/objectReducers.js';
|
||||
import fillPath from 'fill-path';
|
||||
import ClipperShape from 'clipper-js';
|
||||
import subtractShapeFromState from '../../../utils/subtractShapeFromState.js';
|
||||
import update from 'react-addons-update';
|
||||
import { get as getConfig } from '../../../services/config.js';
|
||||
import { getColor, getFirst, filterType, getObjectsFromIds } from '../../../utils/objectSelectors.js';
|
||||
|
||||
import createDebug from 'debug';
|
||||
const debug = createDebug('d3d:reducer:bucket');
|
||||
|
||||
const MITER_LIMIT = 30.0;
|
||||
@ -20,22 +18,20 @@ export default function bucketReducer(state, action) {
|
||||
|
||||
switch (action.type) {
|
||||
case actions.D2_TAP:
|
||||
const { experimentalColorPicker } = getConfig();
|
||||
|
||||
let color = state.context.color;
|
||||
if (experimentalColorPicker) {
|
||||
const imageColor = getColor(
|
||||
getFirst(
|
||||
filterType(
|
||||
getObjectsFromIds(state, action.objects),
|
||||
'IMAGE_GUIDE'
|
||||
)
|
||||
),
|
||||
action.position,
|
||||
action.screenMatrixZoom
|
||||
);
|
||||
if (imageColor !== null) color = imageColor;
|
||||
}
|
||||
const color = state.context.color;
|
||||
// if (experimentalColorPicker) {
|
||||
// const imageColor = getColor(
|
||||
// getFirst(
|
||||
// filterType(
|
||||
// getObjectsFromIds(state, action.objects),
|
||||
// 'IMAGE_GUIDE'
|
||||
// )
|
||||
// ),
|
||||
// action.position,
|
||||
// action.screenMatrixZoom
|
||||
// );
|
||||
// if (imageColor !== null) color = imageColor;
|
||||
// }
|
||||
|
||||
// if clicked on a filled shape change shape color
|
||||
const filledPathIndex = action.objects.findIndex(id => (
|
||||
|
4
src/reducer/d3/tools/heightReducer.js
vendored
4
src/reducer/d3/tools/heightReducer.js
vendored
@ -1,8 +1,8 @@
|
||||
import update from 'react-addons-update';
|
||||
import { Utils } from 'cal';
|
||||
import * as THREE from 'three';
|
||||
import { SHAPE_TYPE_PROPERTIES } from '../../../constatants/shapeTypeProperties.js';
|
||||
import * as d3Tools from '../../../constatants/d3Tools.js';
|
||||
import { SHAPE_TYPE_PROPERTIES } from '../../../constants/shapeTypeProperties.js';
|
||||
import * as d3Tools from '../../../constants/d3Tools.js';
|
||||
import { getSelectedObjectsSelector, getBoundingBox } from '../../../utils/selectionUtils.js';
|
||||
import * as actions from '../../../actions/index.js';
|
||||
// import createDebug from 'debug';
|
||||
|
6
src/reducer/d3/tools/stampReducer.js
vendored
6
src/reducer/d3/tools/stampReducer.js
vendored
@ -1,7 +1,7 @@
|
||||
import * as actions from '../../actions/index.js';
|
||||
import * as actions from '../../../actions/index.js';
|
||||
import { addObject, addSpaceActive } from '../../objectReducers.js';
|
||||
import { recursiveClone } from '../../utils/clone.js';
|
||||
import { getBoundingBox, getSelectedObjectsSelector } from '../../utils/selectionUtils.js';
|
||||
import { recursiveClone } from '../../../utils/clone.js';
|
||||
import { getBoundingBox, getSelectedObjectsSelector } from '../../../utils/selectionUtils.js';
|
||||
import { updateInitTransform } from '../../d2/tools/transformReducer.js';
|
||||
import update from 'react-addons-update';
|
||||
import * as THREE from 'three';
|
||||
|
97
src/reducer/menusReducer.js
Normal file
97
src/reducer/menusReducer.js
Normal file
@ -0,0 +1,97 @@
|
||||
import * as actions from 'src/js/actions/index.js';
|
||||
import * as d2Tools from 'src/js/constants/d2Tools.js';
|
||||
import initialMenuStructure from 'src/js/constants/menu.js';
|
||||
// import createDebug from 'debug';
|
||||
// const debug = createDebug('d3d:reducer:menu:index');
|
||||
|
||||
// flatten & add menu structure
|
||||
const initialState = addChildren({}, initialMenuStructure);
|
||||
|
||||
// read children recursivly and add them flat/unnested to the state
|
||||
function addChildren(state, childrenData) {
|
||||
return childrenData.reduce((reducedState, childData) => {
|
||||
reducedState = addItem(reducedState, childData);
|
||||
if (childData.children) {
|
||||
reducedState = addChildren(reducedState, childData.children);
|
||||
}
|
||||
return reducedState;
|
||||
}, { ...state });
|
||||
}
|
||||
function addItem(state, data) {
|
||||
state[data.value] = {
|
||||
disabled: false,
|
||||
selected: '',
|
||||
open: false,
|
||||
...data, // override defaults with given data
|
||||
children: getChildrenValues(data.children)
|
||||
};
|
||||
|
||||
return state;
|
||||
}
|
||||
function getChildrenValues(childrenData = []) {
|
||||
return childrenData.map(child => child.value);
|
||||
}
|
||||
|
||||
// item specific reducer
|
||||
function item(state, action) {
|
||||
switch (action.type) {
|
||||
case actions.sketcher.MENU_OPEN:
|
||||
case actions.sketcher.MENU_CLOSE:
|
||||
return {
|
||||
...state,
|
||||
open: (action.type === actions.sketcher.MENU_OPEN)
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function getMenu(state, targetValue) {
|
||||
if (state[targetValue] === undefined) {
|
||||
throw new Error(`Can't find menu item '${targetValue}'`);
|
||||
}
|
||||
for (const value in state) {
|
||||
if (state[value].children.indexOf(targetValue) !== -1) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
export const select = (state, value) => {
|
||||
const menuValue = getMenu(state, value);
|
||||
// debug(`selectItem: ${value} in ${menuValue}`);
|
||||
if (menuValue === null) return state;
|
||||
// select value in menu
|
||||
state = {
|
||||
...state,
|
||||
[menuValue]: {
|
||||
...state[menuValue],
|
||||
selected: value
|
||||
}
|
||||
};
|
||||
// try selecting menu in it's menu
|
||||
state = select(state, menuValue);
|
||||
return state;
|
||||
};
|
||||
|
||||
export default function menusReducer(state = initialState, action) {
|
||||
if (action.category === actions.sketcher.CAT_SELECTION) {
|
||||
state = select(state, d2Tools.TRANSFORM);
|
||||
}
|
||||
switch (action.type) {
|
||||
case actions.sketcher.MENU_OPEN:
|
||||
case actions.sketcher.MENU_CLOSE:
|
||||
if (action.menuValue === undefined) return state;
|
||||
return {
|
||||
...state,
|
||||
[action.menuValue]: item(state[action.menuValue], action)
|
||||
};
|
||||
case actions.sketcher.D2_CHANGE_TOOL:
|
||||
case actions.sketcher.D3_CHANGE_TOOL:
|
||||
case actions.sketcher.CONTEXT_CHANGE_TOOL:
|
||||
// recursivly select items in menu's
|
||||
return select(state, action.tool);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
136
src/reducer/pointsReducers.js
Normal file
136
src/reducer/pointsReducers.js
Normal file
@ -0,0 +1,136 @@
|
||||
import R from 'ramda';
|
||||
// import createDebug from 'debug';
|
||||
// const debug = createDebug('d3d:reducers:points');
|
||||
|
||||
export function mergePaths(pathA, pathB, matchIndexes) {
|
||||
if (matchIndexes[0] !== -1) { // if first path's first point matches
|
||||
// always reverse first path
|
||||
const sortedA = R.reverse(pathA);
|
||||
// if matches with second path's second point reverse
|
||||
const sortedB = (matchIndexes[0] === 1) ? R.reverse(pathB) : pathB;
|
||||
// add b behind a, removing overlapping point
|
||||
return sortedA.concat(sortedB.slice(1));
|
||||
} else if (matchIndexes[1] !== -1) { // if first path's second point matches
|
||||
// no need to reorder first path
|
||||
const sortedA = pathA;
|
||||
// if matches with second path's second point reverse
|
||||
const sortedB = (matchIndexes[1] === 1) ? R.reverse(pathB) : pathB;
|
||||
// add b behind a, removing overlapping point
|
||||
return sortedA.concat(sortedB.slice(1));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// get just the end points of a path
|
||||
export const getEndPoints = R.juxt([R.head, R.last]);
|
||||
|
||||
export const getEndPointPaths = R.map(getEndPoints);
|
||||
|
||||
const vectorEquals = R.curry(
|
||||
(a, b) => a.equals(b)
|
||||
);
|
||||
|
||||
// find the index of a point in an array of points
|
||||
export const findPointIndex = R.curry(
|
||||
(points, point) => R.findIndex(vectorEquals(point), points)
|
||||
);
|
||||
export const findEndPointIndex = R.curry(
|
||||
(points, point) => findPointIndex(getEndPoints(points), point)
|
||||
);
|
||||
|
||||
// find indexes of multiple points in array of points,
|
||||
// returned as array of indexes
|
||||
// Result examples:
|
||||
// [0]: a's first point matches b's first point
|
||||
// [1]: a's first point matches b's second point
|
||||
// [-1]: a's first point matches none of b's points
|
||||
// [1, 0]: a's first point matches and b's second point and a's second point matches b's first point
|
||||
export const findPointsIndexes = R.curry(
|
||||
(pointsA, pointsB) => R.map(findPointIndex(pointsB), pointsA)
|
||||
);
|
||||
export const findEndPointsIndexes = R.curry(
|
||||
(pathA, pathB) => findPointsIndexes(
|
||||
getEndPoints(pathA),
|
||||
getEndPoints(pathB)
|
||||
)
|
||||
);
|
||||
|
||||
// find the index of a point in an array of paths
|
||||
// (paths are arrays of points)
|
||||
// returns first result
|
||||
// returns array with
|
||||
// - index of path with matching point
|
||||
// - matching index (see findPointsIndexes)
|
||||
export function findPointIndexInPaths(point, paths) {
|
||||
// debug('findPointIndexInPaths: ', toString(point), toString(paths));
|
||||
for (let i = 0; i < paths.length; i++) {
|
||||
const path = paths[i];
|
||||
// find matching endpoints
|
||||
const index = findPointIndex(path, point);
|
||||
// debug(` ${i}: index: `, index);
|
||||
// if found stop searching
|
||||
if (index > -1) return [i, index];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
export const findEndPointIndexInPaths = R.curry(
|
||||
(point, paths) => findPointIndexInPaths(point, getEndPointPaths(paths))
|
||||
);
|
||||
|
||||
// find indexes of matching points of path inside other path
|
||||
// returns first result
|
||||
// returns array with
|
||||
// - index of path with matching point
|
||||
// - array of matching indexes (see findPointsIndexes)
|
||||
export function findPointsIndexesOfPathInPaths(paths, path) {
|
||||
// console.log('findPointsIndexesOfPathInPaths');
|
||||
// console.log(' paths: ', toString(paths));
|
||||
// console.log(' path: ', toString(path));
|
||||
for (let i = 0; i < paths.length; i++) {
|
||||
const otherPath = paths[i];
|
||||
// skip current path
|
||||
if (otherPath === path) continue;
|
||||
// find matching endpoints
|
||||
const indexes = findPointsIndexes(path, otherPath);
|
||||
// console.log(` ${i}: indexes: `, indexes);
|
||||
// found any matching indexes?
|
||||
// indexes contains any item that's larget than -1
|
||||
const foundMatch = R.any(R.lt(-1))(indexes);
|
||||
// if found stop searching
|
||||
// return index of matching path and indexes of machting end points
|
||||
if (foundMatch) return [i, indexes];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// find indexes of matching end points of path inside other path
|
||||
// see: findPointsIndexesOfPathInPaths
|
||||
export function findEndPointsIndexesOfPathInPaths(paths, path) {
|
||||
return findPointsIndexesOfPathInPaths(
|
||||
R.map(getEndPoints, paths),
|
||||
getEndPoints(path)
|
||||
);
|
||||
}
|
||||
|
||||
// cross-compare points of multiple paths
|
||||
// returns first match
|
||||
// array with
|
||||
// - index of path A with matching point
|
||||
// - index of path B with matching point
|
||||
// - array of matching indexes (see findPointsIndexes)
|
||||
export function findPointIndexesOfPaths(paths) {
|
||||
// console.log('findPointIndexesOfPaths');
|
||||
for (let i = 0; i < paths.length; i++) {
|
||||
const path = paths[i];
|
||||
const indexes = findPointsIndexesOfPathInPaths(paths, path);
|
||||
// console.log(' indexes: ', toString(indexes));
|
||||
if (indexes !== null) return [i, ...indexes];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// cross-compare endpoints of multiple paths
|
||||
export function findEndPointIndexesOfPaths(paths) {
|
||||
return findPointIndexesOfPaths(R.map(getEndPoints, paths));
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import update from 'react-addons-update';
|
||||
import * as actions from '../actions/index.js';
|
||||
import { Vector } from 'cal';
|
||||
import { shapeToPoints } from '../utils/shapeDataUtils.js';
|
||||
import { shapeToPoints } from '../shape/shapeDataUtils.js';
|
||||
import createDebug from 'debug';
|
||||
const debug = createDebug('d3d:reducer:selection');
|
||||
|
||||
|
67
src/utils/objectSelectors.js
Normal file
67
src/utils/objectSelectors.js
Normal file
@ -0,0 +1,67 @@
|
||||
import { SHAPE_TYPE_PROPERTIES } from 'src/js/constants/shapeTypeProperties.js';
|
||||
import { calculatePointInImage } from 'src/js/utils/matrixUtils.js';
|
||||
import R from 'ramda';
|
||||
// import createDebug from 'debug';
|
||||
// const debug = createDebug('d3d:utils:objectSelectors');
|
||||
|
||||
// returns true if object is a closed shape
|
||||
export function closedShapesFilter({ points }) {
|
||||
return points[0].equals(points[points.length - 1]);
|
||||
}
|
||||
// returns true if object is a open (not closed) shape
|
||||
export function openShapesFilter(object) {
|
||||
return !closedShapesFilter(object);
|
||||
}
|
||||
// returns true if object should snap
|
||||
export function snappingFilter({ type }) {
|
||||
return SHAPE_TYPE_PROPERTIES[type].snapping;
|
||||
}
|
||||
|
||||
export function getObjectsById(state) {
|
||||
return state.sketcher.present.objectsById;
|
||||
}
|
||||
|
||||
export function contains(state, testFn) {
|
||||
const objects = R.values(getObjectsById(state));
|
||||
const index = R.findIndex(testFn, objects);
|
||||
return (index !== -1);
|
||||
}
|
||||
|
||||
export function containsType(state, type) {
|
||||
return contains(state, R.propEq('type', type));
|
||||
}
|
||||
|
||||
export function getSnappingPoints(state, matrix) {
|
||||
return Object.values(state.objectsById)
|
||||
.filter(snappingFilter) // filter closed shapes
|
||||
.filter(openShapesFilter)
|
||||
.map(shapeData => {
|
||||
const transform = matrix ? shapeData.transform.multiplyMatrix(matrix) : shapeData.transform;
|
||||
const startPoint = shapeData.points[0].applyMatrix(transform);
|
||||
const endPoint = shapeData.points[shapeData.points.length - 1].applyMatrix(transform);
|
||||
|
||||
return { shapeData, startPoint, endPoint };
|
||||
});
|
||||
}
|
||||
export function getObjectsFromIds(state, ids) {
|
||||
return ids.map(id => state.objectsById[id]);
|
||||
}
|
||||
export function filterType(objects, type) {
|
||||
return objects.filter(value => value.type === type);
|
||||
}
|
||||
export function getFirst(objects) {
|
||||
return objects.length > 0 ? objects[0] : null;
|
||||
}
|
||||
export function getColor(shapeData, position, screenMatrixZoom) {
|
||||
if (!shapeData) return null;
|
||||
|
||||
const canvas = shapeData.imageData;
|
||||
const context = canvas.getContext('2d');
|
||||
|
||||
const start = calculatePointInImage(position, shapeData, screenMatrixZoom);
|
||||
|
||||
const [r, g, b] = context.getImageData(start.x, start.y, 1, 1).data;
|
||||
const color = (r << 16) + (g << 8) + b;
|
||||
|
||||
return color;
|
||||
}
|
Loading…
Reference in New Issue
Block a user