@infinite-canvas-tutorial/webcomponents
Version:
WebComponents UI implementation
327 lines • 13.5 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { v4 as uuidv4 } from 'uuid';
import { consume } from '@lit/context';
import { html, css, LitElement } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { apiContext, appStateContext } from '../context';
var ImageEditMode;
(function (ImageEditMode) {
ImageEditMode["IDLE"] = "idle";
ImageEditMode["POINT_SEGMENT"] = "point-segment";
})(ImageEditMode || (ImageEditMode = {}));
let ContextImageEditBar = class ContextImageEditBar extends LitElement {
constructor() {
super(...arguments);
this.binded = false;
this.mode = ImageEditMode.IDLE;
}
shouldUpdate(changedProperties) {
var _a;
for (const prop of changedProperties.keys()) {
if (prop !== 'appState')
return true;
}
const newEditingPoints = this.appState.editingPoints;
if (newEditingPoints !== this.previouseEditingPoints) {
this.previouseEditingPoints = newEditingPoints;
if (this.mode === ImageEditMode.POINT_SEGMENT) {
this.segmentWithPoints(newEditingPoints);
}
if (newEditingPoints.length === 0) {
(_a = this.maskCanvas) === null || _a === void 0 ? void 0 : _a.remove();
this.maskCanvas = undefined;
}
return true;
}
return false;
}
removeBackground() {
return __awaiter(this, void 0, void 0, function* () {
this.removingBackground = true;
// 先创建一个空白元素
let newImage;
this.api.runAtNextTick(() => {
newImage = {
id: uuidv4(),
type: 'rect',
fill: this.node.fill,
lockAspectRatio: true,
x: this.node.x + this.node.width + 50,
y: this.node.y,
width: this.node.width,
height: this.node.height,
zIndex: 0,
};
this.api.updateNode(newImage);
});
const { images } = yield this.api.createOrEditImage(true, 'Remove background from the image', [this.node.fill]);
if (images.length > 0) {
this.api.runAtNextTick(() => {
this.api.updateNode(newImage, { fill: images[0].url });
this.api.record();
this.removingBackground = false;
});
}
});
}
startSmartSelect() {
return __awaiter(this, void 0, void 0, function* () {
this.encodingImage = true;
yield this.api.encodeImage(this.node.fill);
this.mode = ImageEditMode.POINT_SEGMENT;
this.encodingImage = false;
});
}
segmentWithPoints(points) {
return __awaiter(this, void 0, void 0, function* () {
if (points.length === 0) {
return;
}
// convert points in canvas coordinages to local coordinates
const selectedNode = this.api.getNodeById(this.api.getAppState().layersSelected[0]);
const point = points[0];
const { x, y } = this.api.viewport2Canvas({ x: point[0], y: point[1] });
if (this.maskCanvas) {
this.maskCanvas.remove();
}
const { image } = yield this.api.segmentImage({
image_url: '',
point_prompts: [
{
x: x - selectedNode.x,
y: y - selectedNode.y,
label: 1,
},
],
});
this.maskCanvas = image.canvas;
this.maskCanvas.style.position = 'absolute';
this.maskCanvas.style.left = `${selectedNode.x}px`;
this.maskCanvas.style.top = `${selectedNode.y}px`;
this.maskCanvas.style.width = `${selectedNode.width}px`;
this.maskCanvas.style.height = `${selectedNode.height}px`;
this.maskCanvas.style.pointerEvents = 'none';
this.api.getHtmlLayer().appendChild(this.maskCanvas);
});
}
removeByMask() {
return __awaiter(this, void 0, void 0, function* () {
this.removingByMask = true;
// convert points in canvas coordinages to local coordinates
const selectedNode = this.api.getNodeById(this.api.getAppState().layersSelected[0]);
yield this.api.removeByMask({
image_url: selectedNode.fill,
mask: this.maskCanvas,
});
this.removingByMask = false;
});
}
decomposeImage() {
return __awaiter(this, void 0, void 0, function* () {
this.decomposingImage = true;
// const { images } = await this.api.decomposeImage({
// image_url: this.node.fill,
// });
const images = [
{
url: 'https://v3b.fal.media/files/b/0a86d42c/7T3zJKciQ1cCzqR3ADLif.png',
},
{
url: 'https://v3b.fal.media/files/b/0a86d42c/KVt5pIhe2dU-qZNC2Njo2.png',
},
{
url: 'https://v3b.fal.media/files/b/0a86d42c/3BMMGMaHyA3Y7Q_kamIJ_.png',
},
{
url: 'https://v3b.fal.media/files/b/0a86d42c/AY1BjZxhqS1jl-Pw2S1Tx.png',
},
];
if (images.length > 0) {
this.api.runAtNextTick(() => {
for (const image of images) {
const newImage = {
id: uuidv4(),
type: 'rect',
fill: image.url,
lockAspectRatio: true,
x: this.node.x + this.node.width + 50,
y: this.node.y,
width: this.node.width,
height: this.node.height,
};
this.api.updateNode(newImage, { fill: image.url });
}
this.api.record();
});
}
this.decomposingImage = false;
this.mode = ImageEditMode.IDLE;
});
}
upscaleImage() {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b;
this.upscalingImage = true;
const selectedNode = this.api.getNodeById(this.api.getAppState().layersSelected[0]);
const image = yield this.api.upscaleImage({
image_url: selectedNode.fill,
});
const url = (_a = image.url) !== null && _a !== void 0 ? _a : (_b = image.canvas) === null || _b === void 0 ? void 0 : _b.toDataURL();
this.api.runAtNextTick(() => {
const newImage = {
id: uuidv4(),
type: 'rect',
fill: url,
lockAspectRatio: true,
x: this.node.x + this.node.width + 50,
y: this.node.y,
width: this.node.width,
height: this.node.height,
};
this.api.updateNode(newImage, { fill: url });
this.api.record();
});
this.upscalingImage = false;
});
}
render() {
if (!this.api) {
return;
}
// FIXME: wait for the element to be ready.
if (this.api.element && !this.binded) {
this.binded = true;
}
if (this.mode === ImageEditMode.POINT_SEGMENT) {
return html `<sp-action-button
quiet
size="m"
?disabled="${!this.maskCanvas}"
?loading="${this.removingByMask}"
="${this.removeByMask}"
>
<sp-tooltip self-managed placement="bottom">Remove</sp-tooltip>
<sp-icon-delete slot="icon"></sp-icon-delete>
</sp-action-button>`;
}
return html `<sp-action-button
quiet
size="m"
?disabled="${this.removingBackground}"
="${this.removeBackground}"
>
<sp-tooltip self-managed placement="bottom">
Remove background
</sp-tooltip>
<sp-icon>
<svg
role="img"
fill="currentColor"
viewBox="0 0 20 20"
id="-icon"
width="16"
height="16"
aria-hidden="true"
aria-label=""
focusable="false"
>
<rect x="2" y="4" width="4" height="4" opacity=".35"></rect>
<polygon
points="10 12 9.30741 12 6 9 6 8 10 8 10 12"
opacity=".35"
></polygon>
<rect x="10" y="4" width="4" height="4" opacity=".35"></rect>
<rect x="14" y="8" width="4" height="4" opacity=".35"></rect>
<polygon
points="14 12.28454 10 13.45999 10 12 14 12 14 12.28454"
opacity=".35"
></polygon>
<path
d="m14.5,7.52114c0,.82843-.67157,1.5-1.5,1.5-.82843,0-1.5-.67157-1.5-1.5,0-.82843.67157-1.5,1.5-1.5s1.5.67157,1.5,1.5h0"
></path>
<path
d="m16.75,3H3.25c-1.24072,0-2.25,1.00977-2.25,2.25v9.5c0,1.24023,1.00928,2.25,2.25,2.25h13.5c1.24072,0,2.25-1.00977,2.25-2.25V5.25c0-1.24023-1.00928-2.25-2.25-2.25Zm-13.5,1.5h13.5c.41357,0,.75.33691.75.75v8.21069l-1.90869-1.90894c-.84961-.84961-2.3335-.84961-3.18213,0l-1.23193,1.23145c-.09717.09766-.25684.09668-.354.00098l-3.23193-3.23242c-.84961-.84961-2.3335-.84961-3.18213,0l-1.90918,1.90918v-6.21094c0-.41309.33643-.75.75-.75Zm0,11c-.41357,0-.75-.33691-.75-.75v-1.16797l2.97021-2.96973c.28223-.2832.77686-.2832,1.06006,0l3.23291,3.2334c.68164.67969,1.7915.68262,2.47412-.00098l1.23291-1.23242c.28223-.2832.77686-.2832,1.06006,0l2.70074,2.70068c-.1311.11206-.29553.18701-.48102.18701H3.25Z"
></path>
</svg>
</sp-icon>
</sp-action-button>
<sp-action-button
quiet
size="m"
?disabled="${this.encodingImage}"
="${this.startSmartSelect}"
>
<sp-tooltip self-managed placement="bottom"> Smart select </sp-tooltip>
<sp-icon-polygon-select slot="icon"></sp-icon-polygon-select>
</sp-action-button>
<sp-action-button
quiet
size="m"
?disabled="${this.decomposingImage}"
="${this.decomposeImage}"
>
<sp-tooltip self-managed placement="bottom"> Decompose </sp-tooltip>
<sp-icon-layers slot="icon"></sp-icon-layers>
</sp-action-button>
<sp-action-button
quiet
size="m"
?disabled="${this.upscalingImage}"
="${this.upscaleImage}"
>
<sp-tooltip self-managed placement="bottom"> Upscale </sp-tooltip>
<sp-icon-image-auto-mode slot="icon"></sp-icon-image-auto-mode>
</sp-action-button> `;
}
};
ContextImageEditBar.styles = css `
:host {
display: flex;
}
`;
__decorate([
consume({ context: appStateContext, subscribe: true })
], ContextImageEditBar.prototype, "appState", void 0);
__decorate([
consume({ context: apiContext, subscribe: true })
], ContextImageEditBar.prototype, "api", void 0);
__decorate([
property()
], ContextImageEditBar.prototype, "node", void 0);
__decorate([
state()
], ContextImageEditBar.prototype, "removingBackground", void 0);
__decorate([
state()
], ContextImageEditBar.prototype, "encodingImage", void 0);
__decorate([
state()
], ContextImageEditBar.prototype, "removingByMask", void 0);
__decorate([
state()
], ContextImageEditBar.prototype, "decomposingImage", void 0);
__decorate([
state()
], ContextImageEditBar.prototype, "upscalingImage", void 0);
__decorate([
state()
], ContextImageEditBar.prototype, "maskCanvas", void 0);
ContextImageEditBar = __decorate([
customElement('ic-spectrum-context-image-edit-bar')
], ContextImageEditBar);
export { ContextImageEditBar };
//# sourceMappingURL=context-image-edit-bar.js.map