import { constructors, canvas, cell, group, artefact } from '../core/library.js';
import { mergeOver, isa_obj, λthis, λnull } from '../core/utilities.js';
import baseMix from '../mixin/base.js';
import assetMix from '../mixin/asset.js';The factory generates wrapper Objects around <img> elements which can either be pulled from the current document (DOM-based assets), or fetched from the server using an URL address.
Image-based assets can also be created from entity artefacts, groups of entity artefacts, and Cell wrappers
ImageAssets are used by Picture and Grid entitys, and Pattern styles.
TODO: ImageAssets don’t support animated .gif images (or if they do, then its entirely a lucky accident). Tested image formats are .jpg and .png.
import { constructors, canvas, cell, group, artefact } from '../core/library.js';
import { mergeOver, isa_obj, λthis, λnull } from '../core/utilities.js';
import baseMix from '../mixin/base.js';
import assetMix from '../mixin/asset.js';const ImageAsset = function (items = {}) {
return this.assetConstructor(items);
};let P = ImageAsset.prototype = Object.create(Object.prototype);
P.type = 'Image';
P.lib = 'asset';
P.isArtefact = false;
P.isAsset = true;P = baseMix(P);
P = assetMix(P);let defaultAttributes = {intrinsicDimensions - Javascript object which defines the intrinsic dimensions of each image contributing to an <img> element’s srcset attribute. Can also be set in Javascript code:
filename-String: [width-Number, height-Number]
{
'river-300.jpg': [300, 225],
'river-600.jpg': [600, 450],
'river-900.jpg': [900, 675]
}
intrinsicDimensions: null,
};
P.defs = mergeOver(P.defs, defaultAttributes);Assets do not take part in the packet or clone systems; they can, however, be used for importing and actioning packets as they retain those base functions
P.saveAsPacket = function () {
return [this.name, this.type, this.lib, {}];
};
P.stringifyFunction = λnull;
P.processPacketOut = λnull;
P.finalizePacketOut = λnull;P.clone = λthis;let G = P.getters,
S = P.setters,
D = P.deltaSetters;source
S.source = function (item = {}) {
if (item) {For <img> and <picture> elements
if (['IMG', 'PICTURE'].indexOf(item.tagName.toUpperCase()) >= 0) {
this.source = item;
this.sourceNaturalWidth = item.naturalWidth;
this.sourceNaturalHeight = item.naturalHeight;
this.sourceLoaded = item.complete;
}
if (this.sourceLoaded) this.notifySubscribers();
}
};currentSrc - this attribute is not part of the defs object
S.currentSrc = function (item) {
this.currentSrc = item;
this.currentFile = this.currentSrc.split("/").pop();
};checkSource
P.checkSource = function (width, height) {
let el = this.source,
action = 'element';
if (this.sourceLoaded) {
let iDims = this.intrinsicDimensions[this.currentFile];
if (this.currentSrc !== el.currentSrc) {
this.set({
currentSrc: el.currentSrc
});
iDims = this.intrinsicDimensions[this.currentFile];
if (iDims) action = 'intrinsic';
else action = 'zero';
}
else if (iDims) action = 'intrinsic';
switch (action) {
case 'zero' :
this.sourceNaturalWidth = 0;
this.sourceNaturalHeight = 0;
this.notifySubscribers();
break;
case 'intrinsic' :
if (this.sourceNaturalWidth !== iDims[0] ||
this.sourceNaturalHeight !== iDims[1]) {
this.sourceNaturalWidth = iDims[0];
this.sourceNaturalHeight = iDims[1];
this.notifySubscribers();
}
break;
default:
if (this.sourceNaturalWidth !== el.naturalWidth ||
this.sourceNaturalHeight !== el.naturalHeight ||
this.sourceNaturalWidth !== width ||
this.sourceNaturalHeight !== height) {
this.sourceNaturalWidth = el.naturalWidth;
this.sourceNaturalHeight = el.naturalHeight;
this.notifySubscribers();
}
};
}
};gettableImageAssetAtributes, settableImageAssetAtributes - exported Arrays.
const gettableImageAssetAtributes = [];
const settableImageAssetAtributes = [];importImage - load images from a remote server and create assets from them
Arguments can be a comma-separated list of String urls. For example, for aimage file at server url http://www.example.com/path/to/image/flower.jpg:
Alternatively, the arguments can include an object with the following attributes:
Note: strings and object arguments can be mixed - Scrawl-canvas will interrrogate each argument in turn and take appropriate action to load the assets.
const importImage = function (...args) {
let reg = /.*\/(.*?)\./,
results = [];
args.forEach(item => {
let name, url, className, visibility,
parent = false;
let flag = false;
if (item.substring) {
let match = reg.exec(item);
name = (match && match[1]) ? match[1] : '';
url = item;
className = '';
visibility = false;
flag = true;
}
else {
item = (isa_obj(item)) ? item : false;
if (item && item.src) {
name = item.name || '';
url = item.src;
className = item.className || '';
visibility = item.visibility || false;
if (item.parent) parent = document.querySelector(item.parent);
flag = true;
}
}
if (flag) {
let image = makeImageAsset({
name: name,
intrinsicDimensions: {},
});
let img = document.createElement('img');
img.name = name;
img.className = className;
img.crossorigin = 'anonymous';
img.style.display = (visibility) ? 'block' : 'none';
if (parent) parent.appendChild(img);
img.onload = () => {
image.set({
source: img,
});
};
img.src = url;
image.set({
source: img,
});
results.push(name);
}
else results.push(false);
});
return results;
};importDomImage - import images defined in the web page HTML code
display: none;, opacity: 0;, etc.const importDomImage = function (query) {
let reg = /.*\/(.*?)\./;
let items = document.querySelectorAll(query);
items.forEach(item => {
let name;
if (['IMG', 'PICTURE'].indexOf(item.tagName.toUpperCase()) >= 0) {
if (item.id || item.name) name = item.id || item.name;
else {
let match = reg.exec(item.src);
name = (match && match[1]) ? match[1] : '';
}
let intrinsics = item.dataset.dimensions || {};
if (intrinsics.substring) intrinsics = JSON.parse(intrinsics);
let image = makeImageAsset({
name: name,
source: item,
intrinsicDimensions: intrinsics,
currentSrc: item.currentSrc,
});
item.onload = () => {
image.set({
source: item,
});
};
}
});
};We can get cells, groups and entitys to save their output as imagedata, which we can then use to build an asset which in turn can be used by Picture entitys and pattern styles
createImageFromCell
const createImageFromCell = function (item, stashAsAsset = false) {
let mycell = (item.substring) ? cell[item] || canvas[item] : item;
if (mycell.type === 'Canvas') mycell = mycell.base;
if (mycell.type === 'Cell') {
mycell.stashOutput = true;
if (stashAsAsset) mycell.stashOutputAsAsset = true;
}
};createImageFromGroup
const createImageFromGroup = function (item, stashAsAsset = false) {
let mygroup;
if (item && !item.substring) {
if (item.type === 'Group') mygroup = item;
else if (item.type === 'Cell') mygroup = group[item.name];
else if (item.type === 'Canvas') mygroup = group[item.base.name];
}
else if (item && item.substring) mygroup = group[item];
if (mygroup) {
mygroup.stashOutput = true;
if (stashAsAsset) mygroup.stashOutputAsAsset = true;
}
};createImageFromEntity
const createImageFromEntity = function (item, stashAsAsset = false) {
let myentity = (item.substring) ? artefact[item] : item;
if (myentity.isArtefact) {
myentity.stashOutput = true;
if (stashAsAsset) myentity.stashOutputAsAsset = true;
}
};const makeImageAsset = function (items) {
return new ImageAsset(items);
};
constructors.ImageAsset = ImageAsset;export {
makeImageAsset,
gettableImageAssetAtributes,
settableImageAssetAtributes,
importImage,
importDomImage,
createImageFromCell,
createImageFromGroup,
createImageFromEntity,
};