mirror of
https://github.com/Doodle3D/Doodle3D-Core.git
synced 2024-12-22 11:03:48 +01:00
add shape and image shape
This commit is contained in:
parent
09f276e26c
commit
15dcddc3c3
43
src/d2/ImageShape.js
Normal file
43
src/d2/ImageShape.js
Normal file
@ -0,0 +1,43 @@
|
||||
import { IMAGE_GUIDE_TRANSPARENCY, DESELECT_TRANSPARENCY } from '../constants/d2Constants.js';
|
||||
import { Surface } from 'cal';
|
||||
|
||||
export default class ImageShape extends Surface {
|
||||
constructor(shapeData) {
|
||||
super();
|
||||
|
||||
this.depth = -1;
|
||||
this.UID = shapeData.UID;
|
||||
|
||||
this.update(shapeData);
|
||||
this.setOpaque(true);
|
||||
}
|
||||
update(newShapeData) {
|
||||
let changed;
|
||||
|
||||
if (!this._shapeData || this._shapeData.transform !== newShapeData.transform) {
|
||||
changed = true;
|
||||
this.copyMatrix(newShapeData.transform);
|
||||
}
|
||||
|
||||
if (!this._shapeData || this._shapeData.imageData !== newShapeData.imageData) {
|
||||
changed = true;
|
||||
|
||||
const newImage = newShapeData.imageData;
|
||||
const image = this._shapeData ? this._shapeData.imageData : {};
|
||||
|
||||
if (newImage.width !== image.width || newImage.height !== image.height) {
|
||||
this.setSize(newImage.width, newImage.height);
|
||||
this.centerX = newImage.width / 2;
|
||||
this.centerY = newImage.height / 2;
|
||||
}
|
||||
|
||||
this.context.drawImage(newImage, 0, 0, newImage.width, newImage.height);
|
||||
}
|
||||
|
||||
this._shapeData = newShapeData;
|
||||
return changed;
|
||||
}
|
||||
setOpaque(opaque) {
|
||||
this.alpha = opaque ? IMAGE_GUIDE_TRANSPARENCY : DESELECT_TRANSPARENCY;
|
||||
}
|
||||
}
|
119
src/d2/Shape.js
Normal file
119
src/d2/Shape.js
Normal file
@ -0,0 +1,119 @@
|
||||
import { shapeToPoints } from '../shape/shapeToPoints.js';
|
||||
import { shapeChanged } from '../shape/shapeDataUtils.js';
|
||||
import { Matrix } from 'cal';
|
||||
import { LINE_WIDTH } from '../constants/d2Constants.js';
|
||||
import { hexToStyle } from '../utils/colorUtils.js';
|
||||
import { DESELECT_TRANSPARENCY, FILL_TRANSPARENCY, LINE_TRANSPARENCY } from '../constants/d2Constants.js';
|
||||
import { PIXEL_RATIO } from '../constants/general.js';
|
||||
|
||||
export default class Shape extends Matrix {
|
||||
constructor(shapeData) {
|
||||
super();
|
||||
|
||||
this.visible = true;
|
||||
this.active = false;
|
||||
this.depth = shapeData.height + shapeData.z;
|
||||
|
||||
this.color = '';
|
||||
|
||||
this.UID = shapeData.UID;
|
||||
|
||||
this.update(shapeData);
|
||||
this.setOpaque(true);
|
||||
}
|
||||
update(shapeData) {
|
||||
let changed = false;
|
||||
|
||||
this.depth = shapeData.height + shapeData.z;
|
||||
|
||||
if (!this._shapeData || shapeChanged(shapeData, this._shapeData)) {
|
||||
this.shapes = shapeToPoints(shapeData);
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (!this._shapeData || this._shapeData.transform !== shapeData.transform) {
|
||||
if (shapeData.transform.matrix.some(value => typeof value !== 'number' || isNaN(value))) {
|
||||
throw new Error(`Cannot update object ${this.UID}: transform contains invalid values.`);
|
||||
}
|
||||
|
||||
this.copyMatrix(shapeData.transform);
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (!this._shapeData || this._shapeData.color !== shapeData.color) {
|
||||
if (typeof shapeData.color !== 'number' || isNaN(shapeData.color)) {
|
||||
throw new Error(`Cannot update object ${this.UID}: color is an invalid value.`);
|
||||
}
|
||||
this.color = hexToStyle(shapeData.color);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
this._shapeData = shapeData;
|
||||
return changed;
|
||||
}
|
||||
setOpaque(opaque) {
|
||||
const selectTransparency = this._shapeData.fill ? FILL_TRANSPARENCY : LINE_TRANSPARENCY;
|
||||
this.alpha = opaque ? selectTransparency : DESELECT_TRANSPARENCY;
|
||||
}
|
||||
draw(context, matrix) {
|
||||
context.beginPath();
|
||||
|
||||
for (let i = 0; i < this.shapes.length; i ++) {
|
||||
const { points, holes } = this.shapes[i];
|
||||
|
||||
for (let j = 0; j < points.length; j ++) {
|
||||
const point = points[j].applyMatrix(matrix);
|
||||
|
||||
if (j === 0) {
|
||||
context.moveTo(point.x, point.y);
|
||||
} else {
|
||||
context.lineTo(point.x, point.y);
|
||||
}
|
||||
}
|
||||
|
||||
for (let j = 0; j < holes.length; j ++) {
|
||||
const hole = holes[j];
|
||||
|
||||
for (let k = 0; k < hole.length; k ++) {
|
||||
const point = hole[k].applyMatrix(matrix);
|
||||
|
||||
if (k === 0) {
|
||||
context.moveTo(point.x, point.y);
|
||||
} else {
|
||||
context.lineTo(point.x, point.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.lineCap = 'round';
|
||||
context.lineJoin = 'round';
|
||||
|
||||
const lineWidth = PIXEL_RATIO * LINE_WIDTH;
|
||||
|
||||
context.globalAlpha = this.alpha;
|
||||
if (this._shapeData.fill) {
|
||||
context.fillStyle = this.color;
|
||||
context.fill();
|
||||
|
||||
context.strokeStyle = 'black';
|
||||
context.lineWidth = lineWidth / 2.0;
|
||||
context.stroke();
|
||||
} else {
|
||||
const outerLineWidth = lineWidth * this.parent.sx;
|
||||
const innerLineWidth = outerLineWidth - lineWidth;
|
||||
|
||||
context.strokeStyle = 'black';
|
||||
context.lineWidth = outerLineWidth;
|
||||
context.stroke();
|
||||
|
||||
if (innerLineWidth > 0) {
|
||||
context.strokeStyle = this.color;
|
||||
context.lineWidth = innerLineWidth;
|
||||
context.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
import memoize from 'memoizee';
|
||||
import { Vector } from '@doodle3d/cal';
|
||||
import { SHAPE_CACHE_LIMIT } from '../constants/general.js';
|
||||
import ImageShape from '../d2/ImageShape.js';
|
||||
import Shape from '../d2/Shape.js';
|
||||
|
||||
export function shapeChanged(oldShapeData, newShapeData) {
|
||||
const pointsChanged = oldShapeData.points !== newShapeData.points;
|
||||
|
Loading…
Reference in New Issue
Block a user