fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
147 lines (146 loc) • 4.67 kB
JavaScript
import { _defineProperty } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/defineProperty.mjs";
import { config } from "../config.mjs";
import { log } from "../util/internals/console.mjs";
import { classRegistry } from "../ClassRegistry.mjs";
import { uid } from "../util/internals/uid.mjs";
import { loadImage } from "../util/misc/objectEnlive.mjs";
import { pick } from "../util/misc/pick.mjs";
import { toFixed } from "../util/misc/toFixed.mjs";
import { escapeXml } from "../util/lang_string.mjs";
import { ifNaN } from "../util/internals/ifNaN.mjs";
//#region src/Pattern/Pattern.ts
/**
* @see {@link http://fabric5.fabricjs.com/patterns demo}
* @see {@link http://fabric5.fabricjs.com/dynamic-patterns demo}
*/
var Pattern = class {
/**
* Legacy identifier of the class. Prefer using this.constructor.type 'Pattern'
* or utils like isPattern, or instance of to indentify a pattern in your code.
* Will be removed in future versiones
* @TODO add sustainable warning message
* @type string
* @deprecated
*/
get type() {
return "pattern";
}
set type(value) {
log("warn", "Setting type has no effect", value);
}
/**
* Constructor
* @param {Object} [options] Options object
* @param {option.source} [source] the pattern source, eventually empty or a drawable
*/
constructor(options) {
_defineProperty(
this,
/**
* @type PatternRepeat
* @defaults
*/
"repeat",
"repeat"
);
_defineProperty(
this,
/**
* Pattern horizontal offset from object's left/top corner
* @type Number
*/
"offsetX",
0
);
_defineProperty(
this,
/**
* Pattern vertical offset from object's left/top corner
* @type Number
*/
"offsetY",
0
);
_defineProperty(
this,
/**
* @type TCrossOrigin
*/
"crossOrigin",
""
);
this.id = uid();
Object.assign(this, options);
}
/**
* @returns true if {@link source} is an <img> element
*/
isImageSource() {
return !!this.source && typeof this.source.src === "string";
}
/**
* @returns true if {@link source} is a <canvas> element
*/
isCanvasSource() {
return !!this.source && !!this.source.toDataURL;
}
sourceToString() {
return this.isImageSource() ? this.source.src : this.isCanvasSource() ? this.source.toDataURL() : "";
}
/**
* Returns an instance of CanvasPattern
* @param {CanvasRenderingContext2D} ctx Context to create pattern
* @return {CanvasPattern}
*/
toLive(ctx) {
if (!this.source || this.isImageSource() && (!this.source.complete || this.source.naturalWidth === 0 || this.source.naturalHeight === 0)) return null;
return ctx.createPattern(this.source, this.repeat);
}
/**
* Returns object representation of a pattern
* @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
* @return {object} Object representation of a pattern instance
*/
toObject(propertiesToInclude = []) {
const { repeat, crossOrigin } = this;
return {
...pick(this, propertiesToInclude),
type: "pattern",
source: this.sourceToString(),
repeat,
crossOrigin,
offsetX: toFixed(this.offsetX, config.NUM_FRACTION_DIGITS),
offsetY: toFixed(this.offsetY, config.NUM_FRACTION_DIGITS),
patternTransform: this.patternTransform ? [...this.patternTransform] : null
};
}
/**
* Returns SVG representation of a pattern
*/
toSVG({ width, height }) {
const { source: patternSource, repeat, id } = this, patternOffsetX = ifNaN(this.offsetX / width, 0), patternOffsetY = ifNaN(this.offsetY / height, 0), patternWidth = repeat === "repeat-y" || repeat === "no-repeat" ? 1 + Math.abs(patternOffsetX || 0) : ifNaN(patternSource.width / width, 0), patternHeight = repeat === "repeat-x" || repeat === "no-repeat" ? 1 + Math.abs(patternOffsetY || 0) : ifNaN(patternSource.height / height, 0);
return [
`<pattern id="SVGID_${escapeXml(id)}" x="${patternOffsetX}" y="${patternOffsetY}" width="${patternWidth}" height="${patternHeight}">`,
`<image x="0" y="0" width="${patternSource.width}" height="${patternSource.height}" xlink:href="${escapeXml(this.sourceToString())}"></image>`,
`</pattern>`,
""
].join("\n");
}
static async fromObject({ type, source, patternTransform, ...otherOptions }, options) {
const img = await loadImage(source, {
...options,
crossOrigin: otherOptions.crossOrigin
});
return new this({
...otherOptions,
patternTransform: patternTransform && patternTransform.slice(0),
source: img
});
}
};
_defineProperty(Pattern, "type", "Pattern");
classRegistry.setClass(Pattern);
classRegistry.setClass(Pattern, "pattern");
//#endregion
export { Pattern };
//# sourceMappingURL=Pattern.mjs.map