@evoke-ui/zsort3d
Version:
TypeScript z-plane rendering engine with 3D depth simulation using Canvas 2D and mouse-based navigation
137 lines • 4.91 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Z3DSVG = void 0;
const Z3DSortable_1 = require("../core/Z3DSortable");
class Z3DSVG extends Z3DSortable_1.Z3DSortable {
constructor(svgContent, width = 50, height = 50, title = '', url = '') {
super();
this.svgElement = null;
this.containerElement = null;
this.cachedImage = null;
this.svgContent = svgContent || Z3DSVG.DEFAULT_SVG;
this.width = width;
this.height = height;
this.title = title;
this.url = url;
this.instanceId = `z3dsvg-${Math.random().toString(36).substr(2, 9)}`;
this.createSVGElement();
}
createSVGElement() {
const parser = new DOMParser();
const doc = parser.parseFromString(this.svgContent, 'image/svg+xml');
this.svgElement = doc.documentElement;
if (this.svgElement) {
this.updateSVGTransform();
}
this.createCachedImage();
}
createCachedImage() {
const cacheKey = btoa(this.svgContent);
if (Z3DSVG.imageCache.has(cacheKey)) {
this.cachedImage = Z3DSVG.imageCache.get(cacheKey);
return;
}
const img = new Image();
const svgDataUrl = `data:image/svg+xml;base64,${cacheKey}`;
img.onload = () => {
Z3DSVG.imageCache.set(cacheKey, img);
this.cachedImage = img;
};
img.src = svgDataUrl;
}
updateSVGTransform() {
if (!this.svgElement)
return;
this.svgElement.style.position = 'absolute';
this.svgElement.style.left = `${this.x - (this.width * this.scaleX) / 2}px`;
this.svgElement.style.top = `${this.y - (this.height * this.scaleY) / 2}px`;
this.svgElement.style.transform = `scale(${this.scaleX}, ${this.scaleY})`;
this.svgElement.style.opacity = this.alpha.toString();
this.svgElement.style.transformOrigin = 'center center';
}
render(ctx) {
if (!this.cachedImage)
return;
const scaledWidth = this.width * this.scaleX;
const scaledHeight = this.height * this.scaleY;
ctx.save();
ctx.globalAlpha = this.alpha;
ctx.drawImage(this.cachedImage, this.x - scaledWidth / 2, this.y - scaledHeight / 2, scaledWidth, scaledHeight);
ctx.restore();
}
setSVGContent(svgContent) {
this.svgContent = svgContent;
this.createSVGElement();
}
getSVGContent() {
return this.svgContent;
}
getInstanceId() {
return this.instanceId;
}
addEventListener(canvas, handler) {
this.clickHandler = (e) => {
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
const scaledWidth = this.width * this.scaleX;
const scaledHeight = this.height * this.scaleY;
const left = this.x - scaledWidth / 2;
const top = this.y - scaledHeight / 2;
if (mouseX >= left && mouseX <= left + scaledWidth &&
mouseY >= top && mouseY <= top + scaledHeight) {
handler(e);
}
};
canvas.addEventListener('click', this.clickHandler);
}
removeEventListener(canvas) {
if (this.clickHandler) {
canvas.removeEventListener('click', this.clickHandler);
this.clickHandler = undefined;
}
}
addTouchEventListener(handler) {
this.touchHandler = handler;
}
removeTouchEventListener() {
this.touchHandler = undefined;
}
checkTouchHit(touchData) {
if (!touchData.center)
return false;
const touchX = touchData.center.x;
const touchY = touchData.center.y;
const scaledWidth = this.width * this.scaleX;
const scaledHeight = this.height * this.scaleY;
const left = this.x - scaledWidth / 2;
const top = this.y - scaledHeight / 2;
return touchX >= left && touchX <= left + scaledWidth &&
touchY >= top && touchY <= top + scaledHeight;
}
handleTouchEvent(data) {
if (!this.touchHandler || !this.checkTouchHit(data)) {
return false;
}
this.touchHandler(data);
return true;
}
getTouchHandler() {
return this.touchHandler;
}
destroy() {
super.destroy();
this.svgElement = null;
this.containerElement = null;
this.clickHandler = undefined;
this.touchHandler = undefined;
}
}
exports.Z3DSVG = Z3DSVG;
Z3DSVG.imageCache = new Map();
Z3DSVG.DEFAULT_SVG = `
<svg width="50" height="50" xmlns="http://www.w3.org/2000/svg">
<circle cx="25" cy="25" r="20" fill="#FF6B6B" stroke="#333" stroke-width="2"/>
</svg>
`;
//# sourceMappingURL=Z3DSVG.js.map